Skip to content
jsonforge.app
Kembali ke blog
Panduan7 menit baca

Keamanan JSON: Kerentanan Umum dan Cara Menghindarinya

JSON sendiri tidak berisi kode yang bisa dieksekusi, tak seperti XML dengan risiko external entity-nya atau YAML dengan kejutan type coercion-nya — sehingga ia punya reputasi aman secara bawaan untuk diurai. Reputasi itu sebagian besar pantas untuk tahap parsing-nya sendiri, tetapi apa yang dilakukan kode Anda dengan object hasil parsing setelahnya adalah tempat kerentanan nyata berada.

Prototype pollution lewat input JSON

Object JavaScript mewarisi dari rantai prototype bersama. Jika JSON tak terpercaya berisi key seperti "__proto__" dan kode Anda meng-merge-nya ke object yang ada tanpa menjaga diri dari key khusus, penyerang bisa menyuntikkan property ke Object.prototype itu sendiri — memengaruhi setiap object dalam aplikasi Anda, bukan hanya yang sedang di-merge.

Payload jahat yang menargetkan fungsi deep-merge naif.
json
{
  "__proto__": {
    "isAdmin": true
  }
}

Jika ini di-deep-merge ke object pengguna dengan merge rekursif yang tidak menangani __proto__, constructor, atau prototype secara khusus, setiap object dalam proses itu — termasuk yang tak pernah menyentuh payload spesifik ini — bisa tiba-tiba punya property isAdmin bernilai true. Ini telah menjadi kelas kerentanan nyata di beberapa library merge/extend npm yang populer.

Cara menghindari prototype pollution

Gunakan Object.create(null) untuk map yang dibangun dari key tak terpercaya, karena tak punya prototype yang bisa terpolusi. Utamakan Map daripada object polos ketika key berasal dari input pengguna dan Anda tak butuh serialisasi JSON pada hasilnya. Jika Anda memang harus me-deep-merge JSON tak terpercaya ke object yang ada, gunakan utilitas merge yang secara eksplisit memblokir __proto__, constructor, dan prototype sebagai key — periksa apakah dependensi Anda sudah menambalnya (kebanyakan library besar sudah, pada versi terbaru) alih-alih mengasumsikan sudah ditangani. Jaga dependensi tetap mutakhir: kelas kerentanan persis ini sudah berkali-kali ditambal lintas package populer seiring teknik bypass baru ditemukan.

Deserialisasi tidak aman di luar JSON.parse biasa

JSON.parse() biasa hanya menghasilkan data polos — string, number, boolean, null, object polos, dan array. Ia tak bisa membangun instance kelas arbitrer atau mengeksekusi kode, tak seperti sebagian format serialisasi lain (pickle Python, misalnya, bisa mengeksekusi kode arbitrer selama deserialisasi). Risikonya muncul ketika fungsi reviver atau langkah downstream merekonstruksi instance kelas atau mengeksekusi logika berdasarkan nilai field tak terpercaya — misalnya, field "type" dalam JSON dipakai untuk require() dinamis atau dispatch ke handler berdasarkan nama string tanpa memvalidasi bahwa string itu ada dalam allowlist.

Validasi terhadap schema sebelum memercayai JSON tak terpercaya

JSON.parse() hanya menjamin validitas sintaksis — ia tak berkata apa-apa soal apakah data cocok dengan bentuk yang diharapkan kode Anda. Body request yang valid sebagai JSON tetapi kehilangan field wajib, atau berisi string di tempat number diharapkan, bisa membuat kode downstream crash atau diam-diam menghasilkan perilaku salah. Memvalidasi JSON masuk terhadap schema (JSON Schema, Zod, Joi, atau sejenisnya) sebelum dipakai menangkap struktur cacat atau tak terduga di batas, memberi Anda titik penolakan yang jelas dengan pesan error yang berguna alih-alih crash membingungkan tiga fungsi ke dalam, sekaligus berfungsi sebagai dokumentasi hidup atas bentuk yang benar-benar diharapkan endpoint tersebut.

Checklist praktis

Validasi JSON tak terpercaya terhadap schema di batas, sebelum mencapai logika bisnis. Jangan pernah me-deep-merge JSON tak terpercaya ke object berumur panjang tanpa utilitas merge yang memblokir key berbahaya. Hindari fungsi reviver atau dispatch dinamis berbasis field string tak terpercaya kecuali nilainya diperiksa terhadap allowlist. Jaga dependensi penanganan JSON (parser, utilitas merge, validator schema) tetap mutakhir — ini kelas kerentanan yang terus berevolusi. Tetapkan batas ukuran yang wajar pada body request JSON untuk mengurangi paparan serangan resource-exhaustion lewat payload yang bersarang sangat dalam atau sangat besar.

FAQ

Apakah JSON.parse() sendiri rentan terhadap eksekusi kode, seperti eval()?
Tidak. JSON.parse() hanya menghasilkan struktur data polos (string, number, boolean, null, object polos, array) dan tidak pernah mengeksekusi kode, tak seperti parsing JSON berbasis eval() yang dipakai sebagian codebase sangat tua sebelum JSON.parse() native menjadi standar. JSON.parse() modern aman soal eksekusi kode; risiko yang dibahas di sini ada pada apa yang dilakukan kode Anda dengan hasil parsingnya setelahnya.
Apa itu prototype pollution dalam istilah sederhana?
Ini kerentanan di mana input yang dikendalikan penyerang (sering JSON dengan key __proto__) di-merge ke object memakai kode yang tidak menjaga diri dari nama property khusus, memungkinkan penyerang menambah atau menimpa property pada object dasar bersama yang diwarisi semua object JavaScript — memengaruhi seluruh aplikasi, bukan hanya satu object.
Apakah saya butuh validasi schema jika sudah memakai TypeScript?
Ya — tipe TypeScript terhapus saat compile time dan memberikan perlindungan runtime nol. Payload JSON cacat atau jahat yang datang lewat HTTP tidak diperiksa apa pun saat runtime kecuali Anda secara eksplisit memvalidasinya dengan library seperti Zod, Joi, atau validator JSON Schema. TypeScript mencegah Anda menulis kode yang salah menangani bentuk yang diharapkan; ia tak berbuat apa-apa untuk memverifikasi data aktual cocok dengan bentuk itu.
Apakah YAML atau XML lebih aman diurai daripada JSON?
Tak secara inheren — keduanya punya kelas kerentanannya sendiri. Parser YAML di sebagian bahasa mendukung type coercion dan tag yang bisa membangun object arbitrer jika tidak dikonfigurasi dalam mode "safe load" yang dibatasi. Parser XML rentan serangan XML External Entity (XXE) jika ekspansi entity tidak dimatikan. Sistem tipe JSON yang lebih sederhana (tanpa tag, tanpa entity) menghapus permukaan serangan spesifik itu, tetapi risiko deserialisasi dan merging yang dibahas di sini tetap berlaku.

Coba alat ini

Artikel terkait