HTMLの仕様が変更され、属性値内に記述した<と>がエスケープされるようになります

先日、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が生成されていました。

変更後は、下記のHTMLが生成されます。

以前は、属性内で<>はどちらもエスケープされませんでした。しかし、これからは<>はエスケープされます。

変わらなかった点

この変更は、シリアル化時にHTMLフラグメントが文字列表現に変換される方法のみを変更します。この影響はinnerHTMLouterHTMLプロパティにアクセスする場合、または要素に対してgetHTML()メソッドを読み出す場合に限定されます。これらの操作は既存のDOM構造を取得し、テキスト形式のHTML表現を生成します。

この変更はHTMLのパースには影響しません。
たとえば、下記のHTMLをご覧ください。

どちらのdivもまったく同じ方法でパースされ、どちらの場合もdiv.dataset.contentは「<u>hello</u>」を返します。

何が壊れないのか

属性値を取得するためにgetAttribute, getAttributeNS, dataset, attributesなどのDOM APIを使用すると、以前と同じようにデコードされた値、得に<>がデコードされた値が返されます。

たとえば、下記のようなHTMLがあるとします。

console.logのすべての行に「<u>」が記録されます。

何が壊れるのか

属性を取得するinnerHTMLとouterHTML

属性値を取得するためにinnerHTMLouterHTMLを使用すると、コードが壊れる可能性があります。すこし複雑ですが、下記の例をご覧ください。

このコードは、変更後には異なる動作をします。以前はcontentは「<u>」と等しかったのですが、変更後は「&lt;u&gt;」となります。

正規表現を使用してHTMLをパースすることは推奨されませんので、ご注意ください。属性の値を取得する必要がある場合は、前述のようにDOM APIを使用してください。

エンドツーエンドのテスト

Chromiumを使用して、HTMLを生成するCI/CDパイプラインがあり、そのHTMLを静的な期待値と比較するテストを記述した場合、属性に<>が含まれていると、テストが失敗する可能性があります。

これは想定内の問題です。すべての<>&lt;&gt;にエスケープされるようにする必要があります。

終わりに

この記事では、HTML仕様の変更について解説しました。この変更によりブラウザは属性内の<>をエスケープするようになり、mutation XSS(mXSS)脆弱性を防止してセキュリティが向上します。

この変更はChrome 138とFirefox 140ですべてのユーザーが利用できるようになりました。また、Safari 26(2025年9月予定)で利用できる予定です。

sponsors

top of page

©2025 coliss