Dari Editor ke Renderer:
Kapan Rich Text Menjadi Risiko?
Menemukan fungsi perender HTML adalah awal pemetaan, bukan bukti eksekusi. Risiko baru dapat dinilai setelah source, hak tulis, transport, context, dan public readback tersambung.
Nama produk, program, komponen, host, rute, field, dan artefak asal tidak dipublikasikan. Artikel membahas mekanisme umum berdasarkan bukti teredaksi.
Sebuah editor menerima rich text. Data dikemas sebagai JSON, bergerak melalui layanan, lalu suatu halaman publik memasukkannya ke renderer HTML. Rangkaian ini terlihat menarik bagi reviewer keamanan. Namun satu baris yang menyerupai sink berbahaya belum membuktikan bahwa aktor tak tepercaya dapat mengendalikan input, mencapai call site, dan menghasilkan efek di browser korban.
Source bukan sink
Source adalah tempat data berasal. Sink adalah operasi yang menafsirkan data dalam context sensitif. Di antara keduanya terdapat ownership, validasi, encoding, transformasi, penyimpanan, moderation, template, serta kebijakan browser. Analisis yang hanya mencari nama fungsi sering melewati keputusan-keputusan itu.
Dalam pemetaan teredaksi, kandidat alur dari field konten menuju JSON dan renderer dapat ditunjukkan secara statis. Plain canary membantu melihat bentuk payload dan jalur serialisasi. Tetapi belum ada objek milik peneliti yang dapat ditulis dan dipublikasikan. Tanpa prerequisite tersebut, tidak ada runtime proof bahwa source yang dikontrol benar-benar mencapai sink dalam context yang diperkirakan.
Static HTML rendering adalah lead. Finding membutuhkan input terkontrol, call-site reachable, efek context-correct, dan dampak yang dibaca kembali.
Lima sambungan yang wajib terbukti
1. Aktor dapat menulis source
Keberadaan editor tidak menjawab siapa yang boleh menyimpan. Bisa jadi hanya operator tepercaya, pipeline internal, atau akun dengan proses review. Reviewer harus membuktikan aktor, role, parent object, state, dan operasi yang diizinkan.
2. Nilai yang sama melewati transport
JSON dapat meng-escape karakter, API dapat menormalisasi markup, dan worker dapat membersihkan atribut. Tangkap nilai sebelum dan sesudah setiap boundary. Jangan menyimpulkan dari nama field yang mirip; buktikan identitas data dengan canary unik yang tidak berbahaya.
3. Renderer yang diamati adalah call site nyata
Bundle dapat menyimpan kode lama, fitur mati, atau komponen untuk data tepercaya. Reachability memerlukan route, state, dan kondisi pemanggilan. Source map atau pencarian statis membantu, tetapi runtime menentukan apakah cabang dieksekusi.
4. Context browser dipahami
HTML body, attribute, URL, style, dan script memiliki aturan berbeda. Payload yang hanya tampil sebagai teks justru membantah context tertentu. Sanitizer, Trusted Types, dan CSP juga dapat memutus rantai meskipun markup sampai ke DOM.
5. Ada pembaca yang relevan
Preview pribadi berbeda dari halaman publik. Self-render tanpa perpindahan trust boundary mungkin bukan dampak keamanan. Tentukan siapa yang membuka hasil, origin apa yang digunakan, credential apa yang hadir, dan tindakan apa yang dapat terjadi.
Payload ladder yang aman
Mulai dengan marker teks unik untuk membuktikan penyimpanan. Lanjutkan dengan karakter context yang membedakan encoding, tanpa mencoba eksekusi. Setelah context dipastikan dan scope mengizinkan, gunakan canary visual atau console marker yang tidak mengambil cookie, token, atau data. Pasangkan dengan kontrol yang harus dirender sebagai teks. Terakhir, baca hasil melalui URL canonical atau akun pembaca terkontrol.
Jika langkah writable ownership tidak tersedia, berhenti pada status blocked yang tepat. Menempelkan label serangan pada sink statis hanya menghasilkan laporan rapuh. Exact blocker jauh lebih bernilai: dibutuhkan objek disposable milik peneliti, hak publish, dan browser readback pada renderer yang sama.
Dua penjelasan benign
Pertama, konten mungkin hanya berasal dari operator tepercaya dan telah melewati sanitasi server sebelum disimpan. Kedua, komponen renderer mungkin menerima HTML yang dibuat sistem, sementara field pengguna menggunakan jalur berbeda. Keduanya menghasilkan source code yang tampak serupa tetapi authority model yang berbeda. Eksperimen harus dirancang untuk membedakan, bukan memilih cerita paling dramatis.
Kontrol engineering
- Simpan format terstruktur, bukan HTML bebas, bila kebutuhan produk memungkinkan.
- Sanitasi server-side dengan allowlist sesuai context dan lakukan lagi saat render bila boundary berubah.
- Pisahkan preview penulis dari publikasi serta catat siapa menyetujui transisi.
- Gunakan CSP dan Trusted Types sebagai lapisan tambahan, bukan pengganti validasi.
- Uji serializer, worker, API lama dan baru, mobile, serta renderer publik untuk parity.
Mengubah lead menjadi keputusan
Keputusan yang disiplin memiliki tiga terminal. Proved jika canary context-correct menghasilkan efek terlarang pada pembaca terkontrol dan diverifikasi. Disproved-exact jika sanitizer atau renderer secara konsisten menetralkan mekanisme yang diuji. Blocked-exact jika objek writable, publish permission, atau readback tidak tersedia. Tidak satu pun terminal memerlukan klaim yang dibuat-buat.
Rich text memang memperluas attack surface, tetapi kualitas audit ditentukan oleh kemampuan menghubungkan seluruh rantai. Source-to-sink yang lengkap bukan panah di diagram; ia adalah serangkaian trust decision yang masing-masing memiliki prediksi, falsifier, dan bukti runtime.
Pertanyaan untuk product owner
Siapa yang boleh menulis? Siapa yang menyetujui? Format apa yang disimpan? Sanitasi terjadi di mana? Apakah versi draft dan live menggunakan renderer yang sama? Apa yang terjadi ketika policy sanitizer berubah terhadap konten lama? Jawaban tersebut menentukan tes dan juga desain migrasi yang aman.
Dengan kerangka ini, tim dapat memperbaiki pipeline bahkan saat eksploitasi belum terbukti. Mereka memperoleh peta ownership, encoding, sanitization, rendering, dan publication state. Reviewer tetap jujur: ada kandidat reachability yang layak diuji, tetapi belum ada klaim eksekusi.
Petakan data sampai ke call site yang benar.
Kami menguji ownership, encoding, sanitizer, renderer, CSP, dan lifecycle publikasi dengan bukti yang dapat direproduksi.