Perubahan spesifikasi HTML: meng-escape < dan > dalam atribut

Michał Bentkowski
Michał Bentkowski

Dipublikasikan: 12 Juni 2025

Pada 20 Mei 2025, spesifikasi HTML diperbarui untuk meng-escape < dan > dalam atribut, sehingga membantu mencegah kerentanan XSS mutasi (mXSS). Perubahan ini diterapkan di Chrome 138, yang dipromosikan ke Beta pada 28 Mei 2025, dan akan menjadi Stabil pada 24 Juni 2025.

Postingan ini menjelaskan dampak perubahan escape atribut HTML pada developer web dan potensi kerusakan; alasan keamanan di balik perubahan ini dijelaskan dalam postingan terkait di blog Security Engineering.

Apa yang berubah

Misalkan Anda memiliki elemen <div> yang atribut data-content-nya memiliki nilai "<u>hello</u>". Apa yang terjadi jika Anda membaca div.outerHTML?

Sebelumnya, Anda akan mendapatkan HTML berikut:

<div data-content="<u>hello</u>"></div>

Setelah perubahan, Anda akan mendapatkan HTML berikut:

<div data-content="&lt;u&gt;hello&lt;/u&gt;"></div>

Sebelumnya, < atau > tidak di-escape dalam atribut. Sekarang, kedua karakter ini selalu di-escape.

Apa yang tidak berubah

Perubahan ini secara eksklusif mengubah cara fragmen HTML dikonversi kembali menjadi representasi string selama serialisasi. Dampaknya terbatas pada skenario saat properti innerHTML atau outerHTML diakses, atau saat metode getHTML() dipanggil pada elemen. Operasi ini menggunakan struktur DOM yang ada dan menghasilkan representasi HTML tekstual.

Perubahan ini tidak memengaruhi penguraian HTML. Pertimbangkan HTML berikut:

<div id="div1" data-content="<u>hello</u>"></div>
<div id="div2" data-content="&lt;u&gt;hello&lt;/u&gt;"></div>

Kedua div akan diuraikan dengan cara yang sama persis dan dalam kedua kasus tersebut, div.dataset.content akan menampilkan "<u>hello</u>".

Apa yang tidak akan rusak?

Jika Anda menggunakan DOM API, seperti getAttribute, getAttributeNS, dataset, atau attributes, untuk mengambil nilai atribut, API tersebut akan menampilkan nilai yang didekode sama seperti sebelumnya, khususnya dengan < dan > yang didekode.

Perhatikan contoh berikut, yang menampilkan semua baris console.log akan mencatat ke dalam log "<u>":

<div data-content="&lt;u&gt;"></div>
const div = document.querySelector("div");
// All of the following will log "<u>"
console.log(div.getAttribute("data-content"));
console.log(div.dataset.content);
console.log(div.attributes['data-content'].value);

Apa yang dapat rusak?

innerHTML dan outerHTML untuk mendapatkan atribut

Jika Anda menggunakan innerHTML atau outerHTML untuk mengekstrak nilai atribut, kode Anda dapat rusak. Perhatikan contoh berikut, meskipun sedikit rumit:

<div data-content="<u>"></div>
const div = document.querySelector("div");
const content = div.outerHTML.match(/"([^"]+)"/)[1];
console.log(content);

Kode ini akan menunjukkan perilaku yang berbeda setelah perubahan ini. Sebelumnya, content akan sama dengan "<u>", tetapi sekarang menjadi "&lt;u&gt;".

Perhatikan bahwa penguraian HTML dengan ekspresi reguler tidak direkomendasikan. Jika Anda perlu mendapatkan nilai atribut, gunakan DOM API yang dijelaskan di bagian sebelumnya.

Pengujian menyeluruh

Jika Anda memiliki pipeline CI/CD tempat Anda menggunakan Chromium untuk membuat HTML, dan Anda telah menulis pengujian untuk membandingkan HTML dengan nilai yang diharapkan statis, pengujian ini dapat rusak jika atribut apa pun berisi < atau >.

Ini adalah kerusakan yang diharapkan—Anda perlu memperbarui nilai yang diharapkan sehingga semua karakter < dan > masing-masing di-escape ke &lt; dan &gt;,.

Ringkasan

Postingan blog ini menjelaskan perubahan pada spesifikasi HTML yang akan menyebabkan browser mulai meng-escape < dan > dalam atribut untuk meningkatkan keamanan dengan mencegah beberapa instance mutasi XSS.

Perubahan ini akan tersedia untuk semua pengguna pada 24 Juni 2025 di Chromium (versi 138) dan Firefox (versi 140). Fitur ini juga disertakan dalam Safari 26 Beta yang akan dirilis sekitar September 2025.

Jika Anda yakin bahwa perubahan ini merusak situs Anda dan Anda tidak memiliki cara yang mudah untuk memperbaikinya, laporkan bug di https://issues.chromium.org/.

Informasi tambahan