การเปลี่ยนแปลงข้อกำหนด HTML: การหนีค่า < และ > ในแอตทริบิวต์

Michał Bentkowski
Michał Bentkowski

เผยแพร่เมื่อวันที่ 12 มิถุนายน 2025

เมื่อวันที่ 20 พฤษภาคม 2025 ข้อกำหนดเฉพาะของ HTML ได้รับการอัปเดตเพื่อหลีกหนี < และ > ในแอตทริบิวต์ ซึ่งช่วยป้องกันช่องโหว่ Mutation XSS (mXSS) การเปลี่ยนแปลงนี้มีผลใน Chrome 138 ซึ่งได้รับการเลื่อนขั้นเป็นเบต้าเมื่อวันที่ 28 พฤษภาคม 2025 และจะกลายเป็นเวอร์ชันเสถียรในวันที่ 24 มิถุนายน 2025

โพสต์นี้จะอธิบายรายละเอียดผลกระทบของการเปลี่ยนแปลงการหนีค่าแอตทริบิวต์ HTML ต่อนักพัฒนาเว็บและการหยุดชะงักที่อาจเกิดขึ้น เหตุผลด้านความปลอดภัยที่อยู่เบื้องหลังการเปลี่ยนแปลงนี้อธิบายไว้ในโพสต์ที่เกี่ยวข้องในบล็อกวิศวกรรมความปลอดภัย

สิ่งที่เปลี่ยนแปลง

สมมติว่าคุณมีองค์ประกอบ <div> ที่แอตทริบิวต์ data-content มีค่าเป็น "<u>hello</u>" สิ่งที่จะเกิดขึ้นเมื่อคุณอ่าน div.outerHTML

ก่อนหน้านี้ คุณจะได้รับ HTML ต่อไปนี้

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

หลังจากการเปลี่ยนแปลง คุณจะได้รับ HTML ต่อไปนี้

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

ก่อนหน้านี้ < และ > ไม่ได้ได้รับการหลีกหนีในแอตทริบิวต์ ตอนนี้อักขระทั้ง 2 ตัวนี้จะมีเครื่องหมายหลีกเสมอ

สิ่งที่ไม่เปลี่ยนแปลง

การเปลี่ยนแปลงนี้จะแก้ไขเฉพาะวิธีแปลงข้อมูลโค้ด HTML กลับเป็นการแสดงสตริงระหว่างการจัดเก็บข้อมูลเป็นอนุกรม ผลกระทบจะจำกัดอยู่ในสถานการณ์ที่มีการเข้าถึงพร็อพเพอร์ตี้ innerHTML หรือ outerHTML หรือเมื่อเรียกใช้เมธอด getHTML() ในองค์ประกอบ การดำเนินการเหล่านี้จะนำโครงสร้าง DOM ที่มีอยู่เพื่อสร้างการแสดงผล HTML แบบข้อความ

การเปลี่ยนแปลงนี้ไม่ส่งผลต่อการแยกวิเคราะห์ HTML ลองดู HTML ต่อไปนี้

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

ระบบจะแยกวิเคราะห์ div ทั้ง 2 รายการในลักษณะเดียวกันทุกประการ และทั้ง 2 กรณี div.dataset.content จะแสดงผลเป็น "<u>hello</u>"

อะไรบ้างที่จะไม่เสียหาย

หากคุณใช้ DOM API เช่น getAttribute, getAttributeNS, dataset หรือ attributes เพื่อเรียกค่าแอตทริบิวต์ ระบบจะแสดงผลค่าที่ถอดรหัสแล้วเหมือนเดิม โดยเฉพาะเมื่อถอดรหัส < และ >

ลองดูตัวอย่างต่อไปนี้ ซึ่งระบบจะบันทึกบรรทัด console.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);

สิ่งที่อาจเสียหาย

innerHTML และ outerHTML เพื่อรับแอตทริบิวต์

หากคุณใช้ innerHTML หรือ outerHTML เพื่อดึงค่าของแอตทริบิวต์ โค้ดอาจใช้งานไม่ได้ ลองดูตัวอย่างต่อไปนี้ แม้ว่าจะซับซ้อนไปหน่อย

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

โค้ดนี้จะแสดงลักษณะการทำงานที่แตกต่างออกไปหลังจากการเปลี่ยนแปลงนี้ ก่อนหน้านี้ content จะเท่ากับ "<u>" แต่ตอนนี้เท่ากับ "&lt;u&gt;"

โปรดทราบว่าเราไม่แนะนําให้แยกวิเคราะห์ HTML ด้วยนิพจน์ทั่วไป หากต้องการรับค่าของแอตทริบิวต์ ให้ใช้ DOM API ที่อธิบายไว้ในส่วนก่อนหน้า

การทดสอบจากต้นทางถึงปลายทาง

หากคุณมีพิพลิน CI/CD ที่ใช้ Chromium เพื่อสร้าง HTML และเขียนการทดสอบเพื่อเปรียบเทียบ HTML กับค่าคงที่ที่คาดไว้ การทดสอบเหล่านี้อาจใช้งานไม่ได้หากแอตทริบิวต์ใดก็ตามมี < หรือ >

นี่เป็นข้อบกพร่องที่คาดไว้ คุณต้องอัปเดตค่าที่คาดไว้เพื่อให้ระบบหลีกอักขระ < และ > ทั้งหมดเป็น &lt; และ &gt;, ตามลำดับ

สรุป

บล็อกโพสต์นี้อธิบายการเปลี่ยนแปลงในข้อกำหนด HTML ซึ่งจะทำให้เบราว์เซอร์เริ่มหลีกหนี < และ > ในแอตทริบิวต์เพื่อปรับปรุงความปลอดภัยด้วยการป้องกันการเกิด XSS บางรายการ

การเปลี่ยนแปลงนี้จะพร้อมให้บริการแก่ผู้ใช้ทุกคนในวันที่ 24 มิถุนายน 2025 ใน Chromium (เวอร์ชัน 138) และ Firefox (เวอร์ชัน 140) ฟีเจอร์นี้ยังรวมอยู่ใน Safari 26 เบต้าด้วย ซึ่งคาดว่าจะเปิดตัวประมาณเดือนกันยายน 2025

หากคุณเชื่อว่าการเปลี่ยนแปลงนี้ทำให้เว็บไซต์ใช้งานไม่ได้และคุณไม่มีวิธีแก้ไขง่ายๆ โปรดรายงานข้อบกพร่องที่ https://issues.chromium.org/

ข้อมูลเพิ่มเติม