發布日期:2025 年 6 月 12 日
2025 年 5 月 20 日,HTML 規格更新,以便在屬性中轉義 <
和 >
,有助於防範變異 XSS (mXSS) 漏洞。這項異動已納入 Chrome 138 版,並於 2025 年 5 月 28 日升級為 Beta 版,並將於 2025 年 6 月 24 日推出穩定版。
本文將詳細說明 HTML 屬性逃逸異動對網頁開發人員的影響,以及可能造成的損壞;此外,我們在「安全性工程」網誌的相關文章中,也說明瞭這項異動背後的安全性理由。
異動內容
假設您有一個 <div>
元素,其屬性 data-content
的值為 "<u>hello</u>"
。讀取 div.outerHTML
後會發生什麼事?
過去,您會收到下列 HTML:
<div data-content="<u>hello</u>"></div>
變更後,您會看到以下 HTML:
<div data-content="<u>hello</u>"></div>
先前,屬性中並未轉義 <
或 >
。如今,這兩個字元一律會逸出。
未變更的項目
這項變更僅會修改序列化期間 HTML 片段如何轉換回字串表示法。影響只會發生在存取 innerHTML
或 outerHTML
屬性的情況,或是在元素上叫用 getHTML()
方法時。這些作業會採用現有的 DOM 結構,並產生文字形式的 HTML 表示法。
這項變更「不會」影響 HTML 剖析。請參考以下 HTML:
<div id="div1" data-content="<u>hello</u>"></div>
<div id="div2" data-content="<u>hello</u>"></div>
兩個 div
都會以完全相同的方式剖析,且在兩種情況下 div.dataset.content
都會傳回 "<u>hello</u>"
。
哪些東西不會破裂?
如果您使用任何 DOM API (例如 getAttribute
、getAttributeNS
、dataset
或 attributes
) 來擷取屬性值,則會傳回與先前相同的解碼值,特別是 <
和 >
已解碼。
請參考以下範例,其中所有 console.log
行都會記錄 "<u>"
:
<div data-content="<u>"></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>"
,但現在是 "<u>"
。
請注意,不建議使用規則運算式剖析 HTML。如果您需要取得屬性的值,請使用前面章節所述的 DOM API。
端對端測試
如果您有使用 Chromium 產生 HTML 的 CI/CD 管道,且已編寫測試來比較 HTML 與靜態預期值,如果任何屬性包含 <
或 >
,這些測試就可能會中斷。
這是預期的錯誤,您需要更新預期值,讓所有 <
和 >
字元分別轉換為 <
和 >,
。
摘要
這篇網誌文章說明瞭 HTML 規格中的變更,這項變更會讓瀏覽器開始在屬性中轉義 <
和 >
,藉此防止某些突變 XSS 例項,進而提升安全性。
這項異動將於 2025 年 6 月 24 日生效,適用於 Chromium (138 版) 和 Firefox (140 版) 的所有使用者。這項功能也包含在 Safari 26 Beta 版中,該版本預計將於 2025 年 9 月左右發布。
如果您認為這項變更導致網站發生問題,且您無法輕鬆修正,請前往 https://issues.chromium.org/ 回報錯誤。