テスト
- DOMParser-parseFromString-regression.html (ライブテスト) (ソース)
- DOMParser-parseFromString.html (ライブテスト) (ソース)
- DedicatedWorker-block-eval-function-constructor.html (ライブテスト) (ソース)
- DedicatedWorker-constructor-from-DedicatedWorker.html (ライブテスト) (ソース)
- DedicatedWorker-constructor-from-SharedWorker.html (ライブテスト) (ソース)
- DedicatedWorker-constructor.https.html (ライブテスト) (ソース)
- DedicatedWorker-eval.html (ライブテスト) (ソース)
- DedicatedWorker-importScripts.html (ライブテスト) (ソース)
- DedicatedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- Document-execCommand.html (ライブテスト) (ソース)
- Document-write-appending-line-feed.html (ライブテスト) (ソース)
- Document-write-exception-order.xhtml (ライブテスト) (ソース)
- Document-write.html (live test) (ソース)
- Element-insertAdjacentHTML.html (ライブテスト) (ソース)
- Element-outerHTML.html (live test) (ソース)
- Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-TT-realm.html (ライブテスト) (ソース)
- Element-setAttribute-respects-Elements-node-documents-globals-CSP-after-adoption-from-non-TT-realm.html (ライブテスト) (ソース)
- Element-setAttribute.html (ライブテスト) (ソース)
- Element-setAttributeNS.html (ライブテスト) (ソース)
- Element-toggleAttribute.html (ライブテスト) (ソース)
- GlobalEventHandlers-onclick.html (ライブテスト) (ソース)
- HTMLElement-generic.html (live test) (ソース)
- HTMLScriptElement-in-xhtml-document.tentative.https.xhtml (ライブテスト) (ソース)
- HTMLScriptElement-internal-slot.html (ライブテスト) (ソース)
- Node-multiple-arguments-tt-enforced.html (ライブテスト) (ソース)
- Node-multiple-arguments.html (ライブテスト) (ソース)
- Range-createContextualFragment.html (ライブテスト) (ソース)
- SVGScriptElement-internal-slot.html (ライブテスト) (ソース)
- ServiceWorker-block-eval-function-constructor.https.html (ライブテスト) (ソース)
- ServiceWorker-eval.https.html (ライブテスト) (ソース)
- ServiceWorker-importScripts.https.html (ライブテスト) (ソース)
- ServiceWorkerContainer-register-from-DedicatedWorker.https.html (ライブテスト) (ソース)
- ServiceWorkerContainer-register-from-ServiceWorker.https.html (ライブテスト) (ソース)
- ServiceWorkerContainer-register-from-SharedWorker.https.html (ライブテスト) (ソース)
- ServiceWorkerContainer-register.https.html (ライブテスト) (ソース)
- SharedWorker-block-eval-function-constructor.html (ライブテスト) (ソース)
- SharedWorker-constructor.https.html (ライブテスト) (ソース)
- SharedWorker-eval.html (live test) (ソース)
- SharedWorker-importScripts.html (ライブテスト) (ソース)
- SharedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- TrustedType-AttributeNodes.html (ライブテスト) (ソース)
- TrustedTypePolicy-CSP-no-name.html (ライブテスト) (ソース)
- TrustedTypePolicy-CSP-wildcard.html (ライブテスト) (ソース)
- TrustedTypePolicy-createXXX.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-constants.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-createXYZTests.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-none-name.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-none.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-none.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests-wildcard.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-cspTests.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-non-tt-policy-name.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-createPolicy-unenforced.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-defaultPolicy.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-getAttributeType-namespace.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-getAttributeType-svg.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-getAttributeType.html (ライブテスト) (ソース)
- TrustedTypePolicyFactory-isXXX.html (ライブテスト) (ソース)
- Window-TrustedTypes.html (live test) (ソース)
- Window-block-eval-function-constructor.html (ライブテスト) (ソース)
- Window-setTimeout-setInterval.html (ライブテスト) (ソース)
- block-Document-execCommand.html (ライブテスト) (ソース)
- block-string-assignment-to-DOMParser-parseFromString.html (ライブテスト) (ソース)
- block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- block-string-assignment-to-Document-parseHTMLUnsafe.html (ライブテスト) (ソース)
- block-string-assignment-to-Document-write.html (ライブテスト) (ソース)
- block-string-assignment-to-Element-insertAdjacentHTML.html (ライブテスト) (ソース)
- block-string-assignment-to-Element-outerHTML.html (ライブテスト) (ソース)
- block-string-assignment-to-Element-setAttribute.html (ライブテスト) (ソース)
- block-string-assignment-to-Element-setAttributeNS.html (ライブテスト) (ソース)
- block-string-assignment-to-Element-setHTMLUnsafe.html (ライブテスト) (ソース)
- block-string-assignment-to-HTMLElement-generic.html (ライブテスト) (ソース)
- block-string-assignment-to-HTMLIFrameElement-srcdoc.html (ライブテスト) (ソース)
- block-string-assignment-to-Range-createContextualFragment.html (ライブテスト) (ソース)
- block-string-assignment-to-ShadowRoot-innerHTML.html (ライブテスト) (ソース)
- block-string-assignment-to-ShadowRoot-setHTMLUnsafe.html (ライブテスト) (ソース)
- block-string-assignment-to-SharedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- block-string-assignment-to-Window-setTimeout-setInterval.html (ライブテスト) (ソース)
- block-string-assignment-to-attribute-via-attribute-node.html (ライブテスト) (ソース)
- block-string-assignment-to-text-and-url-sinks.html (ライブテスト) (ソース)
- block-text-node-insertion-into-script-element.html (ライブテスト) (ソース)
- block-text-node-insertion-into-svg-script-element.html (ライブテスト) (ソース)
- csp-block-eval.html (live test) (ソース)
- default-policy-callback-arguments.html (ライブテスト) (ソース)
- default-policy-report-only.html (ライブテスト) (ソース)
- default-policy.html (live test) (ソース)
- empty-default-policy-report-only.html (ライブテスト) (ソース)
- empty-default-policy.html (ライブテスト) (ソース)
- eval-csp-no-tt.html (live test) (ソース)
- eval-csp-tt-default-policy-mutate.html (ライブテスト) (ソース)
- eval-csp-tt-default-policy.html (ライブテスト) (ソース)
- eval-csp-tt-no-default-policy.html (ライブテスト) (ソース)
- eval-function-constructor-untrusted-arguments-and-applying-default-policy.html (ライブテスト) (ソース)
- eval-function-constructor-untrusted-arguments-and-default-policy-throwing.html (ライブテスト) (ソース)
- eval-function-constructor.html (ライブテスト) (ソース)
- eval-no-csp-no-tt-default-policy.html (ライブテスト) (ソース)
- eval-no-csp-no-tt.html (live test) (ソース)
- eval-with-permissive-csp.html (ライブテスト) (ソース)
- get-trusted-types-compliant-attribute-value.html (ライブテスト) (ソース)
- idlharness.window.js (live test) (ソース)
- inheriting-csp-for-local-schemes.html (ライブテスト) (ソース)
- legacy-trusted-script-urls.html (ライブテスト) (ソース)
- legacy-trusted-scripts.html (ライブテスト) (ソース)
- modify-attributes-in-callback.html (ライブテスト) (ソース)
- no-require-trusted-types-for-report-only.html (ライブテスト) (ソース)
- no-require-trusted-types-for.html (ライブテスト) (ソース)
- require-trusted-types-for-TypeError-belongs-to-the-global-object-realm.html (ライブテスト) (ソース)
- require-trusted-types-for-report-only.html (ライブテスト) (ソース)
- require-trusted-types-for.html (ライブテスト) (ソース)
- script-enforcement-001-outerHTML.xhtml (ライブテスト) (ソース)
- script-enforcement-001.html (ライブテスト) (ソース)
- script-enforcement-002-outerHTML.xhtml (ライブテスト) (ソース)
- script-enforcement-002.html (ライブテスト) (ソース)
- script-enforcement-003.html (ライブテスト) (ソース)
- script-enforcement-004.html (ライブテスト) (ソース)
- script-enforcement-005.html (ライブテスト) (ソース)
- script-enforcement-006.html (ライブテスト) (ソース)
- script-enforcement-007.html (ライブテスト) (ソース)
- script-enforcement-008.https.html (ライブテスト) (ソース)
- script-enforcement-009.https.html (ライブテスト) (ソース)
- script-enforcement-010.html (ライブテスト) (ソース)
- script-enforcement-011.html (ライブテスト) (ソース)
- set-attributes-no-require-trusted-types.html (ライブテスト) (ソース)
- set-attributes-require-trusted-types-default-policy.html (ライブテスト) (ソース)
- set-attributes-require-trusted-types-no-default-policy.html (ライブテスト) (ソース)
- should-sink-type-mismatch-violation-be-blocked-by-csp-001.html (ライブテスト) (ソース)
- should-sink-type-mismatch-violation-be-blocked-by-csp-002-worker.html (ライブテスト) (ソース)
- should-sink-type-mismatch-violation-be-blocked-by-csp-003.html (ライブテスト) (ソース)
- should-trusted-type-policy-creation-be-blocked-by-csp-001.html (ライブテスト) (ソース)
- should-trusted-type-policy-creation-be-blocked-by-csp-002.html (ライブテスト) (ソース)
- should-trusted-type-policy-creation-be-blocked-by-csp-003.html (ライブテスト) (ソース)
- should-trusted-type-policy-creation-be-blocked-by-csp-004-worker.html (ライブテスト) (ソース)
- should-trusted-type-policy-creation-be-blocked-by-csp-005.html (ライブテスト) (ソース)
- trusted-types-createHTMLDocument.html (ライブテスト) (ソース)
- trusted-types-duplicate-names-list-report-only.html (ライブテスト) (ソース)
- trusted-types-duplicate-names-list.html (ライブテスト) (ソース)
- trusted-types-duplicate-names-without-enforcement.html (ライブテスト) (ソース)
- trusted-types-duplicate-names.html (ライブテスト) (ソース)
- trusted-types-eval-reporting-no-unsafe-eval.html (ライブテスト) (ソース)
- trusted-types-eval-reporting-report-only.html (ライブテスト) (ソース)
- trusted-types-event-handlers.html (ライブテスト) (ソース)
- trusted-types-navigation.html (ライブテスト) (ソース)
- trusted-types-report-only.html (ライブテスト) (ソース)
- trusted-types-reporting-check-report-DedicatedWorker-create-policy.html (ライブテスト) (ソース)
- trusted-types-reporting-check-report-DedicatedWorker-sink-mismatch.html (ライブテスト) (ソース)
- trusted-types-reporting-check-report-Window-create-policy.html (ライブテスト) (ソース)
- trusted-types-reporting-check-report-Window-sink-mismatch.html (ライブテスト) (ソース)
- trusted-types-reporting-clipping-of-sample.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DOMParser-parseFromString.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-DedicatedWorker-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-ServiceWorkerContainer-register.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-eval.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-function-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-importScripts.html (ライブテスト) (ソース)
- trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Document-execCommand.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Document-parseHTMLUnsafe.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Document-write.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Element-innerHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Element-insertAdjacentHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Element-outerHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Element-setAttribute.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Element-setHTMLUnsafe.html (ライブテスト) (ソース)
- trusted-types-reporting-for-HTMLIFrameElement-srcdoc.html (ライブテスト) (ソース)
- trusted-types-reporting-for-HTMLScriptElement-children-change.html (ライブテスト) (ソース)
- trusted-types-reporting-for-HTMLScriptElement-innerHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-HTMLScriptElement.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Range-createContextualFragment.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SVGScriptElement-children-change.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SVGScriptElement-innerHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ServiceWorker-ServiceWorkerContainer-register.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ServiceWorker-eval.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ServiceWorker-function-constructor.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ServiceWorker-importScripts.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ServiceWorker-setTimeout-setInterval.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ShadowRoot-innerHTML.html (ライブテスト) (ソース)
- trusted-types-reporting-for-ShadowRoot-setHTMLUnsafe.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-DedicatedWorker-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-ServiceWorkerContainer-register.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-eval.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-function-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-importScripts.html (ライブテスト) (ソース)
- trusted-types-reporting-for-SharedWorker-setTimeout-setInterval.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-DedicatedWorker-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-ServiceWorkerContainer-register.https.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-SharedWorker-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-eval.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-function-constructor.html (ライブテスト) (ソース)
- trusted-types-reporting-for-Window-setTimeout-setInterval.html (ライブテスト) (ソース)
- trusted-types-reporting.html (ライブテスト) (ソース)
- trusted-types-sandbox-allow-scripts.html (ライブテスト) (ソース)
- trusted-types-sandbox-no-allow-scripts.html (ライブテスト) (ソース)
- trusted-types-source-file-path.html (ライブテスト) (ソース)
- trusted-types-svg-script-set-href.html (ライブテスト) (ソース)
- trusted-types-tojson.html (ライブテスト) (ソース)
- tt-block-eval.html (live test) (ソース)
1. 導入
このセクションは規範的なものではありません。
特定の種類の脆弱性は、Webアプリケーションが攻撃者制御のソース(例えば document の URL パラメータや postMessage チャンネル)から値を取得し、適切なサニタイズなしに インジェクションシンク(多様で強力な能力を持つWeb API関数群)の一つに渡す時に発生します。
この種の問題は従来防ぐのが難しいものです。
アプリケーション作者はインジェクションシンクに攻撃者制御の値を渡してしまっていることに気づかないことが多く、インジェクションシンクを呼び出す時その入力が攻撃者制御だったかどうか明らかではありません。
JavaScriptの動的な特性のため、そうしたパターンが存在しないと保証するのも困難です。これは手動コードレビューや自動コード解析でも見逃されがちです。例えば、aString
に信頼できないデータが入っている場合、foo[bar] = aString という文も foo や bar
の値次第で脆弱性を引き起こす可能性があります。
本書は、攻撃者制御データが
§ 2.1.1 DOM XSSインジェクションシンク
に到達し、その結果攻撃者が制御するスクリプトペイロードが実行される
DOMベースのクロスサイトスクリプティング(DOM XSS)の防止に焦点を当てています。DOM XSSはWebアプリケーションに蔓延しており、60を超えるインジェクションシンク(例:
Element.innerHTML や Location.href セッターなど)があります。
この文書では Trusted Types を定義します。これは、インジェクションシンク への入力を偽装不可能な型付き値のみ受け入れるようロックダウンするAPIです。こうした値はアプリケーション定義の ポリシー からのみ生成でき、危険なAPIをガードするルールを作者が定義できるため、攻撃対象領域をWebアプリケーションの小さく孤立した一部へ集約し、レビューや保護が容易になります。
1.1. 目的
-
強力なWeb APIを信頼できないデータで呼び出す際に発生するクライアントサイド脆弱性の発生確率(例: DOM XSS)を最小化する。
-
セキュリティ上の判断をアプリケーションの小さい一部分にカプセル化する設計を促進する。
-
複雑なWebアプリケーションコードベースにおけるセキュリティレビューの範囲を縮小する。
-
ダイナミック・スタティック解析ツールの補助によって、通常のプログラミングエラー検出のように、ユーザー体験を損なわずに脆弱性を検出・開発者に可視化できるようにする。
1.2. 非目的事項
-
サーバーサイドで生成されたマークアップへのインジェクション(特にスクリプト本体へのリフレクション)の結果を防ぐ・緩和すること。サーバーサイドXSSに対してはテンプレートシステムや CSP script-src など既存のソリューションを推奨。
-
リソース制限(例: データ持ち出し防止、Fetch による外部接続防止など)に取り組むこと。
-
サブリソースのロード制御。Trusted Typesは、ドキュメントでスクリプト可能なリソースのロード制御には対応するが、他のサブリソース制御は対象外。
-
クロスオリジンのJavaScript実行の防止(例: Trusted Typesは
data:URL 経由の新規ドキュメントへのJSコードロードはガードしない)。 -
Webアプリ作者による悪意あるJavaScriptコードによる回避防止は目指さない。これに対処しようとすると設計が過度に複雑で非現実的になる。
1.3. ユースケース
-
作者が、UIコンポーネントの生成に安全なテンプレートシステムを利用するフレームワークベースの複雑なWebアプリを保守している。アプリは分析やパフォーマンス監視などの目的でサードパーティ製クライアントサイドライブラリにも依存している。いずれの要素もDOM XSS脆弱性を持ち込まないよう、作者はテンプレートライブラリ内でTrusted Typeポリシーを定義し、§ 2.1.1 DOM XSSインジェクションシンク の施行を有効化する。
-
あるウェブサイトが§ 2.1.1 DOM XSSインジェクションシンク を利用している。サイト開発者はTrusted Typesを加えて違反を Content-Security-Policy-Report-Only ヘッダーで監視する。 違反は安全なメソッドを使うようリファクタリングを繰り返して修正し、最終的には § 2.1.1 DOM XSSインジェクションシンク の呼び出しがなくなる。 以後 Trusted Types は不要となり、開発者はreport-onlyモードを解除して trusted-types および require-trusted-types-for ディレクティブでポリシーを無効化する。 このリファクタリング期間中、ウェブサイトの機能性は全く損なわれなかった。
-
大規模チームが複雑なクライアントサイドアプリを保守している。チームはアプリのセキュリティ要件を満たす複数のTrusted Typesポリシーを策定し、その実装や安全な抽象化コードを少数の厳重にレビューされたファイルに集約。これらのファイルへのコミットには追加承認を必須とする。
Trusted値の作成がインジェクションシンク への影響条件となること、およびポリシーコードに特別なレビューを課すことで、開発者はアドホックな文字列合成ではなく安全な抽象化を利用するよう動機づけられる。
DOM XSSリスク評価の際、セキュリティ監査者はCSPヘッダや安全な抽象化を提供する小さなコード部分だけに集中し、大半のアプリ本体コードは無視できる。
-
既存のWebアプリがDOMとのやりとりにほぼXSS安全パターン(§ 2.1.1 DOM XSSインジェクションシンク を使わない)を利用しているが、いくつか危険なパターン(JSONPで追加Script読み込み、
innerHTMLやevalの利用など)が残っている。レビューで、それらはXSSの原因とならない(ユーザ制御データが入力となっていないなど)ことは確認できたが、その使用箇所を完全排除するのは難しい。
そのためCSP強制は(
'unsafe-eval' 'unsafe-inline'など安全でない設定なしには)適用できない。また今後DOM XSSのあるコードが追加されるリスクもある。このリスクに対応するため、レビュー済み部分はTrusted Typesへ移行し、その施行(施行)を有効化する。今後インジェクションシンクの利用箇所が追加されると正しくブロック・報告される。
-
セキュリティチームがクライアントサイド中心のアプリにXSS脆弱性が存在しないことを保証する任務を負っている。このアプリのサーバ側はほぼAPIバックエンドで一様なので、Trusted Typesを施行すればレビュー対象はポリシーとそのルールだけで済む。後に審査済みポリシー名が 'trusted-types' CSPディレクティブで許可され、開発者が安全に利用できるようになる。
ポリシーを作らない限り、しばしば変更される依存コードを含め追加コードはレビュー不要。そうでない限りDOM XSSは発生し得ない。
2. フレームワーク
2.1. インジェクションシンク
このセクションは規範的なものではありません。
インジェクションシンク とは、 信頼できる検証済みまたは適切にサニタイズされた入力のみ呼び出すべき強力なWeb API関数です。 インジェクションシンクを攻撃者制御(つまりインジェクトされた)入力で呼ぶことは望ましくない結果を招き、セキュリティ脆弱性とみなされます。
注記: 本書で扱うインジェクションシンクの正確なリストは § 4 統合 に定義されています。
アプリにこの種の脆弱性(例: DOM XSS)があるかどうかを、インジェクションシンク
の呼び出しだけ分析しても判断は困難です。入力(通常は文字列)に由来情報が含まれないからです。例えばアプリが意図的に難読化などの目的でeval()に動的生成値を渡している場合でも、攻撃者由来でeval()に渡せば明確な脆弱性ですが、両者の区別は簡単ではありません。
本書ではシンクを、各グループがもつ能力に基づきグループ化します。グループへの 施行 は trusted-types-sink-group 値で制御します。
2.1.1. DOM XSSインジェクションシンク
このセクションは規範的なものではありません。
DOM XSS インジェクションシンク は入力文字列を評価し、その値が信頼できない場合DOM XSSにつながることがあります。
例として以下のようなものがあります:
-
コードをロードするURLを受け入れる
Element属性のセッター(例HTMLScriptElement.src) -
実行するコードを受け入れる
Element属性のセッター(例HTMLScriptElement.text) -
直接コードを実行する
evalなどの関数 -
'javascript:' URLへのナビゲーション
HTMLパーサは任意の要素や属性を生成できるため、 DOM XSS インジェクションシンク にはHTMLパース関連シンクも含まれます:
-
HTML文字列をパース・ドキュメントに挿入する
Element.innerHTML、ShadowRoot.innerHTML、Element.outerHTMLセッターやDocument.writeなど -
呼び出し元制御のマークアップ付きで同一オリジンの
Documentを生成するparseFromString()
DOM XSSインジェクションシンクのガードは、trusted-types-sink-group 'script' により制御されます。
2.2. Trusted Types
作者がインジェクションシンクに渡る値を制御できるようにするため、 § 2.2 Trusted Types を導入します。以下のリストは Trusted Type を示し、それぞれが特定の文脈で インジェクションシンク に安全に使えると作者が判断した値を意味します。
注記: ここでの Trusted は、作者がその値はインジェクションシンクに安全に使えると「信じている(trust)」のであって、実際に安全かどうかを意味しません。
注記: 作者は値作成時に意図を指定でき、ユーザーエージェント側でも型に基づくチェックで意図を守れるようになります。例えばHTMLスニペットとして使う意図の値でスクリプトロードしようとすれば失敗します。
注記: すべてのTrusted Typesは生成時に不変な文字列を被包します。これらのオブジェクトは偽造不能で、内部スロットに値がセットされsetterは公開されていません。
注記: すべてのTrusted Typesのstringifierは内部の文字列値を返します。これにより、コードを徐々にTrusted Typesへ移行(部分的に型を導入しつつ他所ではまだDOM文字列を使い受け入れる)しやすくなっています。この意味で、Trusted Typesは通常のDOM APIと後方互換性があります。
2.2.1. TrustedHTML
TrustedHTMLインターフェースは、開発者が信頼しHTMLとして描画する インジェクションシンク に安全に挿入できると判断した文字列オブジェクトを表します。
これらは TrustedTypePolicy
の
createHTML
メソッドによって構築される不変のラッパーです。
[Exposed =(Window ,Worker )]interface TrustedHTML {stringifier ;DOMString toJSON (); };
TrustedHTMLオブジェクトは文字列 data を持ちます。 値は生成時にセットされ、生存期間中は変化しません。
toJSON() メソッド手順および
TrustedHTMLオブジェクトの stringification動作 の手順は、関連 data 値を返します。
2.2.2. TrustedScript
TrustedScriptインターフェースは、開発者が インジェクションシンク へ自信を持って渡せる未コンパイルスクリプト本体文字列を表します。
これらも TrustedTypePolicy
の
createScript
メソッドで構築される不変ラッパーです。
[Exposed =(Window ,Worker )]interface TrustedScript {stringifier ;DOMString toJSON (); };
TrustedScriptオブジェクトは文字列 data を持ちます。 値は生成時にセットされ、生存期間中は変化しません。
toJSON() メソッド手順および
TrustedScriptオブジェクトの stringification動作 の手順は、関連 data 値を返します。
2.2.3. TrustedScriptURL
TrustedScriptURLインターフェースは、開発者が外部スクリプトリソースのURLとして インジェクションシンク へ自信を持って渡せる文字列を表します。
これも TrustedTypePolicy
の
createScriptURL
メソッドで構築される不変ラッパーです。
[Exposed =(Window ,Worker )]interface TrustedScriptURL {stringifier ;USVString toJSON (); };
TrustedScriptURLオブジェクトは文字列 data を持ちます。 値は生成時にセットされ、生存期間中は変化しません。
toJSON() メソッド手順および
TrustedScriptURLオブジェクトの stringification動作 の手順は、関連 data 値を返します。
2.3. ポリシー
Trusted Types は、文字列を指定の Trusted Type オブジェクトに変換するルールを定義するユーザー定義かつ不変のポリシーを通じてのみ作成可能です。ポリシーによって、作者は Trusted Types が遵守すべきカスタムなプログラムルールを指定できます。
TrustedHTML
オブジェクトは、アプリ内で安心して利用でき、innerHTML
などに渡しても、入力が攻撃者制御の値であってもポリシールールによって安全な内容に変換されます。
const sanitizingPolicy= trustedTypes. createPolicy( 'sanitize-html' , { createHTML: ( input) => myTrustedSanitizer( input, { superSafe: 'ok' }), }); myDiv. innerHTML= sanitizingPolicy. createHTML( untrustedValue);
注記: Trusted Type オブジェクトは作者が明示的に信頼した値を包みます。このため、Trusted Type のインスタンス生成自体が実質 インジェクションシンク となるため、Trusted Type 生成コードはセキュリティ上重要です。Trusted Type オブジェクト作成の厳格な制御を可能にするため、コンストラクタは曝露されておらずポリシー経由の生成のみが許されています。
一つの Realm で複数のポリシーを作成でき、コードベースの異なる部分で異なるルールを定義可能です。
const cdnScriptsPolicy= trustedTypes. createPolicy( 'cdn-scripts' , { createScriptURL( url) { const parsed= new URL( url, document. baseURI); if ( parsed. origin== 'https://mycdn.example' ) { return url; } throw new TypeError ( 'invalid URL' ); }, }); myLibrary. init({ policy: cdnScriptsPolicy});
注記: Trusted Type オブジェクトはポリシー経由でのみ作成できます。施行が有効な場合、ポリシーコードだけがインジェクションシンク
の動作を誘発でき、ポリシーcreate*関数の呼び出し元だけがセキュリティ上重要になります。アプリ全体のうちごく小さなサブセットだけをレビューすれば良く、シンク自体を監視・レビューする必要はありません。ユーザーエージェントが型付きオブジェクトのみにシンクを許可し、それは必ずポリシー経由でのみ生成されるためです。
createPolicy
関数は、ポリシーオブジェクトを返します。この create* 関数がポリシールールを適用してTrusted Typeオブジェクトを生成します。
注記:
入力をサニタイズするポリシーはアプリ内どこでも自由に使って構いませんが、著者制御の入力だけを対象とする緩やかなポリシー(例:
クライアントサイドHTMLテンプレート、HTMLサニタイズライブラリ、非同期コードプラグインなど)が必要になる場合もあります。各ポリシーは返り値としてポリシーを参照できる場所のみで使えます(createPolicy())。従ってポリシー参照は
オブジェクト能力
としてJavaScriptのクロージャや内部変数、モジュール等で管理できます。
( function renderFootnote() { const unsafePolicy= trustedTypes. createPolicy( 'html' , { createHTML: input=> input, }); const footnote= await fetch( '/footnote.html' ). then( r=> r. text()); footNote. innerHTML= unsafePolicy. createHTML( footnote); })();
2.3.1.
TrustedTypePolicyFactory
TrustedTypePolicyFactory は
ポリシー
を作成し、Trusted Type オブジェクトのインスタンスが
いずれかのポリシーを通じて作られたことを検証します。
注記: このファクトリーオブジェクトはグローバルオブジェクトの
trustedTypes プロパティを通して JavaScript から利用可能です。詳しくは § 4.1.1 WindowOrWorkerGlobalScope
インターフェースへの拡張 を参照してください。
[Exposed =(Window ,Worker )]interface TrustedTypePolicyFactory {TrustedTypePolicy createPolicy (DOMString ,policyName optional TrustedTypePolicyOptions = {});policyOptions boolean isHTML (any );value boolean isScript (any );value boolean isScriptURL (any );value readonly attribute TrustedHTML emptyHTML ;readonly attribute TrustedScript emptyScript ;DOMString ?getAttributeType (DOMString ,tagName DOMString ,attribute optional DOMString ?= "",elementNs optional DOMString ?= "");attrNs DOMString ?getPropertyType (DOMString ,tagName DOMString ,property optional DOMString ?= "");elementNs readonly attribute TrustedTypePolicy ?defaultPolicy ; };
TrustedTypePolicyFactory
オブジェクトは TrustedTypePolicy
に対応する デフォルトポリシー を持ちます。
初期値は null です。
TrustedTypePolicyFactory
オブジェクトは文字列の 順序付きセット 生成済みポリシー名
を持ちます。
初期値は « » です。
createPolicy(policyName, policyOptions)-
TrustedTypePolicyOptionspolicyOptions オブジェクトで渡すルールを実装するポリシーオブジェクトを生成します。 許可されるポリシー名は Content Security Policy で制限される場合があります。 trusted-types CSP ディレクティブでホワイトリストにないポリシー名の場合、TypeError で失敗します。 また、固有名が強制され('allow-duplicates'が使われていない場合)、同じpolicyNameで2回以上createPolicyを呼び出した場合もTypeErrorで失敗します。// HTTP レスポンスヘッダー: Content-Security-Policy: trusted-types foo trustedTypes. createPolicy( "foo" , {}); // ok. trustedTypes. createPolicy( "bar" , {}); // 失敗 - 名称がホワイトリストにない trustedTypes. createPolicy( "foo" , {}); // 失敗 - 重複名 Trusted Type ポリシー作成 アルゴリズムを次の引数で実行した結果を返します:
- factory
- this の値
- policyName
- policyName
- options
- policyOptions
- global
- this 値の 関連グローバルオブジェクト
const myPolicy= trustedTypes. createPolicy( 'myPolicy' , { // このセキュリティクリティカルなコードはレビューが必要です; // このコードに脆弱性があるとDOM XSSにつながります。 createHTML( input) { return aSanitizer. sanitize( input) }, createScriptURL( input) { const u= new URL( dirty, document. baseURI); if ( APPLICATION_CONFIG. scriptOrigins. includes( u. origin)) { return u. href; } throw new Error ( 'このオリジンのスクリプトは許可されません' ); }, }); document. querySelector( "#foo" ). innerHTML= myPolicy. createHTML( aValue); scriptElement. src= myPolicy. createScriptURL( 'https://scripts.myapp.example/script.js' ); isHTML(value)-
value が
TrustedHTMLのインスタンスで、data 値が設定されている場合 true、そうでなければ false を返します。注記:
is*系関数は、与えられたオブジェクトが本当に正当な Trusted Type(設定済みポリシーのいずれかで作成)か検査するために利用します。例えば Object.create やプロトタイプチェーン改変による偽造の検出に使えます。 isScript(value)-
value が
TrustedScriptのインスタンスで、data 値が設定されている場合 true、それ以外は false。 isScriptURL(value)-
value が
TrustedScriptURLのインスタンスで、data 値が設定されていれば true、そうでなければ false。 getPropertyType(tagName, property, elementNs)-
作者が、指定の
Elementプロパティ(IDL属性)に Trusted Type が必要かどうかを確認できます。この関数は次のアルゴリズムの結果を返します:
-
tagName を ASCII小文字 にして localName とする。
-
elementNs が null または空文字列なら HTML名前空間にする。
-
interface に localName と elementNs に対応する 要素インターフェース をセットする。
-
expectedType を null にする。
-
次の表の1列目が "*" または interface の名前で、property が2列目にある行を探す。一致する行があれば expectedType を3列目のインターフェース名にする。
要素 プロパティ名 TrustedType HTMLIFrameElement"srcdoc" TrustedHTMLHTMLScriptElement"innerText" TrustedScriptHTMLScriptElement"src" TrustedScriptURLHTMLScriptElement"text" TrustedScriptHTMLScriptElement"textContent" TrustedScript"*" "innerHTML" TrustedHTML"*" "outerHTML" TrustedHTML -
expectedType を返す。
-
getAttributeType(tagName, attribute, elementNs, attrNs)-
作者が、指定の
Elementの内容属性に対して Trusted Type が必要か(必要ならどれか)を確認し、後でElement.setAttributeの呼び出し時に型を正しくセットできるようにします。この関数は次のアルゴリズムの結果を返します:
-
tagName をASCII小文字にする。
-
attribute をASCII小文字にする。
-
elementNs が null または空文字なら HTML名前空間にする。
-
attrNs が空なら null にする。
-
interface を localName と elementNs から 要素インターフェースに求める。
-
expectedType を null にする。
-
属性用Trusted Typeデータ取得アルゴリズムの次の引数を使って、 attributeData にセットする:
-
interface(elementとして)
-
attribute
-
attrNs
-
-
attributeData が nullでなければ、expectedType に attributeData の4番目の値のインターフェース名をセットする。
-
expectedType を返す。
-
emptyHTML, 型 TrustedHTML、readonly-
TrustedHTMLオブジェクトで、data 値は空文字列。
emptyScript, 型 TrustedScript、readonly-
TrustedScriptオブジェクトで、data 値は空文字列。
注記: このオブジェクトは実行時環境が動的コードコンパイルをサポートするか検出するのに使えます。
ネイティブの Trusted Types 実装なら eval(TrustedScript) で実行・偽になり、ポリフィルでは eval(TrustedScript) は
unwrap・評価せずオブジェクトを返します。
// ネイティブ Trusted Types なら eval(trustedTypes.emptyScript) で undefined(偽値)を実行・返却 // 非対応なら eval(trustedTypes.emptyScript) で真値のObjectを返却 const supportsTS= ! eval( trustedTypes. emptyScript); eval( supportsTS? myTrustedScriptObj: myTrustedScriptObj. toString());
defaultPolicy, 型 TrustedTypePolicy、readonly, nullable-
デフォルトポリシー の値を返します。
2.3.2. TrustedTypePolicy
ポリシーオブジェクトは TrustedTypePolicy インターフェースを実装し、Trusted Type オブジェクトを生成する関数群を定義します。
各 create* 関数は、文字列値を指定された Trusted Type バリアントに変換するか、与えられた値の変換が許可されていない場合は TypeError をスローします。
[Exposed =(Window ,Worker )]interface TrustedTypePolicy {readonly attribute DOMString ;name TrustedHTML createHTML (DOMString ,input any ...);arguments TrustedScript createScript (DOMString ,input any ...);arguments TrustedScriptURL createScriptURL (DOMString ,input any ...); };arguments
各ポリシーには name があります。
各 TrustedTypePolicy オブジェクトには、TrustedTypePolicyOptions
options オブジェクトが関連付けられており、ポリシーの具体的な動作を記述します。
createHTML(input, ...arguments)-
Create a Trusted Type アルゴリズムを次の引数で実行した結果を返します:
- policy
- this 値
- trustedTypeName
"TrustedHTML"- value
- input
- arguments
- arguments
createScript(input, ...arguments)-
Create a Trusted Type アルゴリズムを次の引数で実行した結果を返します:
- policy
- this 値
- trustedTypeName
"TrustedScript"- value
- input
- arguments
- arguments
createScriptURL(input, ...arguments)-
Create a Trusted Type アルゴリズムを次の引数で実行した結果を返します:
- policy
- this 値
- trustedTypeName
"TrustedScriptURL"- value
- input
- arguments
- arguments
2.3.3.
TrustedTypePolicyOptions
このディクショナリは、文字列値を信頼済みの値へ変換するための著者定義の関数を保持します。これらの関数はTrusted Type
オブジェクトインスタンスを直接生成しません—この動作は
TrustedTypePolicy
によって提供されます。
dictionary TrustedTypePolicyOptions {CreateHTMLCallback ;createHTML CreateScriptCallback ;createScript CreateScriptURLCallback ; };createScriptURL callback =CreateHTMLCallback DOMString ? (DOMString ,input any ...);arguments callback =CreateScriptCallback DOMString ? (DOMString ,input any ...);arguments callback =CreateScriptURLCallback USVString ? (DOMString ,input any ...);arguments
2.3.4. デフォルトポリシー
このセクションは規範的ではありません。
ポリシーの一つである name が "default" のポリシーは特別です。
インジェクションシンク に Trusted Type
オブジェクトの代わりに文字列が渡された場合、このポリシーがユーザーエージェントにより、信頼されていない文字列値・シンクの Trusted Type およびシンクタイプとともに暗黙的に呼び出されます。
これにより、バイオレーションを引き起こさずにアプリケーションのフォールバック動作を定義できます。これは予期しないデータフローから復帰し、潜在的に攻撃者制御の文字列を「最後の手段」としてサニタイズ、あるいは安全な値が作成できない場合には値を拒否することを意図しています。ポリシー内でスローされたエラーはアプリケーションに伝播されます。
デフォルトポリシーが存在しない場合や、該当する create* 関数が null または undefined
を返した場合、CSPバイオレーションとなります。enforcing モードではエラーがスローされますが、report-only の場合はデフォルトポリシーに渡された元の値が使われます。
Note: このオプションの動作により、インジェクションシンクを使用しているレガシーコードを使用するアプリケーションに Trusted Type enforcement を導入できます。 当然ながら、このポリシーは必ず極めて厳格なルールで定義し、アプリケーションの不明な部分でセキュリティ制約をバイパスしないようにすべきです。極端な場合、緩い(no-op の)デフォルトポリシーでは Trusted Types のメリットがすべて無意味になります。可能であれば、著者は移行期間中のみデフォルトポリシーに頼り、インジェクションシンクの安全でない利用を検出・書き換え、最終的にはデフォルトポリシーの利用を完全に廃止すべきです。
Note: デフォルトポリシーの適用方法については、§ 3.4 Get Trusted Type compliant string を参照してください。
// Content-Security-Policy: trusted-types default; require-trusted-types-for 'script' trustedTypes. createPolicy( 'default' , { createScriptURL: ( value, type, sink) => { console. log( "Please refactor." ); return value+ '?default-policy-used&type=' + encodeURIComponent( type) + '&sink=' + encodeURIComponent( sink); } }); aScriptElement. src= "https://cdn.example/script.js" ; // Please refactor. console. log( aScriptElement. src); // https://cdn.example/script.js?default-policy-used&type=TrustedScriptURL&sink=HTMLScriptElement%20src
2.4. 強制
Note: 強制は、値が インジェクションシンク に到達する前に、適切な型であることを検証するプロセスです。
著者がポリシーや Trusted Types オブジェクトを作成するための JavaScript API は常に利用可能です(trustedTypes
経由)。
インジェクションシンク
はセキュリティ上重要な引数を文字列化し、Trusted Type
オブジェクトも内部の文字列値に文字列化されるため、著者は Trusted Types を文字列の代わりとして利用できます。
インジェクションシンク へのアクセスを保護するには、Trusted Types を使った JavaScript に加え、 ユーザーエージェントがそれを強制する、すなわち、与えられたグループのインジェクションシンクが 決して 文字列値で呼び出されず、代わりに Trusted Type 値が使われていることを保障する必要があります。このセクションは著者がその強制動作をどう制御できるかを説明します。
著者はまた ポリシー の生成に関するルールを指定することで、ポリシー自体の管理も可能です。
2.4.1. Content Security Policy
アプリケーションは Content Security Policy の設定 を通じて Trusted Type の強制を制御できます。 本ドキュメントは Trusted Types のルールに対応する新しいディレクティブを定義します。 require-trusted-types-for ディレクティブは、 型が必要とされる インジェクションシンク のグループを指定します。 trusted-types ディレクティブは ポリシー の作成方法を制御します。
Note: CSP メカニズムを利用すると、Content-Security-Policy-Report-Only HTTP Response ヘッダー経由で Trusted Types の強制に備えることができます。
Note: 多くの強制ルールは他仕様のアルゴリズムの修正として定義されているため、§ 4 Integrations を参照してください。
3. アルゴリズム
3.1. Trusted Type ポリシーの作成
Trusted Type
ポリシーを作成するには、TrustedTypePolicyFactory
(factory)、文字列 (policyName)、TrustedTypePolicyOptions
ディクショナリ (options)、および
グローバルオブジェクト (global) が与えられたとき、以下の手順を実行します。
-
allowedByCSP を Content Security Policy によって Trusted Type ポリシーの生成をブロックすべきか アルゴリズムを global, policyName, factory の created policy names 値で実行した結果にしてください。
-
allowedByCSP が
"Blocked"であれば、TypeError をスローし、それ以上の手順を中止する。 -
policyName が
defaultかつ factory の default policy 値が null でない場合、TypeError をスローし、それ以上の手順を中止する。 -
policy を新しい
TrustedTypePolicyオブジェクトとする。 -
policy の
nameプロパティの値を policyName に設定する。 -
policy の options 値を «[ "createHTML" -> options["
createHTML", "createScript" -> options["createScript", "createScriptURL" -> options["createScriptURL" ]» に設定する。 -
policyName が
defaultの場合、factory の default policy 値を policy に設定する。 -
Append policyName を factory の created policy names に追加する。
-
policy を返す。
3.2. Trusted Type の作成
Trusted Type
を作成するには、TrustedTypePolicy
policy、型名 trustedTypeName、文字列 value、リスト arguments
が与えられたとき、次の手順を実行します。
-
policyValue を get trusted type policy value を同じ引数と追加で true (throwIfMissing) で実行した結果にする。
-
アルゴリズムがエラーをスローした場合はそのままエラーを再スローし以後の手順を中止。
-
dataString を policyValue を文字列化した結果にする。
-
policyValue が null か undefined の場合、dataString を空文字列に設定する。
-
型名 trustedTypeName のインターフェースの新しいインスタンスを dataString をデータ値として返す。
3.3. Trusted Type policy value の取得
get trusted
type policy valueには、TrustedTypePolicy
policy、型名 trustedTypeName、文字列 value、リスト arguments、ブール
throwIfMissing が与えられたとき、以下の手順を実行します。
-
functionName を、次の表に基づき与えられた trustedTypeName のための関数名とする:
関数名 Trusted Type 名 "createHTML" "TrustedHTML" "createScript" "TrustedScript" "createScriptURL" "TrustedScriptURL" -
function を policy の options[functionName] にする。
-
function が
nullなら:-
throwIfMissing が真なら TypeError をスロー。
-
偽なら
nullを返す。
-
-
args を « value » にする。
-
Append で arguments の各要素を args に追加する。
-
policyValue を コールバック関数の呼び出し を function と args、
"rethrow"で実行した結果にする。 -
policyValue を返す。
3.4. Trusted Type 準拠文字列を取得する
このアルゴリズムは、インジェクションシンクで使用できる文字列を返します。必要に応じて対応するTrusted Typeからアンラップします。 また、Trusted Type の強制ルールが遵守されたことを保証します。
Trusted Type
準拠文字列を取得するには、TrustedType
型 (expectedType)、グローバルオブジェクト (global)、
TrustedType
または文字列 (input)、文字列 (sink) および文字列 (sinkGroup) を受け取り、次の手順を実行します。
-
input が expectedType のインスタンスである場合、input を文字列化して返し、この手順を中止します。
-
requireTrustedTypes を このシンクタイプは Trusted Types を要求するか? アルゴリズムを global、sinkGroup、および true で実行した結果にします。
-
requireTrustedTypes が
falseなら、input を文字列化して返し、この手順を中止します。 -
convertedInput を デフォルトポリシーで値を処理するを本アルゴリズムの同じ引数で実行した結果にします。
-
アルゴリズムがエラーをスローした場合、そのエラーを再スローし、以後の手順を中止します。
-
convertedInput が
nullまたはundefinedの場合、次の手順を実行します:-
disposition を シンク型不一致バイオレーションは CSP によりブロックされるべきかアルゴリズムを global、文字列化した input を source、 sinkGroup と sink で実行した結果にします。
-
disposition が
“Allowed”なら、input を文字列化して返し、この手順を中止します。Note: このステップにより、デフォルトポリシーの拒否が報告されますが、report-only モードでは無視されます。
-
TypeError をスローし、それ以上の手順を中止します。
-
-
アサート: convertedInput は expectedType のインスタンスです。
-
convertedInput を文字列化して返します。
3.5. デフォルトポリシーで値を処理する
このアルゴリズムは、値を インジェクションシンクに割り当てる際、デフォルトポリシーが存在する場合はそれを経由させます。
デフォルトポリシーで値を処理するには、TrustedType
型 (expectedType)、グローバルオブジェクト (global)、
TrustedType
または文字列 (input)、文字列 (sink) を受け取り、次の手順を実行します:
-
defaultPolicy を global のtrusted type policy factory のdefault policyの値にします。
-
policyValue をget trusted type policy valueを以下の引数で実行した結果にします:
-
policy:defaultPolicy
-
value:文字列化したinput
-
trustedTypeName:expectedTypeの型名
-
arguments:« trustedTypeName, sink »
-
throwIfMissing:false
-
-
アルゴリズムがエラーをスローした場合、それを再スローし、以降の手順を中止します。
-
policyValue が null または undefined なら policyValue を返します。
-
dataString を policyValue を文字列化した結果とします。
-
型名 trustedTypeName のインターフェースの新しいインスタンスを、そのデータ値に dataString を設定して返します。
3.6. スクリプト本文の準備
スクリプト本文の準備は、HTMLScriptElement
またはSVGScriptElement
(script) を受け取って、以下の手順を実行します。
-
script が
HTMLScriptElementなら sink を "HTMLScriptElement text"、そうでなければ "SVGScriptElement text" とします。 -
script のscript text値がchild text contentと等しくない場合、scriptのscript textを、 Trusted Type 準拠文字列を取得するを以下の引数で実行した結果に設定する:
-
expectedType:
TrustedScriptURL -
global:scriptの
Documentのrelevant global object -
input:script のchild text content 属性値
-
sink
-
sinkGroup:
'script'
アルゴリズムがエラーをスローした場合、それを再スローします。
-
3.7. Trusted Type 準拠属性値を取得する
Trusted Type 準拠属性値を取得するには、
文字列attributeName、文字列attributeNs、Element
element、そしてTrustedType
または文字列newValueを受け取り、以下を実行します:
-
attributeNsが空文字列の場合、attributeNsをnullに設定します。
-
attributeData を、次の引数でget Trusted Type data for attribute アルゴリズムを実行した結果にします:
-
element
-
attributeName
-
attributeNs
-
-
attributeData が null の場合:
-
newValue が文字列なら newValue を返します。
-
アサート: newValue は
TrustedHTMLまたはTrustedScriptまたはTrustedScriptURLです。 -
value の関連データを返します。
-
-
expectedType を attributeData の4番目のメンバーの値にします。
-
sink を attributeData の5番目のメンバーの値にします。
-
Trusted Type 準拠文字列を取得する を次の引数で実行して返します:
-
expectedType
-
input:newValue
-
elementのnode documentのrelevant global objectをglobal
-
sink
-
sinkGroup:'script'
-
アルゴリズムがエラーをスローした場合、それを再スローします。
3.8. 属性の Trusted Type データを取得する
属性の Trusted Type データを取得するには、element、attribute、 attributeNs を受け取り、以下の手順を実施します:
以下で使用されるイベントハンドラーコンテンツ属性の概念は曖昧です。この仕様はイベントハンドラー属性を特定するためのより良い仕組みが必要です。詳細は https://github.com/w3c/trusted-types/issues/520 を参照してください。
-
data を null にします。
-
attributeNs が null で、 « HTML 名前空間、SVG 名前空間、MathML 名前空間 » に element の namespace が含まれ、かつ attribute が イベントハンドラーコンテンツ属性名の場合:
-
(
Element, null, attribute,TrustedScript, "Element " + attribute) を返します。
-
-
下記の表の中で element が1列目、attributeNs が2列目、attribute が3列目に一致する行を探し、 一致する行があれば data をその行で設定します。
Element Attribute namespace Attribute local name TrustedType Sink HTMLIFrameElementnull "srcdoc" TrustedHTML"HTMLIFrameElement srcdoc" HTMLScriptElementnull "src" TrustedScriptURL"HTMLScriptElement src" SVGScriptElementnull "href" TrustedScriptURL"SVGScriptElement href" SVGScriptElementXLink 名前空間 "href" TrustedScriptURL"SVGScriptElement href" -
data を返します。
4. 統合
typedef (TrustedHTML or TrustedScript or TrustedScriptURL );TrustedType
4.1. HTMLとの統合
Window
および Worker
オブジェクトは trusted type policy factory を持ち、
これは TrustedTypePolicyFactory
オブジェクトです。
4.1.1. WindowOrWorkerGlobalScope インターフェイスの拡張
このドキュメントは WindowOrWorkerGlobalScope
インターフェイス(HTML で定義)を拡張します:
partial interface mixin WindowOrWorkerGlobalScope {readonly attribute TrustedTypePolicyFactory ; };trustedTypes
trustedTypes
のgetterステップは、thisの関連グローバルオブジェクト の trusted type
policy factory を返します。
4.1.2. スクリプトに対する強制
このドキュメントは、HTMLScriptElement
のchild text content
を動的に作成するスクリプトを制御できるようにするための設定方法を修正します。それにより innerText
と textContent
属性を HTMLScriptElement
へ直接追加します。
元の属性と動作は同じですが、Trusted Type 準拠文字列を取得する 呼び出しの追加挙動があります。
Note: これらのIDL属性を利用することは、スクリプトのURLやテキストを動的に設定する推奨手段です。属性ノードやテキストノードを直接操作する場合でも、最終値のスクリプト準備時にデフォルトポリシーが呼ばれます。
partial interface HTMLScriptElement { [CEReactions ]attribute (TrustedScript or [LegacyNullToEmptyString ]DOMString ); [innerText CEReactions ]attribute (TrustedScript or DOMString )?; [textContent CEReactions ]attribute (TrustedScriptURL or USVString ); [src CEReactions ]attribute (TrustedScript or DOMString ); };text
4.1.2.1. Trusted 値付きスロット
HTMLScriptElement
および SVGScriptElement
には次があります:
- 関連付けられた文字列 script text
-
適合するシンクから設定された、実行するスクリプト本体の文字列。script要素のchild text contentと等価。初期値は空文字列。
4.1.2.2.
innerText
IDL属性
innerText
のsetter手順:
-
value を Trusted Type 準拠文字列を取得する(
TrustedScript, this の relevant global object, 与えられた値,HTMLScriptElement innerText,script)で得た結果とします。 -
this の script text を value に設定します。
-
set the inner text steps を this と value で実行します。
innerText
の getter 手順:
-
get the text steps を this で実行し、結果を返します。
4.1.2.3.
textContent
IDL 属性
textContent
の setter 手順は、与えられた値が null の場合は空文字列として扱い、以下に記載の通り処理します。
-
value を Trusted Type 準拠文字列を取得する(
TrustedScript, this の 関連グローバルオブジェクト, 与えられた値,HTMLScriptElement textContent,script)の結果にする。 -
this の script text の値を value に設定する。
-
set text content を this と value で実行する。
textContent
の getter 手順は:
-
get text content を this で実行し、その結果を返す。
Note: 現状、SVGScriptElement
相当のものは追加されていません。
詳細は https://github.com/w3c/trusted-types/issues/512
を参照。
4.1.2.4.
text
IDL 属性
text
の setter 手順アルゴリズムを以下のように更新します。
-
value を Trusted Type 準拠文字列を取得する(
TrustedScript, this の 関連グローバルオブジェクト, 与えられた値,HTMLScriptElement text,script)の結果にする。 - this の script text の値を与えられた値に設定する。
-
String replace all を与えられた値に対して this で実行する。
4.1.2.5.
src
IDL 属性
src
の getter 手順は:
- element を this で要素を取得した結果とする。
- contentAttributeValue を this で内容属性を取得した結果とする。
- contentAttributeValue が null なら、空文字列を返す。
- urlString を element の node document を基準として contentAttributeValue の URL エンコード・パース・シリアライズした結果とする。
- urlString が失敗でない場合、urlString を返す。
- contentAttributeValue をスカラ値文字列に変換して返す。
src
の setter 手順は:
-
value を Trusted Type 準拠文字列を取得する(
TrustedScriptURL, this の 関連グローバルオブジェクト, 与えられた値,HTMLScriptElement src,script)の結果にする。 - this の src 内容属性を value に設定する。
4.1.2.6. パーサによるスロット値の設定
本ドキュメントはHTMLパーサを修正し、スクリプト作成時にscript text値を設定します。
The text insertion mode アルゴリズムを以下のように修正します:
- タグ名が "script" の終了タグ
-
...
script の script text の値を、その child text content に設定する。
アクティブな投機的HTMLパーサがnullなら、スクリプト要素を準備する script。 これによりスクリプトが実行される場合があり、追加の文字がトークナイザに挿入される場合や、 トークナイザがさらにトークンを出力し、パーサのリエントラント呼び出しとなることがあります。
...
上記アルゴリズムはスクリプト要素の内容が解析中に変更されるケースに対応していません。 実装者はこのケースへの対策が必要です。詳細は https://github.com/w3c/trusted-types/issues/507 を参照。
SVGスクリプト要素の処理に正式な定義がありません。
ただし、実装ではSVGScriptElementの処理にも同様の変更を適用する必要があります。
4.1.2.7. スロット値の検証
スクリプト要素を準備する アルゴリズムの最初のいくつかのステップは以下のように修正されます:
-
el の already started が true の場合は return。
-
parser document を el の parser document に設定する。
-
el の parser document を null に設定する。
これは parser 挿入済み
script要素の実行がパーサで失敗した際に、例えば空だったりサポートされていないスクリプト言語を指定していた場合に、別のスクリプトによる変更によって再度実行されるようにするためです。 -
parser document が null でなく、 el が
async属性を持たない場合、el の force async を true に設定する。これは parser 挿入済み
script要素がパーサでの実行に失敗し、その後動的変更によって実行可能になった場合でも async 属性の有無に関わらず非同期で実行されるようにするためです。 -
el に対し スクリプト本文の準備 アルゴリズムを実行する。 そのアルゴリズムがエラーをスローした場合は return。
-
source text を
child text contentscript text の値 に設定する。 - ...
SVGスクリプト要素の処理に正式な定義がありません。
ただし、実装ではSVGScriptElementの処理にも同様の変更を適用する必要があります。
4.2. DOMとの統合
Note: この統合のアップストリームについては https://github.com/whatwg/dom/pull/1268 を参照してください。
4.3. Content Security Policyとの統合
4.3.1. require-trusted-types-for ディレクティブ
本ドキュメントでは require-trusted-types-for という新しい Content Security Policy ディレクティブ を定義します。
require-trusted-types-for ディレクティブは、現在の インジェクションシンクのグループ全体に対して Trusted Types フレームワークを構成します。 具体的には、与えられたグループの インジェクションシンク に文字列値が渡された場合の挙動(つまり型ベースの強制を有効にするかどうか)を定義します。
Note: 現時点では § 2.1.1 DOM XSSインジェクションシンク の強制のみが定義されています。
このディレクティブの 名前 および 値 の構文は次の ABNF で記述されます:
directive-name = "require-trusted-types-for" directive-value = trusted-types-sink-group-keyword *( required-ascii-whitespace trusted-types-sink-group-keyword) trusted-types-sink-group-keyword = "'" trusted-types-sink-group "'" trusted-types-sink-group = "script"
Content-Security-Policy: require-trusted-types-for 'script'
4.3.1.1. require-trusted-types-for
プリナビゲーション・チェック
リクエスト (request)、文字列 navigation type、ポリシー (policy) を受け取り、以下の場合に
"Blocked" を返し、それ以外は "Allowed" を返します。これが
require-trusted-types-for ディレクティブの プリナビゲーション・チェックとなります:
Note: このアルゴリズムは javascript: URL の実行コードも
デフォルトポリシー の createScript 関数を通す必要があることを保証します。他の
CSP ディレクティブの制限にも加えて適用されます。
-
request の url の スキーム が
"javascript"でなければ"Allowed"を返し以降の手順を中止。 -
encodedScriptSource を urlString の
"javascript:"を取り除いたものとする。 -
convertedScriptSource を デフォルトポリシーで値を処理する アルゴリズムを、次を引数に実行した結果とする:
-
TrustedScriptを expectedType -
request の clients の グローバルオブジェクト を global
-
encodedScriptSource を input
-
"Location href"を sink とする
このアルゴリズムがエラーを投げた場合や convertedScriptSource が
TrustedScriptオブジェクトでない場合、"Blocked" を返し中止。 -
-
urlString を
"javascript:"を先頭に付けて convertedScriptSource を文字列化した値に設定する。 -
newURL を URLパーサ で urlString を実行した結果とする。パーサが失敗を返す場合、"Blocked" を返し、それ以降の手順を中止。
-
request の url を newURL に設定する。
Note: 他の CSP ディレクティブはプリナビゲーションチェックでは
javascript:URL を操作しません。他ディレクティブは、後で インラインチェックで修正後のURLで実行されます。 -
"Allowed"を返します。
4.3.2. trusted-types ディレクティブ
本ドキュメントでは trusted-types という新しい Content Security Policy ディレクティブ を定義します。trusted-types ディレクティブは Trusted Type の ポリシー作成 を制御します。
このディレクティブの 名前 および 値 の構文は次のABNFで記述されます:
directive-name = "trusted-types" directive-value = serialized-tt-configuration serialized-tt-configuration = ( tt-expression *( required-ascii-whitespace tt-expression ) ) tt-expression = tt-policy-name / tt-keyword / tt-wildcard tt-wildcard = "*" tt-policy-name = 1*( ALPHA / DIGIT / "-" / "#" / "=" / "_" / "/" / "@" / "." / "%") tt-keyword = "'allow-duplicates'" / "'none'"
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types one two
Content-Security-Policy: trusted-types; require-trusted-types-for 'script'
キーワード 'none' は上記を明示的に示すために使用できます:
キーワード 'allow-duplicates' を使うと同名のポリシーを複数作成できます。
default という名前のポリシーがリストに含まれる場合、それはデフォルトポリシーを指します。
全ての文字列が直接拒否される代わりに、このポリシーを経由して インジェクションシンクに渡されます。
4.3.3. このシンクタイプは Trusted Types を要求するか?
このアルゴリズムは、インジェクションシンク が Trusted Type を必要とする場合は
true を、そうでなければ false を返します。
このシンクタイプは Trusted Types を要求するか?アルゴリズムは、グローバルオブジェクト (global)、文字列 (sinkGroup) およびブール値 (includeReportOnlyPolicies) を受け取り、次のステップを実行します:
-
global の CSPリスト 内の各 policyについて:
-
policy の ディレクティブセットに ディレクティブ で 名前 が
"require-trusted-types-for"のものがない場合は、次の policy にスキップ。 -
directive を policy の ディレクティブセット の中で 名前が
"require-trusted-types-for"の ディレクティブ とする。 -
directive の 値 が trusted-types-sink-group で sinkGroup に合致するものを含まない場合、次の policy にスキップ。
-
enforced を policy の ディスポジション が
"enforce"であれば true、そうでなければ false にする。 -
enforced が true なら true を返す。
-
includeReportOnlyPolicies が true なら true を返す。
-
-
false を返す。
4.3.4. シンク型不一致の違反はContent Security Policyでブロックされるべきか?
このアルゴリズムは、インジェクションシンク が Trusted Type を必要とする場合は
"Blocked" を、そうでなければ "Allowed" を返します。
シンク型不一致の違反はContent Security Policyでブロックされるべきか?アルゴリズムは、グローバルオブジェクト (global)、文字列 (sink)、文字列 (sinkGroup)、文字列 (source) を受け取り、次の手順を実行します:
-
result を
"Allowed"にする。 -
sample を source にする。
-
sink が
"Function"の場合:-
sample が
"function anonymous"で始まるなら、そこを取り除く。 -
そうでなく sample が
"async function anonymous"で始まるなら、そこを取り除く。 -
そうでなく sample が
"function* anonymous"で始まるなら、そこを取り除く。 -
そうでなく sample が
"async function* anonymous"で始まるなら、そこを取り除く。
-
-
global の CSPリスト 内の各 policy について:
-
policy の ディレクティブセット に ディレクティブ で 名前 が
"require-trusted-types-for"のものがなければ、次の policy にスキップ。 -
directive を policy の ディレクティブセット から名前が
"require-trusted-types-for"の ディレクティブ とする -
directive の 値 が trusted-types-sink-group で sinkGroup に合致するものを含まない場合、次の policy にスキップ。
-
グローバル・ポリシー・ディレクティブのバイオレーションオブジェクト作成 を global, policy,
"require-trusted-types-for"で実行した結果を violation とする。 -
violation の resource を
"trusted-types-sink"に設定する。 -
trimmedSample を sample の最初の40文字を含む部分文字列とする。
-
violation の sample を、連結したリスト « sink, trimmedSample » (区切りは
"|") に設定する。 -
バイオレーション報告 を violation で実行。
-
policy の ディスポジション が
"enforce"なら result を"Blocked"に設定。
-
-
result を返す。
4.3.5. Trusted Type ポリシーの作成はContent Security Policyでブロックされるべきか?
このアルゴリズムは、TrustedTypePolicy
を作成してはならない場合 "Blocked" を、そうでなければ "Allowed" を返します。
Trusted Type ポリシーの作成はContent Security Policyでブロックされるべきか?アルゴリズムは、グローバルオブジェクト (global)、文字列 (policyName) および文字列リスト (createdPolicyNames) を受け取り、以下を実行します:
-
result を
"Allowed"に設定。 -
global の CSPリスト の各 policy について:
-
createViolation を false に設定。
-
policy の ディレクティブセット に ディレクティブ で
"trusted-types"という名前のものがなければ、次の policy へスキップ。 -
directive を policy の ディレクティブセット 内で名前が
"trusted-types"の ディレクティブ とする。 -
directive の 値 が tt-keyword で
'none'に合致するものだけを含む場合、createViolation を true に設定。Note: 他のCSPディレクティブと同様、'none'キーワードは他のキーワードやポリシー名が存在する場合は無視されます。
-
createdPolicyNames が policyName を含み、かつ directive の 値 に
'allow-duplicates'に合致する tt-keyword が含まれていなければ、createViolation を true に設定。Note:
trusted-types policyA policyB 'allow-duplicates'は、同名のポリシーを複数作成可能にします。 -
directive の 値 に policyName と一致する tt-policy-name がなく、かつ directive の値に tt-wildcard も含まれていなければ createViolation を true に設定。
Note:
trusted-types *で一意の名前のポリシーは自由に作成可能。「同名ポリシーを複数可」はtrusted-types * 'allow-duplicates'か、trusted-typesを設定しないこと。 -
createViolation が false なら次の policy へスキップ。
-
グローバル・ポリシー・ディレクティブのバイオレーションオブジェクト作成 を global, policy,
"trusted-types"で実行した結果を violation とする。 -
violation の resource を
"trusted-types-policy"に設定。 -
violation の sample を policyName の最初の40文字に設定。
-
バイオレーション報告 を violation で実行。
-
policy の ディスポジション が
"enforce"なら result を"Blocked"に設定。
-
-
result を返す。
5. セキュリティ考慮事項
Trusted Types は、インジェクションシンク へのアクセスを、積極的に悪意のある実行環境から保護する目的のものではありません。アプリケーションが悪意のない著者によって書かれていることを前提とし、開発者によるミスによるセキュリティバグを防ぐためのものであり、ポリシー制約を積極的に回避しようとするファーストパーティの悪意コードから守るものではありません。以下は、Trusted Typesを強制しても依然としてリスクのあるベクターです。
5.1. ドキュメントを跨いだベクター
Trusted Types
が強制されているウィンドウ内で実行されているコードは、ポリシー制約を回避するノードを動的に生成できませんが、同じ制約セットで保護されていない他のウィンドウのドキュメントからノードをインポート・アダプトすることは可能です。要するに、悪意ある著者が制限付きドキュメントと無制限ドキュメントが協調する仕組みを作った場合、Trusted
Types をバイパスできる可能性があります。極端な場合、制限付きドキュメントが文字列から Blob
を作り、それにナビゲートすることも可能です。
CSP伝播ルール(Content Security
Policy 3 § 7.8 CSP の継承によるバイパス回避)はこの問題に部分的に対処しています。新しいlocal
scheme文書も同じ制約を継承します。たとえば script-src 制約で Blob
の内容に対してスクリプトの実行を防げます。これを包括的に解決するには、Origin Policy
などの他の仕組みを利用し、オリジン全体にベースラインセキュリティルールを適用すべきです。
5.2. 廃止予定の機能
長らく非推奨でほとんど使われない一部のプラットフォーム機能は、Trusted Types の対象にならないため、制限を回避するのに悪意ある著者に悪用される可能性があります:
5.3. スクリプトガジェット
Trusted Typesのロジックは多くのDOM文字列からツリーを生成する操作で呼ばれますが、ドキュメントのすべてのDOMツリー生成をガードする仕組みとみなすべきではありません。特に スクリプトガジェット が存在する場合、アプリケーションが通常は無害なDOM要素や属性の内容に反応してしまう可能性があります。 DOM APIを直接利用する開発者は、このようなガジェットを Trusted Types を使わずに起動できます。しかし、DOM XSS を発火させるには、ガジェット側でポリシー経由で Trusted Type 値を取得する必要があります。ポリシーで制約やバリデーションがなされない場合は、著者は必ずポリシーに渡すデータが本当に信頼できるものかを確認してください。
5.4. ポリシーデザインのベストプラクティス
Trusted Typesは、インジェクションシンク を通じた脆弱性導入の範囲を ポリシー の実装部分だけに制限します。 この設計では、不安全なポリシーがあると インジェクションシンク に信頼できないデータが入り得ます。 すべての入力に対して安全なポリシーを使うか、不安全なポリシーは攻撃者に制御されない入力限定でだけ呼ばれるようにするなど、特に注意が必要です。
ポリシーはカスタムJavaScriptなので、グローバル状態に大きく依存した書き方も可能ですが、これは推奨しません。ポリシーはできるだけ自己完結的であるべきです。ポリシー内でセキュリティ決定に影響を与える可能性のある全オブジェクトは事実上「ポリシー化」されるため、一緒に管理・レビューする必要があります。
6. プライバシーに関する考慮事項
この仕様は、アプリケーション内で実行中のスクリプト挙動を部分的に監視・変更する可能性があります。たとえば インジェクションシンク で特定の操作を失敗させたり、デフォルトポリシーで効果を監視・変更したりします。 しかし初期に実行されるスクリプトは関連プロパティディスクリプタをオーバーライドすることで、同様のことがすでに可能です。
アプリケーションは Trusted Types 制限の違反を報告可能です。バイオレーションレポートにはインジェクションシンクへ渡されたペイロードの(40文字分のsink名付き)切り詰め内容が含まれます。これは Content Security Policy のレポート機構を流用しています。
7. 実装に関する考慮事項
7.1. ベンダー固有拡張とアドオン
Trusted Typesによる制限は、アドオン・拡張機能・ブックマークレット等のユーザーエージェント機能の動作を妨げてはなりません(SHOULD NOT)。 こうした機能は通常、ページ著者よりもユーザーを優先するものです(詳細は [html-design-principles])。具体的には、拡張機能はインジェクションシンク へ 文字列を渡しても、デフォルトポリシー の実行や違反生成、値の拒否などが発生しないようにすべきです。