Thay đổi về thông số kỹ thuật HTML: thoát < và > trong các thuộc tính

Michał Bentkowski
Michał Bentkowski

Ngày xuất bản: 12 tháng 6 năm 2025

Vào ngày 20 tháng 5 năm 2025, thông số kỹ thuật HTML đã được cập nhật để thoát <> trong các thuộc tính, giúp ngăn chặn các lỗ hổng XSS đột biến (mXSS). Thay đổi này đã được đưa vào Chrome 138, phiên bản này được nâng cấp lên Beta vào ngày 28 tháng 5 năm 2025 và sẽ trở thành phiên bản ổn định vào ngày 24 tháng 6 năm 2025.

Bài đăng này trình bày chi tiết về tác động của thay đổi đối với việc thoát thuộc tính HTML đối với nhà phát triển web và các lỗi có thể xảy ra; lý do bảo mật đằng sau thay đổi này được giải thích trong bài đăng liên quan trên blog Kỹ thuật bảo mật.

Những nội dung thay đổi

Giả sử bạn có một phần tử <div> có thuộc tính data-content có giá trị là "<u>hello</u>". Điều gì xảy ra khi bạn đọc div.outerHTML?

Trước đây, bạn sẽ nhận được HTML sau:

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

Sau khi thay đổi, bạn sẽ nhận được HTML sau:

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

Trước đây, cả <> đều không được thoát trong các thuộc tính. Giờ đây, cả hai ký tự này luôn được thoát.

Điều gì đã không thay đổi

Thay đổi này chỉ sửa đổi cách các mảnh HTML được chuyển đổi trở lại thành một chuỗi đại diện trong quá trình chuyển đổi tuần tự. Mức tác động chỉ giới hạn ở các trường hợp truy cập vào thuộc tính innerHTML hoặc outerHTML hoặc khi phương thức getHTML() được gọi trên một phần tử. Các thao tác này lấy cấu trúc DOM hiện có và tạo ra một bản trình bày HTML dạng văn bản.

Thay đổi này không ảnh hưởng đến việc phân tích cú pháp HTML. Hãy xem xét đoạn mã HTML sau:

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

Cả hai div sẽ được phân tích cú pháp theo cách giống hệt nhau và trong cả hai trường hợp, div.dataset.content sẽ trả về "<u>hello</u>".

Những gì sẽ không bị hỏng?

Nếu bạn sử dụng bất kỳ API DOM nào, chẳng hạn như getAttribute, getAttributeNS, dataset hoặc attributes để truy xuất giá trị thuộc tính, thì các API này sẽ trả về các giá trị đã giải mã giống như trước, cụ thể là với <> đã giải mã.

Hãy xem xét ví dụ sau, trong đó tất cả các dòng console.log sẽ ghi lại "<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);

Điều gì có thể bị hỏng?

innerHTML và outerHTML để lấy thuộc tính

Nếu bạn sử dụng innerHTML hoặc outerHTML để trích xuất giá trị của một thuộc tính, mã của bạn có thể bị lỗi. Hãy xem xét ví dụ sau đây, mặc dù hơi phức tạp:

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

Mã này sẽ thể hiện hành vi khác sau khi thay đổi này. Trước đây, content sẽ bằng "<u>" nhưng hiện tại là "&lt;u&gt;".

Xin lưu ý rằng bạn không nên phân tích cú pháp HTML bằng biểu thức chính quy. Nếu bạn cần lấy giá trị của một thuộc tính, hãy sử dụng các API DOM được mô tả trong các phần trước.

Kiểm thử toàn diện

Nếu bạn có quy trình CI/CD sử dụng Chromium để tạo HTML và bạn đã viết mã kiểm thử để so sánh HTML với một giá trị dự kiến tĩnh, thì các mã kiểm thử này có thể bị lỗi nếu bất kỳ thuộc tính nào chứa < hoặc >.

Đây là lỗi gián đoạn dự kiến – bạn cần cập nhật giá trị dự kiến để tất cả ký tự <> được thoát tương ứng thành &lt;&gt;,.

Tóm tắt

Bài đăng trên blog này mô tả một thay đổi trong quy cách HTML, theo đó trình duyệt sẽ bắt đầu thoát <> trong các thuộc tính để cải thiện khả năng bảo mật bằng cách ngăn chặn một số trường hợp đột biến XSS.

Thay đổi này sẽ được áp dụng cho tất cả người dùng vào ngày 24 tháng 6 năm 2025 trên Chromium (phiên bản 138) và Firefox (phiên bản 140). Tính năng này cũng có trong Safari 26 Beta, dự kiến sẽ phát hành vào khoảng tháng 9 năm 2025.

Nếu bạn cho rằng thay đổi này đã làm hỏng trang web của bạn và bạn không có cách dễ dàng để khắc phục, vui lòng gửi lỗi tại https://issues.chromium.org/.

Thông tin khác