Belajar Hermes JS Engine - Secure Runtime Practices
Episode 12 of 23

Belajar Hermes JS Engine - Secure Runtime Practices

Episode ini masuk ke Fase 4 tentang keamanan runtime: cara memuat bundel JavaScript Hermes dengan aman, menghindari remote code execution dan eval yang tidak aman, serta mitigasi praktis untuk aplikasi mobile dan edge runtime.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 11 kita menutup Fase 3 dengan menata konfigurasi Hermes supaya build reproducible, tervalidasi di CI, dan terintegrasi dengan release pipeline. Sekarang kita memasuki Fase 4: Networking & Security. Kalau performa itu soal kecepatan, keamanan itu soal apa yang terjadi kalau aplikasi kalian sudah sampai di tangan orang yang tidak berniat baik.

Episode 12 berfokus pada secure runtime practices: bagaimana bundel JavaScript Hermes kalian dimuat dengan aman, bagaimana menghindari remote code execution dan eval yang tidak aman, lalu contoh mitigasi nyata untuk aplikasi mobile dan edge runtime. Roadmap-nya: model ancaman, secure loading, menghindari RCE, mitigasi di mobile, lalu mitigasi di edge.

Mengapa Bundel JavaScript Perlu Diamankan

Hermes mengeksekusi bundel yang dikompilasi menjadi bytecode .hbc. Penting dipahami sejak awal: bytecode Hermes bukan enkripsi. File .hbc bisa dibongkar kembali menjadi disassembly menggunakan tool hbcdump, dan struktur internalnya sudah didokumentasikan. Yang melindungi aplikasi bukan "kerahasiaan" bytecode, melainkan integritas dan kontrol atas apa yang dieksekusi.

Model ancaman khas aplikasi mobile:

  • Tampering: seseorang membongkar APK/IPA, memodifikasi bundel, lalu menyebarkannya ulang sebagai "versi modifikasi".
  • MITM: bundel yang diunduh dari jaringan saat runtime bisa dicegat dan diganti di tengah jalan.
  • Injection: data dari luar (API, deep link, storage) disisipkan ke jalur yang akhirnya dieksekusi sebagai kode.

Info

Aturan emasnya: apa pun yang kalian kontrol (bundel, konfigurasi, native code) harus selalu diasumsikan bisa dibaca dan dianalisis penyerang. Keamanan datang dari verifikasi, bukan dari menyembunyikan kode.

Secure Loading Bundel JavaScript

Cara paling aman memuat bundel Hermes adalah memasangnya di dalam aset aplikasi saat build, bukan mengunduhnya dari server saat runtime. Di React Native, file index.android.bundle (yang di release build adalah bytecode .hbc) sudah otomatis dikemas ke dalam APK. Selama kalian tidak mengganti mekanisme ini, bundel ikut ditandatangani oleh tanda tangan aplikasi di toko aplikasi.

Kalau aplikasi kalian terpaksa mengambil bundel dari jaringan — misalnya untuk update over-the-air — jangan pernah percaya hasil unduhan mentah-mentah. Verifikasi terlebih dahulu dengan hash yang diketahui:

JSVerifikasi integritas bundel sebelum dieksekusi
import { checkBundleSignature } from "./crypto-utils";
 
const EXPECTED_SHA256 = "ab3f...0c9d";
 
async function loadRemoteBundle(url) {
  const bundle = await fetch(url).then((res) => res.arrayBuffer());
  const digest = await checkBundleSignature(bundle);
  if (digest !== EXPECTED_SHA256) {
    throw new Error("Integritas bundel gagal diverifikasi");
  }
  return bundle;
}

Hash statis seperti di atas hanya masuk akal untuk rilis yang dijadwalkan. Untuk update yang lebih sering, ganti mekanismenya dengan tanda tangan kriptografis: kunci publik disematkan di aplikasi, bundel ditandatangani kunci privat di sisi server, dan aplikasi memverifikasi tanda tangan tersebut. Selalu kombinasikan dengan HTTPS dan, bila memungkinkan, certificate pinning.

Menghindari Remote Code Execution dan eval yang Tidak Aman

Kabar baiknya: Hermes sejak awal tidak mendukung local eval. Memanggil eval di Hermes tidak akan memberi akses ke variabel lokal maupun mendefinisikan variabel baru di luar — perilakunya menyimpang dari spesifikasi dan di beberapa kasus langsung melempar error. Ini bukan bug, tapi keputusan desain yang sekaligus memperkecil permukaan serangan: tidak ada jalur eksekusi kode dinamis gratis.

Meski begitu, kalian tetap bisa menembak kaki sendiri. Pola berbahaya yang wajib dihindari: new Function, template string yang mengeksekusi kode, dan yang paling klasik — fetch lalu eval. Ini contoh buruknya:

JSPola berbahaya: mengeksekusi data dari jaringan
const config = await fetch("https://api.example.com/feature").then((r) => r.text());
const feature = new Function(config);
feature();

Dan ini pengganti yang aman — data tetap data, tidak pernah jadi kode:

JSPola aman: parse data, jangan eksekusi
const payload = await fetch("https://api.example.com/feature").then((r) => r.json());
 
const feature = {
  enabled: payload.enabled === true,
  label: String(payload.label ?? "fitur baru"),
};
const code = `return ${userInput};`;
const result = new Function(code)();

Perhatikan bahwa JSON.parse bukan pengganti seratus persen untuk semua kasus eval — ia hanya mem-parsing struktur data. Itu justru maksudnya: kalau yang kalian butuhkan hanyalah data, gunakan format data. Kalau kalian butuh logika, tulis logika tersebut sebagai fungsi sungguhan yang menerima input, bukan sebagai string yang dikompilasi saat itu juga.

Warning

Hati-hati juga dengan helper yang membungkus new Function untuk "menyusun query" atau "template engine". Di Hermes helper semacam itu sering pecah di device karena keterbatasan eval lokal — selain berbahaya secara keamanan, mereka juga tidak portabel.

Mitigasi di Aplikasi Mobile React Native

Berikut rangkaian minimum yang harus selalu aktif untuk build release mobile:

  • Pastikan Hermes aktif dan dev mode dimatikan di release — dev mode mengaktifkan inspector dan jalur debug yang tidak diperlukan di produksi.
  • Jangan menyertakan source map di dalam APK produksi. Gunakan source map untuk deobfuscation di backend crash reporting, bukan untuk dikirim ke perangkat.
  • Aktifkan R8/Proguard agar kode native Java/Kotlin di-minify, sehingga tidak membocorkan nama kelas dan method internal.
  • Jangan pernah meneruskan data yang tidak dipercaya ke dalam modul native yang mengeksekusi string (misalnya evalString yang disediakan beberapa modul debugging).

Flag kompiler di android/app/build.gradle juga bisa dikunci agar konsisten antar developer:

Kunci flag Hermes untuk build reproducibility
react {
  hermesFlags = ["-O", "-output-source-map"]
}

Dengan -output-source-map, stack trace produksi bisa dipetakan balik ke sumber asli — tapi pastikan file .map hasilnya disimpan di CI untuk digunakan tool observability, bukan dibundle.

Mitigasi di Edge Runtime

Di edge runtime (serverless, Cloudflare Workers, atau embedded Hermes di Node.js), prinsipnya sama, tapi ancamannya bergeser: kini yang tidak dipercaya adalah input request, bukan bundel. Pikiran pertama yang harus muncul: kode yang dieksekusi adalah kode milik kalian, sedangkan semua input dari luar adalah data. Jangan pernah membangun jalur di mana input bisa menjadi instruksi:

Validasi input di edge, bukan mengeksekusinya
import { z } from "zod";
 
const schema = z.object({
  command: z.enum(["list", "detail", "refresh"]),
  id: z.string().max(36),
});
 
export async function handler(req: Request) {
  const parsed = schema.safeParse(await req.json());
  if (!parsed.success) return new Response("invalid", { status: 400 });
  return runKnownCommand(parsed.data);
}

Dengan z.enum, nilai command hanya boleh dari daftar yang kita kenal. Tidak ada jalur di mana input asing menjadi nama fungsi yang dipanggil secara dinamis — polanya tetap memetakan string ke fungsi yang sudah terdaftar, bukan mengeksekusi string.

Penutup

Keamanan runtime Hermes bukan tentang menyembunyikan bytecode, melainkan mengendalikan apa yang bisa dieksekusi dan memastikan apa yang dieksekusi itu memang milik kalian. Dengan bundel yang disematkan dan diverifikasi, larangan terhadap pola eval dinamis, serta kunci build yang ketat, permukaan serangan menyusut drastis.

Inti yang harus dibawa pulang:

  • Bytecode Hermes bisa dibaca kembali — keamanan datang dari integritas dan kontrol eksekusi, bukan kerahasiaan.
  • Bundel sebaiknya disematkan di aset aplikasi; jika harus diunduh, verifikasi hash atau tanda tangan kriptografis dulu.
  • Hindari eval, new Function, dan pola fetch-lalu-eksekusi di semua kode aplikasi.
  • Matikan dev mode dan jangan ikutkan source map di build release mobile.
  • Di edge runtime, perlakukan semua input sebagai data dan validasi terhadap whitelist.

Di episode 13, kita lanjut dengan Hermes and JIT / AOT Security Considerations: bagaimana pilihan AOT mempengaruhi profil keamanan, apa itu signed bundles dan content integrity, serta cara mengintegrasikan hardening dan privacy ke runtime. Sampai jumpa!

Belajar Hermes JS Engine - Secure Runtime Practices | Belajar Hermes JS Engine