Chrome の version83 より追加された TrustedTypesを使用した。その概要と大まかな使用方法、コードを記す。記載にあたっては、Prevent DOM-based cross-site scripting vulnerabilities with Trusted Typesを参照した。
TL;DL
下記のページに Trusted Types の動作確認コードをホストした。動作のイメージを掴みたい方は、アクセスして Console を確認いただくと理解が早いかもしれない。
Netlify: https://laughing-shirley-de1838.netlify.app/
ソースコード:https://github.com/benibana2001/til/tree/master/csp/dist
Trusted Types とは
概要
DOM ベースの XSS を回避するために導入されたブラウザ API。2020 年 6 月現在 Draft。
W3C の仕様: Trusted Types
GitHub: w3c/webappsec-trusted-types
DOM-based XSS?
DOM-based cross-site scripting とは何か。これは以下のように言われている。
DOM-based cross-site scripting happens when data from a user controlled source (like user name, or redirect URL taken from the URL fragment) reaches a sink, which is a function like eval() or a property setter like .innerHTML, that can execute arbitrary JavaScript code.
つまり、JavaScript の DOM 操作に関する一部の機能の穴を突き、XSS を行うこと。具体的には、DOM 情報を動的に操作する script、例えばinnerHTML
や document.write
などを使用した際に発生しうる。
Trusted Types によって実行できること
Trusted Typesを有効化しておくと、innerHTML
等を使用した XSS の原因となりうるコードを記述した際、ブラウザ上で実行エラーとなる。これにより開発者は、事前に危険なコードを検知し、修正する機会を得ることができる。
|
|
Trusted Types は危険を知らせてくれる。しかしこの機能を使用したからといって、コードが安全になるわけではない。XSS を防ぐためには、開発者自身がコードを修正する必要がある。
例えば開発者がinnerHTML
を使用する際は、代わりに以下のような手段を検討すべきだ。
innerHTML
の代わりにtextContent
を使用する- DOMPrifyのようなライブラリを使用しサニタイズを行う
これらの方法を使用してコードが安全な状態(trustedHTML)となった時、Trusted types はエラーを吐くのをやめる。
Trusted Types を使用する方法
ここでは Trusted Types を使用する方法について確認する。
使用準備
HTTP レスポンスのヘッダーに下記を設定することで、Trusted Types を有効化することができる。また URI を指定することで、エラーを通知することができる(要 HTTPS)。
Content-Security-Policy: require-trusted-types-for 'script'; report-uri
上記の記述は、コンテンツセキュリティポリシー (CSP)と呼ばれるセキュリティレイヤーの設定を行なっている。これはXSS をはじめとする脅威を検知するためのものだ。
上記設定をサーバーに対して行うことで、Trusted Typesは有効となる。しかし<meta>
要素を用いて指定することも可能だ。その際は下記のような形となる。
|
|
ただし、Content-Security-Policy-Read-Only
というエラー通知用のレイヤーに関してはmeta
タグでの使用はサポートされていないため注意が必要だ。

CSP の詳細についてはMDN/コンテンツセキュリティポリシーがわかりやすい。
エラー内容
詳細について今回は触れないが、上記のContent-Security-Policy-Report-Only
というエラー確認用のレイヤーを設定した場合は、違反が発生した際にレポートという形で、以下のような情報が送られる。
|
|
Trusted Types を使ってポリシーを作成
違反が確認された際は、修正を行う必要がある。
上述したが、修正の方法は複数存在する。ただし場合によっては、サニタイズのためのライブラリが使用できないこともある。そんな時は、自前でポリシーの実装をする必要がある。
ポリシーとは、安全なコードを作るための機能だ。具体的にはwindow.trustedTypes
オブジェクトのcreatePolicy
メソッドを使用して作成する。
以下のコードではポリシーを作成し、そこに文字列をエスケープするための機能を追加している。
|
|
このポリシーを下記のように使用することで、文字列をエスケープできる。
|
|
実際に TrustedTypes を使用してみる
ここでは危険を含むコードを実際に Netlify にホストし、どのような結果になるのか確認する。
ホストするコードを用意
今回は、以下の2つのコードを用意して TrustedTypes の動きを確認する。
-
- 故意に脅威を含ませたコード
-
- ポリシーを作成し、1 に対して適用を行い、無害化したコード
はじめに 1 のコードを用意する。
|
|
続いて 2 のコードを用意する。
|
|
上記 2 つのコードをホストする。
Netlify にホスト
Netlify を使用して、上記の 2 つのコードをhttps://laughing-shirley-de1838.netlify.app/にホストした。こちらのページで Console を確認すると下記のエラーが確認できる。

Consoleを見るに、1 の危険を含むコードは、下記のようなエラーが表示されていることが確認できる。
This document requires ‘TrustedHTML’ assignment.
Uncaught TypeError: Failed to set the ‘innerHTML’ property on ‘Element’: This document requires ‘TrustedHTML’ assignment.
反対に、2 の安全なコードでは、エラーは表示されない。
これらのことから、Trusted Types が予想通りに正しく機能していることが確認できた。
おわりに
Trusted Types を有効化しておくことで、開発者にとって安全なコードを書く助けとなることがわかった。
現在はまだ Draft のため Polyfill が必要だが、積極的に使用していきたい。