HTMLの仕様が変更され、属性値内に記述した<と>がエスケープされるようになります
Post on:2025年6月26日
sponsorsr
先日、HTMLの仕様が変更され、属性値内に記述した<
と>
がエスケープされるようになりました。この変更は6/25にリリースされたChrome 138やFirefox 140をはじめ、Edge, Safariも次のバージョンでサポートされる予定です。
この変更は主に、XSS脆弱性の防止に役立ちます。Web制作者に与える影響と潜在的な問題について紹介します。

HTML spec change: escaping < and > in attributes
下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。基づいてというのは、貢献部分に関して同ライセンスも含みます。
はじめに
2025年5月20日にHTMLの仕様が変更され、属性内の<
と>
がエスケープされるようになりました。これによりmutation XSS(mXSS)脆弱性の防止に役立ちます。この変更はChrome 138に反映され、2025年6月末には安定版がリリース予定です。
この記事では、HTML属性のエスケープがWebデベロッパーに与える影響と、潜在的な問題について詳しく解説します。このアップデートの背景にあるセキュリティ上の根拠については、セキュリティエンジニアリングのブログで解説しています。
変更点
たとえば、<div>
要素があり、そのdata-content
属性の値が「<u>hello</u>
」だとします。div.outerHTML
を読み込むとどうなると思いますか?
以前は、下記のHTMLが生成されていました。
1 |
<div data-content="<u>hello</u>"></div> |
変更後は、下記のHTMLが生成されます。
1 |
<div data-content="<u>hello</u>"></div> |
以前は、属性内で<
と>
はどちらもエスケープされませんでした。しかし、これからは<
と>
はエスケープされます。
変わらなかった点
この変更は、シリアル化時にHTMLフラグメントが文字列表現に変換される方法のみを変更します。この影響はinnerHTML
やouterHTML
プロパティにアクセスする場合、または要素に対してgetHTML()
メソッドを読み出す場合に限定されます。これらの操作は既存のDOM構造を取得し、テキスト形式のHTML表現を生成します。
この変更はHTMLのパースには影響しません。
たとえば、下記のHTMLをご覧ください。
1 2 |
<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>
」を返します。
何が壊れないのか
属性値を取得するためにgetAttribute
, getAttributeNS
, dataset
, attributes
などのDOM APIを使用すると、以前と同じようにデコードされた値、得に<
と>
がデコードされた値が返されます。
たとえば、下記のようなHTMLがあるとします。
1 |
<div data-content="<u>"></div> |
console.log
のすべての行に「<u>
」が記録されます。
1 2 3 4 5 |
const div = document.querySelector("div"); // 以下すべて「<u>」 console.log(div.getAttribute("data-content")); console.log(div.dataset.content); console.log(div.attributes['data-content'].value); |
何が壊れるのか
属性を取得するinnerHTMLとouterHTML
属性値を取得するためにinnerHTML
やouterHTML
を使用すると、コードが壊れる可能性があります。すこし複雑ですが、下記の例をご覧ください。
1 |
<div data-content="<u>"></div> |
1 2 3 |
const div = div.querySelector("div"); const content = div.outerHTML.match(/"([^"]+)"/)[1]; console.log(content); |
このコードは、変更後には異なる動作をします。以前はcontent
は「<u>
」と等しかったのですが、変更後は「<u>
」となります。
正規表現を使用してHTMLをパースすることは推奨されませんので、ご注意ください。属性の値を取得する必要がある場合は、前述のようにDOM APIを使用してください。
エンドツーエンドのテスト
Chromiumを使用して、HTMLを生成するCI/CDパイプラインがあり、そのHTMLを静的な期待値と比較するテストを記述した場合、属性に<
や>
が含まれていると、テストが失敗する可能性があります。
これは想定内の問題です。すべての<
と>
が<
や>
にエスケープされるようにする必要があります。
終わりに
この記事では、HTML仕様の変更について解説しました。この変更によりブラウザは属性内の<
と>
をエスケープするようになり、mutation XSS(mXSS)脆弱性を防止してセキュリティが向上します。
この変更はChrome 138とFirefox 140ですべてのユーザーが利用できるようになりました。また、Safari 26(2025年9月予定)で利用できる予定です。
sponsors