1. 導入
この章は非規範的です。
この仕様書では Content Security Policy (CSP) を定義します。CSP とは、開発者が様々な方法でアプリケーションの影響範囲を限定できるツールであり、クロスサイトスクリプティングのようにコンテンツが注入される脆弱性のリスクを軽減し、アプリケーションが動作する権限を制限することができます。
コンテンツが注入される脆弱性に対して、CSP を最前線の防御に用いることは想定していません。むしろ、CSP は多層防御の構成要素として用いるのが最も効果的です。CSP を導入することで、悪意あるコンテンツが注入された際の被害を軽減することは可能ですが、入力時のバリデーションと出力時エンコーディングを注意深く行うことには勝りません。
この仕様書は Content Security Policy Level 2 の改訂版です。この改訂では、CSP・HTML・Fetch の三者における連携をより明確に説明すること、ならびにモジュールとしての拡張性に関する情報を明確に提供することが目的となっています。
私たちが新しい機能を必要とした際、その上に機能を構築できるような安定した基盤を形成することがこの仕様書の理想です。
1.1. 例
1.1.1. Web ページの制御
Content-Security-Policy: script-src https://cdn.example.com/scripts/; object-src 'none'
1.2. 目的
Content Security Policy は以下を目的として設計されています。
-
以下の事柄を制御することができ、かつ粒度の高い方法を開発者に提供することで、コンテンツが注入される攻撃のリスクを軽減します。
-
指定したリソースの埋め込み先オリジンを制御でき、かつ粒度の高い方法を開発者に提供することで、悪意あるコンテキストにリソースを埋め込む必要がある攻撃(例えば [TIMING] で説明されている "Pixel Perfect" 攻撃)のリスクを軽減します。
-
開発者がアプリケーションの動作権限を制限できるようなポリシーの枠組みを提供します。
-
本番環境で攻撃を受けている箇所を報告し、開発者が検知できるような仕組みを提供します。
1.3. Level 2 からの変更点
この仕様書は Content Security Policy Level 2 の仕様 [CSP2] を発展させたものです。以下に変更点を概説します。
-
[FETCH] の仕様を元にして CSP の仕様を基礎から書き直しました。このことにより、CSP の要請と制限を他の仕様(例えば Service Worker など)と組み合わせるのが容易になるはずです。
-
CSP Level 2 で廃止された
frame-src
ディレクティブが削除されました。 -
source expressions に安全でないスキームを指定した際、安全なスキームにもマッチするようになりました。すなわち、
http:
はhttp: https:
と等価であり、http://example.com
はhttp://example.com https://example.com
と等価です。同様に、
http
スキームのページで'self'
を指定した場合、そのページのオリジンにおけるhttps
とwss
にもマッチするようになりました。 -
インラインのスクリプトとスタイルから生成された違反レポートは、ブロックされたリソースとして "
inline
" が報告されることになります。同様に、eval()
の実行がブロックされた場合は、ブロックされたリソースとして "eval
" が報告されます。 -
(コンテキストが読込可能なリソースではなく)
Document
やWorker
に作用するディレクティブは [CSP-DOCUMENT] モジュールに分離されました。このモジュールにはbase-uri
とform-action
、frame-ancestors
、plugin-types
、sandbox
が含まれます。 -
manifest-src
ディレクティブが追加されました。 -
report-uri
ディレクティブが廃止され、新しいディレクティブとしてreport-to
が推奨されるようになりました。このreport-to
ディレクティブは [OOB-REPORTING] を基盤として設計されています。
1.4. 議論中の事項
frame-src
を本当に削除したほうがいいのでしょうか?Worker とフレームの脅威モデルは似ていますが、それらの上で実行できる内容は異なります。もしかすると、Worker と フレームのどちらか一方のみを許可するほうが良いのかもしれません。
報告の際に値を取り除く必要はまだあるのでしょうか?ブロックされたリソースにおける元々の URL を用いることで、そのリスクはほとんど排除されたと考えています。つまり、スクリプトが DOM を走査しても、レポートの JSON に含まれている自分自身の情報は何も収集できないはずです。
'unsafe-dynamic'
を追加すべきでしょうか?
ハッシュ値によるインラインイベントハンドラのホワイトリスト化を可能にすべきでしょうか? <https://github.com/w3c/webappsec-csp/issues/13>
2. 枠組み
2.1. ポリシー
policy#policyReferenced in:2.1.1.
serialized CSP を disposition に従ってパースする (2) (3)2.1.2.
serialized CSP の list を disposition に従ってパースする 2.2. ディレクティブ (2) (3) (4) (5)2.3. Violations (2) (3)2.3.1.
global、policy、directive に対する violation オブジェクトの生成 2.3.2.
request、policy、directive に対する violation オブジェクトの生成 3.
ポリシーの伝達 (2)4.1.
Fetch との連携 4.2.
HTML との連携 (2) (3) (4) (5)4.2.1.
Document の CSP list に対する初期化 5.
報告 (2)6.1.2.1. アルゴリズム (2)6.1.3.1. アルゴリズム (2)6.1.4.1. Algorithms (2)6.1.5.1. Algorithms (2)6.1.6.1. Algorithms (2)6.1.7.1. Algorithms (2)6.1.8.1. Algorithms (2)6.1.9.1. Algorithms (2)6.1.10.1. Algorithms (2)6.1.11.1.
request はpolicy に違反するか? 7.1. nonce の再利用9.1. ベンダー独自の拡張機能やアドオン とは、動作の許可・制限の集合を定義するものです。§4.2.2 グローバルオブジェクトの CSP list に対する初期化 で説明されているように、Window
や WorkerGlobalScope
に対して適用されることもあります。
各ポリシーには対応する directive set#policy-directive-setReferenced in:2.1.1. serialized CSP を disposition に従ってパースする (2) (3) (4)2.1.2. serialized CSP の list を disposition に従ってパースする 5.3. violation を報告する (2) (3) が存在します。directive set とは、ポリシー適用時の結果を定義した directive の集合です。
各ポリシーには対応する disposition#policy-dispositionReferenced in:2.1.1.
serialized CSP を disposition に従ってパースする (2)2.1.2.
serialized CSP の list を disposition に従ってパースする 4.1.2.
request における Content Security Policy 違反を報告する 4.1.3.
request は Content Security Policy によってブロックされるべきか? 4.1.4.
request に対する response は Content Security Policy によってブロックされるべきか? (2)4.2.3.
element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? が存在し、"enforce
" または "report
" の値を持ちます。
serialized CSP#serialized-cspReferenced in:2.1.1. serialized CSP を disposition に従ってパースする 2.1.2. serialized CSP の list を disposition に従ってパースする 2.2.1. Source Lists3. ポリシーの伝達 3.1. Content-Security-Policy HTTP レスポンスヘッダフィールド 3.2. Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド 4.1.1. response の CSP list を設定する 5.2. violation を廃止された方法でシリアライズしたものを取得する とは、シリアライズされたディレクティブをセミコロン区切りで並べた ASCII 文字列です。[RFC5234] の ABNF 文法を用いると以下のように表現されます。
serialized-policy#grammardef-serialized-policyReferenced in:3.1.
Content-Security-Policy HTTP レスポンスヘッダフィールド
3.2.
Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド
= serialized-directive *( OWS ";" [ OWS serialized-directive ] )
; OWS は RFC 7230 の 3.2.3 項で定義されています。
2.1.1. serialized CSP を disposition に従ってパースする #parse-serialized-policyReferenced in:2.1.2. serialized CSP の list を disposition に従ってパースする 3.1. Content-Security-Policy HTTP レスポンスヘッダフィールド 3.2. Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド 4.1. Fetch との連携
serialized CSP (serialized CSP) と disposition (disposition) に対して、このアルゴリズムは policy オブジェクトを返します。文字列をパースできなかった場合、空の directive set が含まれた policy が返されます。
-
空の directive set と disposition の disposition を持った policy を policy に代入します。
-
serialized CSP を U+003B SEMICOLON (
;
) で 厳格に分割し、その結果に含まれる各 token に対して以下を実行します。-
token から Strip leading and trailing whitespace します。
-
ここで token が空文字列だった場合、残りの副手続きをスキップし、次の要素の処理に移ります。
-
token から space characters 以外の文字を集めた結果を directive name に代入します。
-
ここで、directive name と等しい name を持つ directive が policy の directive set に既に存在した場合、残りの副手続きをスキップし、次の要素の処理に移ります。
ユーザエージェントはディレクティブが無視された旨を開発者に通知すべきです(SHOULD)。例えば、コンソールに警告を出すのが適切かもしれません。
-
token をスペースで分割した結果を directive value に代入します。
-
name として directive name を、また value として directive value を持った新しい directive を directive に代入します。
-
directive を policy の directive set に追加します。
-
-
policy を返します。
2.1.2. serialized CSP の list を disposition に従ってパースする
複数の serialized CSP をカンマ区切りで並べた文字列 (list) と、disposition (disposition) とに対して、以下のアルゴリズムは policy のリストを返します。
-
空のリストを policies に代入します。
-
list をカンマで分割し、その結果に含まれる各 token に対して以下を実行します。
-
§2.1.1 serialized CSP を disposition に従ってパースする に token と disposition を適用させた結果を policy に代入します。
-
ここで policy の directive set が空だった場合、残りの副手続きをスキップし、次の要素の処理に移ります。
-
policy を policies に追加します。
-
-
policies を返します。
2.2. ディレクティブ
Policies には directives#directivesReferenced in:2.1. ポリシー2.1.1. serialized CSP を disposition に従ってパースする (2)2.2. ディレクティブ (2)2.2.1. Source Lists2.3. Violations4.1. Fetch との連携 4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) (2) (3)5.3. violation を報告する (2) (3)6. Content Security Policy のディレクティブ 6.1.3.1. アルゴリズム (2) (3) (4) の集合が含まれており、各ディレクティブは動作を制御します。この仕様書で定義されるディレクティブは §6 Content Security Policy のディレクティブ で説明されています。
各 directive は name#directive-nameReferenced in:2.1.1. serialized CSP を disposition に従ってパースする (2)2.2. ディレクティブ4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) (2)6.1.3.1. アルゴリズム (2) (3) (4)6.1.11.5. request の effective directive を得る と value#directive-valueReferenced in:2.1.1. serialized CSP を disposition に従ってパースする 2.2. ディレクティブ (2)2.2.1. Source Lists4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) (2)5.3. violation を報告する (2)6.1.2.1. アルゴリズム (2)6.1.3.1. アルゴリズム (2)6.1.4.1. Algorithms (2)6.1.5.1. Algorithms (2)6.1.6.1. Algorithms (2)6.1.7.1. Algorithms (2)6.1.8.1. Algorithms (2)6.1.9.1. Algorithms (2) (3) (4) (5)6.1.10.1. Algorithms (2) (3) (4) (5) の組です。name は空ではない文字列であり、value は空でない文字列の集合です。value は空であってもよいです(MAY)。
serialized directive は、空白で区切られた一つ以上のトークンからなる ASCII 文字列であり、[RFC5234] の ABNF を用いると以下のように表現されます
serialized-directive#grammardef-serialized-directiveReferenced in:2.1. ポリシー (2) = directive-name [ RWS directive-value ] directive-name#grammardef-directive-nameReferenced in:2.2. ディレクティブ = 1*( ALPHA / DIGIT / "-" ) directive-value#grammardef-directive-valueReferenced in:2.2. ディレクティブ = *( %x09 / %x20-%x2B / %x2D-%x3A / %x3C-%7E ) ; ディレクティブの値には空白と VCHAR 文字を含めることができます。 ; ただし、";" と "," は除きます。 ; RWS は RFC 7230 の 3.2.3 項で定義されています。 ; ALPHA、DIGIT、VCHAR は RFC 5234 の付録 B.1 で定義されています。
Directives に関連するアルゴリズムは以下の 5 つです。
-
pre-request check#directive-pre-request-checkReferenced in:6.1.1.1. アルゴリズム6.1.2.1. アルゴリズム6.1.3.1. アルゴリズム (2) (3)6.1.4.1. Algorithms6.1.5.1. Algorithms6.1.6.1. Algorithms6.1.7.1. Algorithms6.1.8.1. Algorithms6.1.9.1. Algorithms6.1.10.1. Algorithms6.1.11.1. request はpolicy に違反するか? 6.3. 他の文書で定義されるディレクティブ は request と policy を引数に取り、§4.1.3 request は Content Security Policy によってブロックされるべきか? の中で実行されるアルゴリズムです。実行結果として "
Allowed
" またはその他の指定された値を返します。 -
post-request check#directive-post-request-checkReferenced in:4.1.4. request に対する response は Content Security Policy によってブロックされるべきか? 6.1.1.1. アルゴリズム6.1.2.1. アルゴリズム6.1.3.1. アルゴリズム6.1.4.1. Algorithms6.1.5.1. Algorithms6.1.6.1. Algorithms6.1.7.1. Algorithms6.1.8.1. Algorithms6.1.9.1. Algorithms6.1.10.1. Algorithms6.3. 他の文書で定義されるディレクティブ は request と response、そして policy とを引数に取り、§4.1.4 request に対する response は Content Security Policy によってブロックされるべきか? の中で実行されるアルゴリズムです。実行結果として "
Allowed
" またはその他の指定された値を返します。 -
response check#directive-response-checkReferenced in:4.1.4. request に対する response は Content Security Policy によってブロックされるべきか? は request と response、そして policy とを引数に取り、§4.1.4 request に対する response は Content Security Policy によってブロックされるべきか? の中で実行されるアルゴリズムです。実行結果として "
Allowed
" またはその他の値を定義に従って返します。§4.1.4 request に対する response は Content Security Policy によってブロックされるべきか? の中で実行されるアルゴリズムです。実行結果として "Allowed
" またはその他の指定された値を返します。 -
inline check#directive-inline-checkReferenced in:4.2.3. element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? 6.1.9.1. Algorithms6.1.10.1. Algorithms は
Element
と type string を引数に取り、§4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? の中で実行されるアルゴリズムです。実行結果として "Allowed
" またはその他の指定された値を返します。 -
initialization#directive-initializationReferenced in:4.2.1. Document の CSP list に対する初期化 6.1.9.1. Algorithms6.1.10.1. Algorithms6.3. 他の文書で定義されるディレクティブ は
Document
または global object と、responce、そして policy との 3 つの引数を取り、§4.2.1 Document の CSP list に対する初期化 の中で実行されるアルゴリズムです。特に指定がない限り、実行結果で値が返されることはありません。
2.2.1. Source Lists
directives における values の多くは source lists#source-listsReferenced in:6.1.1. child-src6.1.2. connect-src6.1.4. font-src6.1.5. img-src6.1.6. manifest-src6.1.7. media-src6.1.8. object-src6.1.11.2. Does nonce match source list? 6.1.11.3. url は source list にマッチするか? 6.1.12.1. Does element match source list? から構成されます。source list とは、読み込まれるコンテンツ、埋め込み・実行の可能性があるコンテンツを特定するトークンの集合です。これらのトークンは、以下に列挙した source expression#source-expressionReferenced in:2.2.1. Source Lists4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) 6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? 6.1.12.1. Does element match source list? の種類のうち、いずれか 1 つを示します。
-
'none'
や'self'
といったキーワード(要素を持たないものと、その時点における URL のオリジンとにそれぞれマッチします) -
https://example.com/path/to/file.js
のようにシリアライズされた URL (特定のファイルにマッチします)またはhttps://example.com/
のようにシリアライズされた URL (そのオリジン上のすべてにマッチします) -
https:
のようなスキーム(特定のスキームを持つ任意のリソースにマッチします) -
example.com
のようなホスト名(スキームに関係なく、そのホスト上にある任意のリソースにマッチします)または*.example.com
のようなホスト(スキームに関係なく、そのホスト上やサブドメイン上にある任意のリソースにマッチします(さらにそのサブドメインについても同様です)) -
'nonce-qwertyu12345'
のような nonces (ページにおける特定の要素にマッチします) -
'sha256-abcd...'
のようなダイジェスト(ページにおける特定の要素にマッチします)
serialized source list とは、source expressions を空白区切りで並べた ASCII 文字列であり、[RFC5234] の ABNF を用いると以下のように表現されます。
serialized-source-list#grammardef-serialized-source-listReferenced in:6.1.1. child-src6.1.2. connect-src6.1.3. default-src6.1.4. font-src6.1.5. img-src6.1.6. manifest-src6.1.7. media-src6.1.8. object-src6.1.9. script-src6.1.10. style-src = ( source-expression *( RWS source-expression ) ) / "'none'#grammardef-noneReferenced in:2.2.1. Source Lists" source-expression#grammardef-source-expressionReferenced in:2.2.1. Source Lists (2) = scheme-source / host-source / keyword-source / nonce-source / hash-source ; スキーム: scheme-source#grammardef-scheme-sourceReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) = scheme ":" ; scheme は RFC 3986 の 3.1 節で定義されています。 ; ホスト: "example.com" / "*.example.com" / "https://*.example.com:12/path/to/file.js" host-source#grammardef-host-sourceReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) (3) = [ scheme-part "://" ] host-part [ port-part ] [ path-part ] scheme-part#grammardef-scheme-partReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) (3) (4) (5) (6) = scheme host-part#grammardef-host-partReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) (3) (4) (5) = "*" / [ "*." ] 1*host-char *( "." 1*host-char ) host-char#grammardef-host-charReferenced in:2.2.1. Source Lists (2) (3) = ALPHA / DIGIT / "-" port-part#grammardef-port-partReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) (3) = ":" ( 1*DIGIT / "*" ) path-part#grammardef-path-partReferenced in:2.2.1. Source Lists6.1.11.4. redirect count を持つ origin において url は expression にマッチするか? (2) (3) = path ; path は RFC 3986 の 3.3 節で定義されています。 ; キーワード: keyword-source#grammardef-keyword-sourceReferenced in:2.2.1. Source Lists = "'self'#grammardef-selfReferenced in:2.2.1. Source Lists6.1.3. default-src (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19)" / "'unsafe-inline'#grammardef-unsafe-inlineReferenced in:6. Content Security Policy のディレクティブ 7.1. nonce の再利用 (2)" / "'unsafe-eval'#grammardef-unsafe-evalReferenced in:4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) " ; Nonces: 'nonce-[ここに nonce 値が入ります]' nonce-source#grammardef-nonce-sourceReferenced in:2.2.1. Source Lists6.1.9. script-src6.1.10. style-src6.1.11.2. Does nonce match source list? 6.1.12.1. Does element match source list? (2)7.1. nonce の再利用 = "'nonce-" base64-value "'" base64-value#grammardef-base64-valueReferenced in:2.2.1. Source Lists (2)6.1.11.2. Does nonce match source list? 6.1.12.1. Does element match source list? (2) = 1*( ALPHA / DIGIT / "+" / "/" / "-" / "_" )*2( "=" ) ; ダイジェスト: 'sha256-[digest goes here]' hash-source#grammardef-hash-sourceReferenced in:2.2.1. Source Lists6.1.9. script-src6.1.10. style-src6.1.12.1. Does element match source list? (2) = "'" hash-algorithm "-" base64-value "'" hash-algorithm#grammardef-hash-algorithmReferenced in:2.2.1. Source Lists6.1.12.1. Does element match source list? (2) (3) = "sha256" / "sha384" / "sha512"
host-char の項では、意図的に ASCII 文字のみが許されています。従って、国際化ドメイン名は serialized CSP の中に直接含めることはできず、その代わりに Punycode で事前にエンコードしなければなりません(MUST)。例えば、üüüüüü.de
というドメイン名は xn--tdaaaaaa.de
と表記されなければなりません(MUST)。
Note: IP アドレスも上記の文法に適合しますが、source expression の中で用いて実際に URL とマッチするのは 127.0.0.1
のみです(詳しくは §6.1.11.3 url は source list にマッチするか? を参照してください)。IP アドレスに関するセキュリティの問題点はまだ明確になっていませんが、管理者は可能な限りホスト名を用いるべきです。
§6.1.11.3 url は source list にマッチするか? のアルゴリズムが Matches
を返した場合、その URL
は matches a source list といいます。
2.3. Violations
violation#violationReferenced in:2.3. Violations (2) (3) (4) (5) (6) (7) (8) (9) (10)2.3.1. global、policy、directive に対する violation オブジェクトの生成 (2)2.3.2. request、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する 5.3. violation を報告する (2)6.2. Reporting Directives とは、global object に対する policies の制約に反したアクションやリソースを表現するものです。
各 violation は global object#violation-global-objectReferenced in:2.3. Violations2.3.1. global、policy、directive に対する violation オブジェクトの生成 (2)5.3. violation を報告する (2) (3) (4) を持っており、違反が行われた policy に対応する global object がこれに相当します。
各 violation は url#violation-urlReferenced in:5.2.
violation を廃止された方法でシリアライズしたものを取得する 5.3.
violation を報告する (2) を持っており、global object の URL
がこれに相当します。
各 violation は status#violation-statusReferenced in:2.3.1. global、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する 5.3. violation を報告する を持っており、グローバルオブジェクトが生成されたリソースについて、このリソースの HTTP ステータスコードを表す非負整数で表現されます。
各 violation は resource#violation-resourceReferenced in:2.3.1.
global、policy、directive に対する violation オブジェクトの生成 2.3.2.
request、policy、directive に対する violation オブジェクトの生成 4.2.3.
element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? 5.2.
violation を廃止された方法でシリアライズしたものを取得する 5.3.
violation を報告する を持っており、null
、"inline
"、"eval
"、または URL
のいずれかで、ポリシーに違反したリソースを表現します。
各 violation は referrer#violation-referrerReferenced in:2.3.1.
global、policy、directive に対する violation オブジェクトの生成 5.2.
violation を廃止された方法でシリアライズしたものを取得する 5.3.
violation を報告する を持っており、null
または URL
のどちらかで、違反されたポリシーのリソースに対するリファラを表現します。
各 violation は policy#violation-policyReferenced in:2.3.1. global、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する 5.3. violation を報告する (2) (3) (4) (5) を持っており、違反が行われた policy がこれに相当します。
各 violation は effective directive#violation-effective-directiveReferenced in:2.3.1. global、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する (2)5.3. violation を報告する (2) を持っており、空でない文字列として、違反の対象となった制限を指定した directive を表現します。
各 violation は source file#violation-source-fileReferenced in:2.3.1.
global、policy、directive に対する violation オブジェクトの生成 5.2.
violation を廃止された方法でシリアライズしたものを取得する (2)5.3.
violation を報告する を持っており、null
または URL
で表現されます。
各 violation は line number#violation-line-numberReferenced in:2.3.1. global、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する 5.3. violation を報告する を持っており、負でない整数値で表現されます。
各 violation は column number#violation-column-numberReferenced in:2.3.1. global、policy、directive に対する violation オブジェクトの生成 5.2. violation を廃止された方法でシリアライズしたものを取得する 5.3. violation を報告する を持っており、負でない整数値で表現されます。
2.3.1. global、policy、directive に対する violation オブジェクトの生成
ある global object (global) と policy (policy)、 文字列 (directive) に対し、以下のアルゴリズムは新しい violation オブジェクト を生成し、初期値をそれぞれ設定します。
-
global object に global を、policy に policy を、effective directive に directive を、resource に
null
をそれぞれセットした新しい violation を violation に代入します。 -
ここで、ユーザエージェントがスクリプトを実行中であり、かつ global からソースファイルの URL や行数、列数を読み出せる場合、それらに従って violation の source file と line number、column number を設定します。
このような処理は他でも行われているでしょうか?この処理 は [ECMA262] で効果的に用いられていますが、それ以外の例をまだ知りません。
-
ここで global が
Window
オブジェクトであった場合、global におけるdocument
のreferrer
を violation の referrer に代入します。 -
violation の global object に対応するリソースの HTTP ステータスコードを violation の status に代入します。
-
violation を返します。
2.3.2. request、policy、directive に対する violation オブジェクトの生成
ある request (request) と policy (policy)、そして文字列 (directive) に対し、以下のアルゴリズムは新しい violation オブジェクトを生成し、初期値をそれぞれ設定します。
-
request における client の global object と policy、directive に対して §2.3.1 global、policy、directive に対する violation オブジェクトの生成 を実行し、その結果を violation に代入します。
-
request の url を violation の resource に代入します。
Note: ここで用いるのは request の url であり、current url では ありません。なぜなら後者には、リダイレクト先かつアクセスされてはならない(MUST NOT)ページに関する情報が含まれている可能性があるからです。
-
violation を返します。
3. ポリシーの伝達
フィールド値に serialized CSP を持つ HTTP レスポンスヘッダを利用し、サーバは指定した resource representation に対する policy を宣言してもよいです(MAY)。この仕組みは §3.1 Content-Security-Policy HTTP レスポンスヘッダフィールド と §3.2 Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド で詳しく定義されており、Fetch や HTML との併用については §4.1 Fetch との連携 と §4.2 HTML との連携 で詳しく説明されています。
また、§3.3 <meta> 要素 で説明されているように、meta
要素の http-equiv
属性を HTML ドキュメント中に用いて policy を宣言してもよいでしょう。
3.1. Content-Security-Policy
HTTP レスポンスヘッダフィールド
サーバからクライアントへポリシーを伝達する仕組みとしては、Content-Security-Policy
#content-security-policyReferenced in:3.1.
Content-Security-Policy HTTP レスポンスヘッダフィールド 6.1.3. default-src (2) (3) (4)6.2.1. report-uri HTTP レスポンスヘッダフィールドを用いることが望まれます。ヘッダの値は [RFC5234] の ABNF で以下のように表現されます。
Content-Security-Policy = 1#serialized-policy
Content-Security-Policy: script-src 'self'; report-to /csp-reporting-endpoint
同じリソースを指す異なる representations について、サーバはそれぞれ異なる Content-Security-Policy
ヘッダフィールド値を送信してもよいです(MAY)。
1 つの resource representation について、サーバは "Content-Security-Policy
" という名前の HTTP レスポンスヘッダフィールドを 2 つ以上送信するべきではありません(SHOULD NOT)。
Content-Security-Policy
ヘッダフィールドを受信したユーザエージェントは、フィールドに含まれている serialized CSP のそれぞれを parse し、かつ enforce しなければなりません(MUST)。これについては §4.1 Fetch との連携 と §4.2 HTML との連携 で説明されています。
3.2. Content-Security-Policy-Report-Only
HTTP レスポンスヘッダフィールド
Web 開発者がポリシーの影響範囲を(実際に適用するのではなく)モニタリングしたい場合、Content-Security-Policy-Report-Only
#content-security-policy-report-onlyReferenced in:3.2.
Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド (2)3.3.
<meta> 要素 HTTP レスポンスヘッダフィールドを用いて実験することができます。ヘッダの値は [RFC5234] の ABNF で以下のように表現されます。
Content-Security-Policy-Report-Only = 1#serialized-policy
Web 開発者はこのヘッダフィールドを用いることで、実験を繰り返しつつセキュリティポリシーを組み立てることができます。つまり、サイトの動作を入念に設計した状態で report-only ポリシーをデプロイし、その結果を違反レポートとして検証することで、サイトの動作に自信を持ってから実際にポリシーを適用することができます。
Content-Security-Policy-Report-Only: script-src 'self'; report-to /csp-reporting-endpoint
同じリソースを指す異なる representations について、サーバはそれぞれ異なる Content-Security-Policy-Report-Only
ヘッダフィールド値を送信してもよいです(MAY)。
1 つの resource representation について、サーバは "Content-Security-Policy-Report-Only
" という名前の HTTP レスポンスヘッダフィールドを 2 つ以上送信するべきではありません(SHOULD NOT)。
Content-Security-Policy-Report-Only
ヘッダフィールドを受信したユーザエージェントは、フィールドに含まれている serialized CSP のそれぞれを parse し、かつ monitor しなければなりません(MUST)。これについては §4.1 Fetch との連携 と §4.2 HTML との連携 で説明されています。
Note: meta
要素における Content-Security-Policy-Report-Only
ヘッダはサポートされていません。
3.3. <meta>
要素
"Content-Security-Policy
" に対して ASCII case-insensitive match な文字列を http-equiv
属性値に持つ HTML meta
要素について、Document
はこの要素を 1 つ以上用いてポリシーを伝達してもよいです(MAY)。具体例を以下に示します。
実装に関する詳細は、HTML 仕様の Content-Security-Policy
http-equiv
processing instructions [HTML] を参照してください。
Note: meta
要素における Content-Security-Policy-Report-Only
ヘッダはサポートされていません。また、report-uri
、frame-ancestors
、sandbox
各ディレクティブも meta
要素内ではサポートされていません。
Web 開発者は、できるだけドキュメントの先頭近くに meta
要素を書くように強く推奨されます。なぜなら、meta
要素内で指定されたポリシーは、その書かれた位置より前のコンテンツには適用されないからです。特に、Link
HTTP レスポンスヘッダフィールドを使って読込・先読みされるリソース、また meta
要素で伝達されたポリシーより前に位置する link
要素や script
要素で読込・先読みされるリソースについて、これらがブロックの対象とならないことに注意してください。
Note: あるポリシーが meta
要素内で指定されており、かつ保護されたリソースに対するアクティブなポリシーが他にもあった場合、後者のポリシーを指定した位置に関係なく、両方のポリシーが同時に適用されます。複数ポリシーの適用時における一般的な影響については §8.1 複数のポリシーによる影響 で説明されています。
4. 連携
この章は非規範的です。
この仕様書で定義されるアルゴリズムには、機能実装を目的として他の仕様書で利用されるものがあります。このような連携を明らかにするため以下に概要を説明しますが、それら外部の仕様書は規範的な文書であり、詳細はその仕様書で確認すべきものです。
4.1. Fetch との連携
リソースを読み込む様々な方法は、多くの directives によって制御されます。この仕様書で提供するアルゴリズムにより、特定の requestに対するブロック・許可の判断、または特定の response を network error で置き換える判断を Fetch が行えるようになります。
-
§4.1.3 request は Content Security Policy によってブロックされるべきか? は Main Fetch アルゴリズム中のステップ #4 で呼び出されます。
-
§4.1.4 request に対する response は Content Security Policy によってブロックされるべきか? は Main Fetch アルゴリズム中のステップ #12 で呼び出されます。
policy は global object に適用されるのが通常ですが、response の内容を必要とするディレクティブを処理するため、ユーザエージェントは HTTP レスポンスヘッダフィールドで伝達されてきたすべてのポリシーについて、global object を生成する前に parse する必要があります。そのため、
-
response は CSP list を持ちます。CSP list とは、response の header list で伝達されたすべてのポリシーオブジェクトを含むものです。
-
§4.1.1 response の CSP list を設定する は HTTP fetch と HTTP-network fetch アルゴリズムの中で呼び出されます。
Note: この 2 つの呼び出しについては、どのように response を生成したかに関係なく、response の CSP list がセットされていることを保障すべきです。(HTTP-network fetch を用いて)ネットワークに接続した場合、
Set-Cookie
ヘッダを処理する前にポリシーをパースします。(HTTP fetch を用いて)Service Worker からレスポンスを受けた場合、そのレスポンスを呼び出し元に返す前に CSP list を処理します。
4.1.1. response の CSP list
を設定する
ある response (response) に対して、このアルゴリズムは serialized CSP を値に持つ header list を評価し、その結果に基づいて CSP list を以下のように設定します。
-
空のリストを response の CSP list に代入します。
-
disposition を "
enforce
" とし、response の header list におけるContent-Security-Policy
を parsing した結果に §2.1.2 serialized CSP の list を disposition に従ってパースする を適用した結果を policies に代入します。 -
disposition を "
report
" とし、response の header list におけるContent-Security-Policy-Report-Only
を parsing し、その結果について §2.1.2 serialized CSP の list を disposition に従ってパースする を適用した結果を policies に追加します。 -
policies に含まれる要素 policy のそれぞれについて以下を実行します。
-
response の CSP list に policy を挿入します。
-
4.1.2. request における Content Security Policy 違反を報告する
ある request (request) に対して、このアルゴリズムは client の "report only" ポリシーに基づいて違反を報告します。
-
request の client が持つ global object の CSP list を CSP list に代入します。
-
CSP list に含まれる要素 policy のそれぞれについて以下を実行します。
-
ここで policy の disposition が "
enforce
" だった場合、以降の処理を飛ばして次の policy に移ります。 -
request と policy に対して §6.1.11.1 request はpolicy に違反するか? を適用した結果を violates に代入します。
-
ここで violates が "
Does Not Violate
" でなかった場合、request と policy と violates に対して §2.3.2 request、policy、directive に対する violation オブジェクトの生成 を適用し、その結果に対して §5.3 violation を報告する を適用します。
-
4.1.3. request は Content Security Policy によってブロックされるべきか?
ある request (request) に対し、このアルゴリズムは request の client における Content Security Policy に基づいて Blocked
または Allowed
のどちらかを返します。
-
request の client が持つ global object の CSP list を CSP list に代入します。
-
result に "
Allowed
" を代入します。 -
CSP list に含まれる要素 policy のそれぞれについて以下を実行します。
-
ここで policy の disposition が "
report
" だった場合、以降の処理を飛ばして次の policy に移ります。 -
request と policy に対して §6.1.11.1 request はpolicy に違反するか? を適用した結果を violates に代入します。
-
ここで violates が "
Does Not Violate
" ではなかった場合、以下を実行します。-
request と policy と violates に対して §5.3 violation を報告する を実行します。
-
result に "
Blocked
" を代入します。
-
-
-
result を返します。
4.1.4. request に対する response は Content Security Policy によってブロックされるべきか?
ある response (response) と a request (request) に対し、このアルゴリズムは request の client における Content Security Policy に基づいて Blocked
または Allowed
のどちらかを返します。
-
request の client が持つ global object の CSP list を CSP list に代入します。
-
result に "
Allowed
" を代入します。 -
CSP list に含まれる要素 policy のそれぞれについて以下を実行します。
-
policy に含まれる要素 directive のそれぞれについて以下を実行します。
-
ここで directive の post-request check を実行し、その結果が "
Blocked
" だった場合、以下を実行します。-
request と policy と directive に対して §2.3.2 request、policy、directive に対する violation オブジェクトの生成 を適用し、その結果をもとに §5.3 violation を報告する を実行します。
-
ここで policy の disposition が "
enforce
" だった場合、result に "Blocked
" を代入します。
-
-
Note: この箇所では、ページがレスポンスを読み込み可能であることを検証しています。すなわち、ページの CSP に違反したファイルを Service Worker が差し替えていない場合などを想定したものです。
-
-
response の CSP list に含まれる要素 policy のそれぞれについて以下を実行します。
-
policy に含まれる要素 directive のそれぞれについて以下を実行します。
-
ここで request と response と policy に対して directive の response check を適用し、その結果が "
Blocked
" だった場合、以下を実行します。-
request と policy と directive に対して §2.3.2 request、policy、directive に対する violation オブジェクトの生成 を適用し、その結果をもとに §5.3 violation を報告する を実行します。
-
ここで policy の disposition が "
enforce
" だった場合、result に "Blocked
" を代入します。
-
-
Note: この箇所では、レスポンスと一緒に伝達されてきたポリシーをもとに、そのレスポンスは読み込むべきものかどうかを判断しています。
-
-
result を返します。
4.2. HTML との連携
-
Document
オブジェクトとWorkerGlobalScope
オブジェクトは CSP list#global-object-csp-listReferenced in:4.1.2. request における Content Security Policy 違反を報告する 4.1.3. request は Content Security Policy によってブロックされるべきか? 4.1.4. request に対する response は Content Security Policy によってブロックされるべきか? 4.2. HTML との連携 4.2.2. グローバルオブジェクトの CSP list に対する初期化 (2)4.2.3. element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? 4.3. Integration with ECMAScript4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm) を持ちます。この CSP list は、そのコンテキストでアクティブな policy オブジェクトすべてを含むリストです。特に指定のない限り、このリストが空になることはなく、アルゴリズム §4.2.2 グローバルオブジェクトの CSP list に対する初期化 によって初期化されます。この概念は WHATWG’s HTML に追加されていますが、W3C’s HTML にはまだ追加されていません。 <https://github.com/w3c/html/issues/187>
-
ある policy が global object の CSP list に挿入されると、その policy は global object に対して enforced#enforcedReferenced in:3.1. Content-Security-Policy HTTP レスポンスヘッダフィールド 4.2. HTML との連携 されるか monitored#monitoredReferenced in:3.2. Content-Security-Policy-Report-Only HTTP レスポンスヘッダフィールド されます。
-
ある response に対する policy オブジェクトの集合を、新しく生成した global object と関連付けるため、アルゴリズム §4.2.2 グローバルオブジェクトの CSP list に対する初期化 は initialising a new
Document
object と run a worker のアルゴリズム中で呼び出されます。このフックは WHATWG’s HTML に組み込まれましたが、W3C’s HTML にはまだ組み込まれていません。 <https://github.com/w3c/html/issues/188>
-
インラインのスクリプト・スタイルを実行・レンダリングしてもよいかを判断するため、アルゴリズム §4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? は prepare a script と update a
style
block のアルゴリズム中で呼び出されます。script
とstyle
のnonce
属性が WHATWG’s HTML に追加されました(whatwg/html@882803c)。しかし、まだ W3C’s HTML には追加されていません。 <https://github.com/w3c/html/issues/186>§4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? のフックが WHATWG’s HTML に追加されました(whatwg/html@ee3486e)。しかし、まだ W3C’s HTML には追加されていません。 <https://github.com/w3c/html/issues/185>
-
アルゴリズム §4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか? は、インラインのイベントハンドラ(
onclick
など)や、インラインのstyle
属性を処理する過程で呼び出され、これらを実行・レンダリングしてもよいかを判断するのに用いられます。このフックは WHATWG’s HTML に追加されました(whatwg/html@920c918)。また、W3C’s HTML にも一部が追加されています。 <https://github.com/w3c/html/issues/185>
-
policies は
meta
要素中のhttp-equiv
を処理する過程で enforced されます。この処理は WHATWG’s HTML に追加されました(whatwg/html@5064a62)。しかし、まだ W3C’s HTML には追加されていません。 <https://github.com/w3c/html/issues/184>
-
ある
Document
の embedding document#embedding-documentReferenced in:4.2.1. Document の CSP list に対する初期化 (2)4.2.2. グローバルオブジェクトの CSP list に対する初期化 とは、そのDocument
の browsing context がネストされているDocument
です。
4.2.1. Document
の CSP list
に対する初期化
ある Document
(document) と response (response) に対し、ユーザエージェントは document の CSP list を初期化するために以下の処理を実行します。
-
ここで response における url の
scheme
が local scheme だった場合、以下を実行します。-
documents に空リストを代入します。
-
ここで document が embedding document (embedding) を持っていた場合、その embedding を documents に追加します。
-
ここで document が opener browsing context を持っていた場合、そのブラウジングコンテキストの active document を documents に追加します。
-
documents に含まれる各要素 doc のそれぞれについて以下を実行します。
Note: local scheme には
about:
も含まれているため、embedding document の有するポリシーのうち、an iframesrcdoc
Document
に対するポリシーのエイリアスが挿入されます。Note: このアルゴリズムは、ページが制御するコンテンツ(
blob:
リソースやdocument.write()
)を含むフレームを埋め込んだり、またはコンテンツを含む新しいウィンドウを開いたりしても、そのページが自身の policy を回避できないことを保障するために実行されます。 -
-
response の CSP list に含まれる policy について、それぞれの policy を document の CSP list に挿入します。
-
document の CSP list に含まれる policy のそれぞれについて以下を実行します。
-
policy に含まれる directive のそれぞれについて以下を実行します。
-
document と response に対して directive の initialization アルゴリズムを実行します。
-
-
4.2.2. グローバルオブジェクトの CSP list
に対する初期化
ある global object (global) と response (response) に対し、ユーザエージェントは global の CSP list を初期化するために以下の処理を実行します。
-
ここで response における url の
scheme
が local scheme だった場合、以下を実行します。-
documents に空リストを代入します。
-
global に含まれる document のそれぞれを documents に追加します。
-
documents に含まれる要素 document のそれぞれについて以下を実行します。
-
document の global object が有する CSP list に含まれる要素 policy のそれぞれについて以下を実行します。
-
policy に対するエイリアスを global の a for="global object">CSP list に挿入します。
-
-
Note: local scheme には
about:
も含まれているため、embedding document の有するポリシーのうち、an iframesrcdoc
Document
に対するポリシーのエイリアスが挿入されます。 -
-
response の CSP list に含まれる policy について、それぞれの policy を global の CSP list に挿入します。
4.2.3. element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか?
ある Element
(element) と文字列 (type) に対するこのアルゴリズムは、(スクリプト実行、スタイル適用、イベントハンドラなどといった)特定の挙動に関するインライン定義を、その要素に与えることが許されていれば "Allowed" を返し、そうでなければ "Blocked" を返します。
-
result に "
Allowed
" を代入します。 -
element の
Document
が持つ global object の CSP list に含まれる要素 policy のそれぞれについて以下を実行します。-
policy に含まれる directive のそれぞれについて以下を実行します。
-
ここで element と type に対して directive の inline check を実行した結果が "
Allowed
" だった場合、以下の処理を飛ばして次の directive に移ります。 -
"
Allowed
" ではなく、かつ type が "style
" か "style-attribute
" のどちらかである、または "script-src
" 以外である場合、incumbent settings object と policy と "style-src
" に対して §2.3.1 global、policy、directive に対する violation オブジェクトの生成 を適用し、その結果を violation に代入します。 -
violation の resource に "
inline
" を代入します。 -
violation に対して §5.3 violation を報告する を適用します。
-
ここで policy の disposition が "
enforce
" だった場合、result に "Blocked
" を代入します。
-
-
-
result を返します。
4.3. Integration with ECMAScript
ECMAScript defines a HostEnsureCanCompileStrings()
operation which allows
the host environment to block the compilation of strings into ECMAScript code.
This document defines an implementation of that operation which examines the
relevant CSP list to determine whether such
compilation ought to be blocked.
This has landed in WHATWG’s HTML, but hasn’t yet made it to W3C’s version. <https://github.com/w3c/html/issues/189>
4.3.1. EnsureCSPDoesNotBlockStringCompilation(callerRealm, calleeRealm)
Given two realms (callerRealm and calleeRealm), this algorithm
returns normally if string compilation is allowed, and throws an "EvalError
"
if not:
-
Let global be callerRealm’s global object.
-
For each policy in global’s CSP list:
-
Let source-list be null.
-
If policy contains a directive whose name is "
script-src
", then set source-list to that directive’s value.Otherwise if policy contains a directive whose name is "
default-src
", then set source-list to that directive’s value. -
If source-list is non-null, and does not contain a source expression which is an ASCII case-insensitive match for the string "
'unsafe-eval'
", then throw anEvalError
-
5. 報告
1 つ以上の policy のディレクティブが違反を受けた際、violation report#violation-reportReferenced in:6.2.1. report-uri を作成して policy における reporting endpoint に送信することができます。
5.1. Violation DOM イベント
[Constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict)] interface SecurityPolicyViolationEvent : Event { readonly attribute DOMString documentURI#dom-securitypolicyviolationevent-documenturiReferenced in:5.3. violation を報告する ; readonly attribute DOMString referrer#dom-securitypolicyviolationevent-referrerReferenced in:5.3. violation を報告する ; readonly attribute DOMString blockedURI#dom-securitypolicyviolationevent-blockeduriReferenced in:5.3. violation を報告する ; readonly attribute DOMString violatedDirective#dom-securitypolicyviolationevent-violateddirectiveReferenced in:5.3. violation を報告する (2); readonly attribute DOMString effectiveDirective#dom-securitypolicyviolationevent-effectivedirectiveReferenced in:5.3. violation を報告する (2); readonly attribute DOMString originalPolicy#dom-securitypolicyviolationevent-originalpolicyReferenced in:5.3. violation を報告する ; readonly attribute DOMString sourceFile#dom-securitypolicyviolationevent-sourcefileReferenced in:5.3. violation を報告する ; readonly attribute unsigned short statusCode#dom-securitypolicyviolationevent-statuscodeReferenced in:5.3. violation を報告する ; readonly attribute long lineNumber#dom-securitypolicyviolationevent-linenumberReferenced in:5.3. violation を報告する ; readonly attribute long columnNumber#dom-securitypolicyviolationevent-columnnumberReferenced in:5.3. violation を報告する ; }; dictionary SecurityPolicyViolationEventInit#dictdef-securitypolicyviolationeventinitReferenced in:5.1. Violation DOM イベント : EventInit { DOMString documentURI; DOMString referrer; DOMString blockedURI; DOMString violatedDirective; DOMString effectiveDirective; DOMString originalPolicy; DOMString sourceFile; unsigned short statusCode; long lineNumber; long columnNumber; };
5.2. violation を廃止された方法でシリアライズしたものを取得する
ある violation (violation) に対して、このアルゴリズムは JSON 文字列で表現された violation を返します。この JSON テキストは、廃止された report-uri
ディレクティブに指定する reporting endpoint への送信に適しています。
-
以下に従ってプロパティを初期化した JavaScript オブジェクトを新しく作成し、それを object に代入します。
-
"
document-uri
" -
violation の url について、
exclude fragment
フラグをセットした状態で URL serializer を実行し、その結果を格納します。 -
"
referrer
" -
violation の referrer について、
exclude fragment
フラグをセットした状態で URL serializer を実行し、その結果を格納します。 -
"
blocked-uri
" -
violation の resource について、
exclude fragment
フラグをセットした状態で URL serializer を実行し、その結果を格納します。 -
"
effective-directive
" -
violation の effective directive を格納します。
-
"
violated-directive
" -
violation の effective directive を格納します。
-
"
original-policy
" -
violation の policy における serialization を格納します。
-
"
status-code
" -
violation の status を格納します。
-
-
ここで violation の source file が
null
ではなかった場合、以下を実行します。-
violation の source file について、
exclude fragment
フラグをセットした状態で URL serializer を実行し、その結果を object の "source-file
" プロパティに代入します。 -
object の "
line-number
" プロパティに violation の line number を代入します。 -
object の "
column-number
" プロパティに violation の column number を代入します。
-
-
object に
JSON.stringify()
を実行した結果を返します。
5.3. violation を報告する
ある violation (violation) に対するこのアルゴリズムは、violation の policy で指定したエンドポイントに violation を報告し、violation の global object における SecurityPolicyViolationEvent#securitypolicyviolationeventReferenced in:5.1. Violation DOM イベント 5.3. violation を報告する を発火させます。
-
以下のように属性値を初期化した
SecurityPolicyViolationEvent
インターフェイスを用いて、securitypolicyviolation
という名前の trusted イベントを fire します。-
violation の url
-
violation の referrer
-
violation の resource
-
violation の effective directive
-
violation の effective directive
-
violation の policy
-
violation の source file
-
violation の status
-
violation の line number
-
violation の column number
Note:
effectiveDirective
とviolatedDirective
には同じ値が格納されます。これは後方互換性が保たれるよう意図したものです。 -
ここで violation の policy における directive set に "
report-uri
" という directive (directive) が含まれていた場合、以下を実行します。-
ここで violation の policy における directive set に "
report-to
" という directive が含まれていた場合、残りの副手続きを飛ばします。 -
directive の value に対して URL parser を適用した結果を endpoint に代入します。
-
ここで endpoint が有効な URL でなかった場合、残りの副手続きを飛ばします。
-
新しい request を以下に従って初期化し、request に代入します。
-
"
POST
" -
violation の url
-
violation の global object における origin
-
"
no-window
" -
violation の global object における relevant settings object
-
""
-
""
-
""
-
"
no-cache
" -
"
same-origin
" -
名前を "
Content-Type
"、値を "application/csp-report
" とした単一のヘッダを含む header list -
violation に §5.2 violation を廃止された方法でシリアライズしたものを取得する を適用した結果
-
"
error
"
-
request を fetch します。ここでの実行結果は無視されます。
Note: この箇所はすべて廃止されたものと考えるべきです。ここでは 1 つの violation につき 1 つのリクエストを送信しており、単純にスケールできません。この箇所の動作をユーザエージェントから削除できる状態になれば廃止されることになります。
Note:
report-uri
はreport-to
が無い場合のみ有効になります。すなわち後者は前者を上書きするため、この新しい仕組みをサポートしていないブラウザへの後方互換性が保たれます。 -
-
ここで violation の policy における directive set に "
report-to
" という directive (directive) が含まれていた場合、以下を実行します。-
directive の value を group に代入します。
-
violation の global object における relevant settings object を settings object に代入します。
-
[OOB-REPORTING] の Queue data as type for endpoint group on settings アルゴリズムに以下の引数を与えて実行します。
-
data
-
violation
-
type
-
"CSP"
-
endpoint group
-
group
-
settings
-
settings object
-
-
6. Content Security Policy のディレクティブ
この仕様書では directives の種類が数多く定義されています。これらのディレクティブを用いることで、Web サイトの動作を開発者が制御できるようになります。この文書では、リソースの取得を制御するディレクティブ(§6.1 Fetch ディレクティブ群)と、報告を制御するディレクティブ(§6.2 Reporting Directives)が定義されます。これらのディレクティブは Content Security Policy の核を形成するものであり、他のディレクティブはモジュールとして付随文書で定義されます(使用例は §6.3 他の文書で定義されるディレクティブ を参照してください)。
クロスサイトスクリプティング攻撃のリスクを軽減するため、Web 開発者はスクリプトやプラグインの読込元を制限するディレクティブを含めるべきです(SHOULD)。これは以下のディレクティブを指定することで実現できます。
-
script-src と object-src ディレクティブの両方、または
-
default-src ディレクティブ
どちらの場合でも、開発者はポリシーの中に 'unsafe-inline'
や data:
を有効な読込元に含めるべきではありません(SHOULD NOT)。これらを指定すると、XSS 攻撃によってコードが直接ドキュメントの中に差し込まれる隙が生まれるため、どちらも全く使用しないことがベストです。
6.1. Fetch ディレクティブ群
Fetch directives#fetch-directivesReferenced in:6.1.3. default-src (2)6.1.11.5. request の effective directive を得る を用いると、ポリシーを適用させたいリソースの種類を指定したうえで、そのリソースの読込元を制御することができます。例えば script-src を用いた場合、ページ上で実行可能なスクリプトについて、信頼できる読込元をホワイトリスト化することができます。一方 font-src を用いた場合は、Web フォントの読込元を制御することができます。
6.1.1. child-src
child-src#child-srcReferenced in:6.1.1. child-src6.1.3. default-src (2) ディレクティブを用いると、nested browsing contexts (iframe
や frame
によるナビゲーションなど)の生成を制御したり、Worker の実行されるコンテキストを制御することができます。このディレクティブの名前と値に関する構文は、以下の ABNF で表現されます。
directive-name = "child-src" directive-value = serialized-source-list
このディレクティブは、フレームや Worker を生成する requests を制御します。より形式的に言えば、requests は以下の種類のうちどれか一つに分類されます。
-
destination が "
document
" であり、かつその target browsing context が nested browsing context(iframe
やframe
要素の中にデータを読み込むリクエストなど)であるもの -
destination が "
serviceworker
"、"sharedworker
"、"worker
" のいずれかであるもの(これらは各々ServiceWorker
、SharedWorker
、Worker
における run a worker アルゴリズムに適用されます)
Content-Security-Policy: child-src https://example.com/
以下のコードによって生じた通信は、指定されている URL が child-src
の source list にマッチしないため、すべてネットワークエラーが返されます。
<iframe src="https://not-example.com"></iframe> <script> var blockedWorker = new Worker("data:application/javascript,..."); </script>
6.1.1.1. アルゴリズム
このディレクティブの pre-request check は次の通りです。
ある request (request) に対して以下を実行します。
このディレクティブの post-request check は次の通りです。
6.1.2. connect-src
connect-src#connect-srcReferenced in:6.1.2. connect-src6.1.3. default-src (2) ディレクティブを用いると、スクリプトのインターフェイスを利用して読み込む URL を制御することができます。このディレクティブの名前と値に関する構文は、以下の ABNF で表現されます。
directive-name = "connect-src" directive-value = serialized-source-list
このディレクティブでは、他のオリジンとデータを送受信する requests を制御します。この requests は、fetch()
や [XHR]、[EVENTSOURCE]、[BEACON]、そして a
要素の ping
属性といった API を経由して生成されるものです。加えて、技術的には Fetch と異なるものの、connect-src
ディレクティブは WebSocket [WEBSOCKETS] の接続も制御します。
EventSource
、ブラウザとサーバとの間に双方向の通信路を確立する WebSockets
、そしてユーザに代わって任意の HTTP リクエストを生成する XMLHttpRequest
といった具合です。こういった強力な API によって利便性が向上する一方、データを窃取する巧妙な手法も編み出されています。
connect-src
ディレクティブを用いることで、こういった類の接続先を信頼できるオリジンのみに制限することができます。このディレクティブに関しては、必要な source expressions を定義してポリシーを送信するのは単純な作業で済みます。例として、接続先を https://example.com
のみに限定したい場合は、次のようなヘッダを送信することになります。
Content-Security-Policy: connect-src https://example.com/
以下のコードを用いて接続を試みると、connect-src
の source list と URL がマッチしないため、すべてネットワークエラーが返されます。
<a ping="https://not-example.com">... <script> var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://not-example.com/'); xhr.send(); var ws = new WebSocket("https://not-example.com/"); var es = new EventSource("https://not-example.com/"); navigator.sendBeacon("https://not-example.com/", { ... }); </script>
6.1.2.1. アルゴリズム
このディレクティブにおける pre-request check は以下の通りです。
ある request (request) と policy (policy) に対して、以下を実行します。
-
ここで request の initiator が "
fetch
" だった場合、または request の type が "" かつ destination が "subresource
" だった場合、以下を実行します。-
ここで request の url とディレクティブの value に対して §6.1.11.3 url は source list にマッチするか? を適用し、その実行結果が "
Does Not Match
" だった場合、"Blocked
" を返します。
-
-
"
Allowed
" を返します。
このディレクティブにおける post-request check は以下の通りです。
ある request (request) と response (response) と policy (policy) に対して、以下を実行します。
-
ここで request の initiator が "
fetch
" だった場合、または request の type が "" かつ destination が "subresource
" だった場合、以下を実行します。-
ここで response の url とディレクティブの value に対して §6.1.11.3 url は source list にマッチするか? を適用し、その実行結果が "
Does Not Match
" だった場合、"Blocked
" を返します。
-
-
"
Allowed
" を返します。
6.1.3. default-src
default-src#default-srcReferenced in:6. Content Security Policy のディレクティブ 6.1.3. default-src (2) (3) ディレクティブは、他の fetch directives におけるフォールバックの役を担います。このディレクティブの名前と値に関する構文は、以下の ABNF で表現されます。
directive-name = "default-src" directive-value = serialized-source-list
ポリシーに default-src ディレクティブが含まれていた場合、その値はポリシーにおけるデフォルトの source list として扱われます。つまり、default-src 'none'; script-src 'self'
を指定した場合、スクリプトのリクエストに対するマッチの基準には 'self'
が用いられ、他のリクエストに対するマッチの基準には 'none'
が用いられます。この部分に関しては、アルゴリズム §4.1.3 request は Content Security Policy によってブロックされるべきか? と §4.1.4 request に対する response は Content Security Policy によってブロックされるべきか? の節で詳しく説明されています。
Content-Security-Policy: default-src 'self'
以下のようにディレクティブを指定した場合と等価です。
Content-Security-Policy: child-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self'; manifest-src 'self'; media-src 'self'; object-src 'self'; script-src 'self'; style-src 'self'
すなわち default-src
に値が指定されていれば、明示的に値が指定されていない fetch directive のディレクティブ各々について、default-src
の値にフォールバックすることになります。
script-src
ディレクティブが明示的に指定されている場合、default-src
の値はスクリプトのリクエストに対して何も影響を与えません。すなわち、ヘッダが以下のように与えられている場合、
Content-Security-Policy: default-src 'self'; script-src https://example.com
以下のようにディレクティブを指定した場合と等価です。
Content-Security-Policy: child-src 'self'; connect-src 'self'; font-src 'self'; img-src 'self'; manifest-src 'self'; media-src 'self'; object-src 'self'; script-src https://example.com; style-src 'self'
この挙動を踏まえると、Web サイトのポリシーを構築する際はまず default-src
に 'none'
を指定しておき、そこからページごとに必要なリソースの種類のみを許可するようなポリシーを組み上げていくのが良いでしょう。
6.1.3.1. アルゴリズム
このディレクティブにおける pre-request check は以下の通りです。
ある request (request) と a policy (policy) に対して以下を実行します。
-
request に対して §6.1.11.5 request の effective directive を得る を実行した結果を name に代入します。
-
ここで name が
null
だった場合、"Allowed
" を返します。 -
ここで、name と等しい name を持つ directive が policy に含まれていた場合、"
Allowed
" を返します。 -
Otherwise, return the result of executing the pre-request check for the directive whose name is name on request and policy, using this directive’s value for the comparison.
このディレクティブにおける post-request check は以下の通りです。
ある request (request) と response (response) と policy (policy) に対し、以下を実行します。
-
request に §6.1.11.5 request の effective directive を得る を適用した結果を name に代入します。
-
ここで name が
null
だった場合、"Allowed
" を返します。 -
ここで、name と等しい name を持つ directive が policy に含まれていた場合、"
Allowed
" を返します。 -
Otherwise, return the result of executing the pre-request check for the directive whose name is name on request and policy, using this directive’s value for the comparison.
6.1.4. font-src
The font-src#font-srcReferenced in:6.1. Fetch ディレクティブ群 6.1.3. default-src (2)6.1.4. font-src directive restricts the URLs from which font resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "font-src" directive-value = serialized-source-list
Content-Security-Policy: font-src https://example.com/
Fetches for the following code will return a network errors, as the URL
provided do not match font-src
's source list:
<style> @font-face { font-family: "Example Font"; src: url("https://not-example.com/font"); } body { font-family: "Example Font"; } </style>
6.1.4.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "
font
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "
font
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
6.1.5. img-src
The img-src#img-srcReferenced in:6.1.3. default-src (2)6.1.5. img-src directive restricts the URLs from which image resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "img-src" directive-value = serialized-source-list
This directive controls requests which load images. More formally, this
includes requests whose type is "image
" [FETCH].
Content-Security-Policy: img-src https://example.com/
Fetches for the following code will return a network errors, as the URL
provided do not match img-src
's source list:
<img src="https://not-example.com/img">
6.1.5.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "
image
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "
image
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
6.1.6. manifest-src
The manifest-src#manifest-srcReferenced in:6.1.3. default-src (2)6.1.6. manifest-src directive restricts the URLs from which application manifests may be loaded [APPMANIFEST]. The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "manifest-src" directive-value = serialized-source-list
Content-Security-Policy: manifest-src https://example.com/
Fetches for the following code will return a network errors, as the URL
provided do not match manifest-src
's source list:
<link rel="manifest" href="https://not-example.com/manifest">
6.1.6.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "", and its initiator is "
manifest
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "", and its initiator is "
manifest
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
6.1.7. media-src
The media-src#media-srcReferenced in:6.1.3. default-src (2)6.1.7. media-src directive restricts the URLs from which video, audio, and associated text track resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "media-src" directive-value = serialized-source-list
Content-Security-Policy: media-src https://example.com/
Fetches for the following code will return a network errors, as the URL
provided do not match media-src
's source list:
<audio src="https://not-example.com/audio"></audio> <video src="https://not-example.com/video"> <track kind="subtitles" src="https://not-example.com/subtitles"> </video>
6.1.7.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is one of "
audio
", "video
", or "track
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is one of "
audio
", "video
", or "track
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
6.1.8. object-src
The object-src#object-srcReferenced in:6. Content Security Policy のディレクティブ 6.1.3. default-src (2)6.1.8. object-src directive restricts the URLs from which plugin content may be loaded. The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "object-src" directive-value = serialized-source-list
Content-Security-Policy: object-src https://example.com/
Fetches for the following code will return a network errors, as the URL
provided do not match object-src
's source list:
<embed src="https://not-example.com/flash"></embed> <object data="https://not-example.com/flash"></object> <applet archive="https://not-example.com/flash"></applet>
If plugin content is loaded without an associated URL (perhaps an object
element lacks a data
attribute, but loads some default plugin based
on the specified type
), it MUST be blocked if object-src
's value is 'none'
, but will otherwise be allowed.
Note: The object-src
directive acts upon any request made on behalf of
an object
, embed
, or applet
element. This includes requests
which would populate the nested browsing context generated by the
former two (also including navigations). This is true even when the data is
semantically equivalent to content which would otherwise be restricted by
another directive, such as an object
element with a text/html
MIME
type.
6.1.8.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "", and its destination is "
unknown
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "", and its destination is "
unknown
":-
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
6.1.9. script-src
The script-src#script-srcReferenced in:6.
Content Security Policy のディレクティブ 6.1.
Fetch ディレクティブ群 6.1.3. default-src (2) (3) directive restricts the locations from which scripts
may be executed. This includes not only URLs loaded directly into script
elements, but also things like inline script blocks and XSLT stylesheets [XSLT] which can trigger script execution. The syntax for the directive’s
name and value is described by the following ABNF:
directive-name = "script-src" directive-value = serialized-source-list
The script-src
directive governs four things:
-
Script requests MUST pass through §4.1.3 request は Content Security Policy によってブロックされるべきか?.
-
Script responses MUST pass through §4.1.4 request に対する response は Content Security Policy によってブロックされるべきか?.
-
Inline
script
blocks MUST pass through §4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか?. Their behavior will be blocked unless every policy allows inline script, either implicitly by not specifying ascript-src
(ordefault-src
) directive, or explicitly, by whitelisting "unsafe-inline
", a nonce-source or a hash-source that matches the inline block. -
The following JavaScript execution sinks are gated on the "
unsafe-eval
" source expression:-
setTimeout()
with an initial argument which is not callable. -
setInterval()
with an initial argument which is not callable.
Note: If a user agent implements non-standard sinks like
setImmediate()
orexecScript()
, they SHOULD also be gated on "unsafe-eval
".
6.1.9.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "
script
", and its destination is "subresource
":-
If the result of executing §6.1.11.2 Does nonce match source list? on request’s cryptographic nonce metadata and this directive’s value is "
Matches
", return "Allowed
". -
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "
script
", and its destination is "subresource
":-
If the result of executing §6.1.11.2 Does nonce match source list? on request’s cryptographic nonce metadata and this directive’s value is "
Matches
", return "Allowed
". -
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s inline check algorithm is as follows:
Given an Element
(element) and a string (type):
-
If type is "
script
" or "script attribute
":-
If the result of executing §6.1.12.1 Does element match source list? on element, this directive’s value, and type is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s initialization algorithm is as follows:
Do something interesting to the execution context in order to lock down eval()
, et al. I don’t think ECMA gives us any hooks here, so let’s work
with them to put something reasonable together.
6.1.10. style-src
The style-src#style-srcReferenced in:6.1.3. default-src (2) directive restricts the locations from which style
may be applied to a Document
. The syntax for the directive’s name and
value is described by the following ABNF:
directive-name = "style-src" directive-value = serialized-source-list
The style-src
directive governs several things:
-
Style requests MUST pass through §4.1.3 request は Content Security Policy によってブロックされるべきか?. This includes:
-
Responses to style requests MUST pass through §4.1.4 request に対する response は Content Security Policy によってブロックされるべきか?.
-
Inline
style
blocks MUST pass through §4.2.3 element においてインラインの type に関する挙動は Content Security Policy によってブロックされるべきか?. The styles will be blocked unless every policy allows inline style, either implicitly by not specifying ascript-src
(ordefault-src
) directive, or explicitly, by whitelisting "unsafe-inline
", a nonce-source or a hash-source that matches the inline block. -
The following CSS algorithms are gated on the
unsafe-eval
source expression:This would include, for example, all invocations of CSSOM’s various
cssText
setters andinsertRule
methods [CSSOM] [HTML5].
6.1.10.1. Algorithms
This directive’s pre-request check is as follows:
Given a request (request) and a policy (policy):
-
If request’s type is "
style
":-
If the result of executing §6.1.11.2 Does nonce match source list? on request’s cryptographic nonce metadata and this directive’s value is "
Matches
", return "Allowed
". -
If the result of executing §6.1.11.3 url は source list にマッチするか? on request’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s post-request check is as follows:
Given a request (request), a response (response), and a policy (policy):
-
If request’s type is "
style
":-
If the result of executing §6.1.11.2 Does nonce match source list? on request’s cryptographic nonce metadata and this directive’s value is "
Matches
", return "Allowed
". -
If the result of executing §6.1.11.3 url は source list にマッチするか? on response’s url and this directive’s value is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s inline check algorithm is as follows:
Given an Element
(element) and a string (type):
-
If type is "
style
" or "style attribute
":-
If the result of executing §6.1.12.1 Does element match source list? on element, this directive’s value, and type is "
Does Not Match
", return "Blocked
".
-
-
Return "
Allowed
".
This directive’s initialization algorithm is as follows:
Do something interesting to the execution context in order to lock down interesting CSSOM algorithms. I don’t think CSSOM gives us any hooks here, so let’s work with them to put something reasonable together.
6.1.11. URL のマッチングアルゴリズム
6.1.11.1. request はpolicy に違反するか?
ある request (request) と policy (policy) に対し、このアルゴリズムはリクエストによって違反を受けたポリシーを返し、違反を受けたポリシーがなければ "Does Not Violate
" を返します。
-
violates に "
Does Not Violate
" を代入します。 -
policy に含まれる directive のそれぞれについて以下を実行します。
-
request と policy に対して pre-request check を実行し、その結果を result に代入します。
-
ここで result が "
Blocked
" だった場合、violates に directive を代入します。
-
-
violates を返します。
6.1.11.2. Does nonce match source list?
Given a request’s cryptographic nonce metadata (nonce) and a source list (source list), this algorithm returns
"Matches
" if the nonce matches one or more source expressions in the list,
and "Does Not Match
" otherwise:
-
If source list is
null
, or nonce is the empty string, return "Does Not Match
". -
For each expression in source list:
-
If expression matches the
nonce-source
grammar, and nonce is a case-sensitive match for expression’sbase64-value
part, return "Matches
".
-
-
Return "
Does Not Match
".
6.1.11.3. url は source list にマッチするか?
ある URL
(url) と source list (source list) に対するこのアルゴリズムは、source list に含まれる source expressions の 1 つ以上に URL がマッチすれば "Matches
" を返し、それ以外の場合は "Does Not Match
" を返します。
-
ここで source list が
null
だった場合、"Matches
" を返します。 -
ここで、文字列 "
'none'
" に ASCII case-insensitive match する単一の要素が source list に含まれていた場合、"Does Not Match
" を返します。 -
source list に含まれる要素 expression のそれぞれについて以下を実行します。
-
ここで url と expression に対して §6.1.11.4 redirect count を持つ origin において url は expression にマッチするか? を適用し、その実行結果が "
Matches
" であれば "Matches
" を返します。
-
-
"
Does Not Match
" を返します。
6.1.11.4. redirect count を持つ origin において url は expression にマッチするか?
ある URL
(url) と source expression (expression) と origin (origin) と数値 (redirect count) に対し、このアルゴリズムは url が expression にマッチすれば "Matches
" を返し、それ以外の場合は "Does Not Match
" を返します。
Note: origin とは、expression が相対的に解決されるべきリソースの origin です。例えば、"'self'
" はコンテキストによって別々の意味を持つことになります。
-
ここで expression が文字列 "*" であり、かつ url の
scheme
が local scheme ではない場合、"Matches
" を返します。 -
ここで expression が
scheme-source
またはhost-source
の文法に一致する場合、以下を実行します。-
ここで、url の
scheme
に ASCII case-insensitive match するscheme-part
を expression が持たず、かつ以下の条件をいずれも満たさない場合、"Does Not Match
" を返します。-
expression の
scheme-part
が "http
" に ASCII case-insensitive match し、かつ url のscheme
が "https
" である -
expression の
scheme-part
が "ws
" に ASCII case-insensitive match し、かつ url のscheme
が "wss
" である
-
-
ここで expression が
scheme-source
の文法に一致する場合、"Matches
" を返します。
Note: この処理が鍵となり、
script-src http:
がscript-src http: https:
と等しく、script-src http://example.com/
がscript-src http://example.com https://example.com
と等しくなります。つまり、明示的に書かれた安全でない式を、安全な式へ自動変換することが常に可能となります。 -
-
ここで expression が
host-source
の文法に一致する場合、以下を実行します。-
ここで url の
host
がnull
である場合、"Does Not Match
" を返します。 -
ここで expression に
scheme-part
がなく、かつ以下の条件をいずれも満たさない場合に "Does Not Match
" を返します。Note: 先程の
scheme-part
に関する処理と同様に、source expression がスキームを持たないhost-source
であれば、安全なスキームへ自動変換することが可能です。 -
ここで expression の
host-part
における先頭文字が U+002A ASTERISK 文字 (*
) だった場合、以下を実行します。-
expression から先頭の "
*
" を取り除いた結果を remaining に代入します。 -
ここで(先頭に U+002E FULL STOP 文字 (
.
) を含む)remaining が、url のhost
における最右端の文字列に ASCII case-insensitive match する場合、"Does Not Match
" を返します。
-
-
ここで expression の
host-part
における先頭文字が U+002A ASTERISK 文字 (*
) ではなく、かつ url のhost
が expression のhost-part
に ASCII case-insensitive match しない場合、"Does Not Match
" を返します。 -
ここで expression の
host-part
が IPv4address の文法 [RFC3986] に一致し、かつ "127.0.0.1
" ではない場合、または expression のhost-part
が IPv6 address の文法に一致する場合、"Does Not Match
" を返します。Note: 将来の仕様では、利用の度合いと要望に応じて IPv6 と IPv4 のアドレスリテラルが使えるようになるかもしれません。とはいえ、名前ベースのホストと比較して IP アドレスのセキュリティ特性は弱いため、Web サイトの管理者は可能な限り後者を用いることが推奨されます。
-
ここで expression に
port-part
が含まれておらず、かつ url のport
が url のscheme
に対する default port ではない場合、"Does Not Match
" を返します。 -
ここで expression に
port-part
が含まれる場合、以下を実行します。 -
ここで expression に空でない
path-part
が含まれており、かつ redirect count が 0 である場合、以下を実行します。-
ここで expression の
path-part
における末尾文字が U+002F SOLIDUS 文字 (/
) である場合、exact match にfalse
を代入し、それ以外の場合はtrue
を代入します。 -
expression の
path-part
を U+002F SOLIDUS 文字 (/
) で strictly splitting した結果を path list に代入します。 -
ここで path list が url の
path
よりも多くの要素を含んでいる場合、"Does Not Match
" を返します。 -
ここで exact match が
true
であり、かつ path list が url のpath
と同じ要素数を含む場合、"Does Not Match
" を返します。 -
path list に含まれる expression piece のそれぞれについて以下を実行します。
-
url の
path
における次の要素を url piece に代入します。 -
expression piece を Percent decode します。
-
url piece を Percent decode します。
-
ここで expression piece が url piece に case-sensitive で一致しない場合、"
Does Not Match
" を返します。
-
-
-
"
Matches
" を返します。
-
-
ここで expression が "
'self'
" に ASCII case-insensitive match し、かつ以下の条件のうち 1 つ以上を満たすならば "Matches
" を返します。-
origin が url の
origin
に等しい場合 -
origin の
host
が url のhost
に等しく、かつ origin のport
が url のport
かscheme
の default ports に等しく、かつ以下の条件のうちどちらかを満たす
Note: 先程の
scheme-part
に関する処理と同様に、"'self'
" のマッチングアルゴリズムにおける安全なスキームへの自動変換は、その変換が安全である限り可能です。この変換は、特定のスキームに対するデフォルトポートか、保護されたリソースのオリジンにおけるポートかで動作しているエンドポイントに限られます。とはいえ、この制限があったとしても、変換が成り立つケースは十分にカバーされるはずです。 -
-
"
Does Not Match
" を返します。
6.1.11.5. request の effective directive を得る
各 fetch directive は request のタイプを制御します。ある request (request) に対し、このアルゴリズムは null
を返すか、リクエストの effective directive における name を返します。
-
request の type に対応する処理を以下から実行します。
-
""
-
-
ここで request の initiator が "
fetch
" だった場合、connect-src
を返します。 -
ここで request の initiator が "
manifest
" だった場合、manifest-src
を返します。 -
ここで request の destination が "
subresource
" だった場合、connect-src
を返します。 -
ここで request の destination が "
unknown
" だった場合、object-src
を返します。 -
ここで request の destination が "
document
" であり、かつ request の target browsing context が nested browsing context だった場合、child-src
を返します。
-
-
"
audio
""
track
""
video
" -
-
media-src
を返します。
-
-
"
font
" -
-
font-src
を返します。
-
-
"
image
" -
-
image-src
を返します。
-
-
"
style
" -
-
style-src
を返します。
-
-
"
script
" -
-
request の destination に対応する処理を以下から実行します。
-
"
subresource
" -
-
script-src
を返します。
-
-
"
serviceworker
""
sharedworker
""
worker
" -
-
child-src
を返します。
-
-
-
-
-
null
を返します。
6.1.12. Element Matching Algorithms
6.1.12.1. Does element match source list?
Given an Element
(element), a source list (list), and a string
(type), this algorithm returns "Matches
" or "Does Not Match
".
-
Let contains nonce or hash be
false
. -
For each expression in list:
-
If expression matches the
nonce-source
orhash-source
grammar, set contains nonce or hash totrue
.
-
-
If contains nonce or hash is
false
, and list contains a source expression which is an ASCII case-insensitive match for the string "unsafe-inline
", then return "Matches
". -
If type is not "
script attribute
" or "style attribute
":-
If type is "
script
" and element has an attribute whose name is an ASCII case-insensitive match for the string "<script
", or type is "style
" and element has an attribute whose name is an ASCII case-insensitive match for the string "<style
", then return "Does Not Match
". -
Let content be the script block’s source if element is a
script
element, or the value of element’stextContent
IDL attribute for any other element. -
For each expression in list:
-
If expression matches the
nonce-source
grammar, and element has anonce
attribute whose value is a case-sensitive match for expression’sbase64-value
part, return "Matches
". -
If expression matches the
hash-source
grammar:-
Let algorithm be
null
. -
If expression’s
hash-algorithm
part is an ASCII case-insensitive match for "sha256", set algorithm to SHA-256. -
If expression’s
hash-algorithm
part is an ASCII case-insensitive match for "sha384", set algorithm to SHA-384. -
If expression’s
hash-algorithm
part is an ASCII case-insensitive match for "sha512", set algorithm to SHA-512. -
If algorithm is not
null
:-
Let actual be the result of base64 encoding the result of applying algorithm to content.
-
If actual is a case-sensitive match for expression’s
base64-value
part, return "Matches
".
-
-
-
-
-
Return "
Does Not Match
".
6.2. Reporting Directives
Various algorithms in this document hook into the reporting process by constructing a violation object via §2.3.2 request、policy、directive に対する violation オブジェクトの生成 or §2.3.1 global、policy、directive に対する violation オブジェクトの生成, and passing that object to §5.3 violation を報告する to deliver the report.
6.2.1. report-uri
report-uri
directive is deprecated. Please use the report-to
directive instead. If the latter directive is present,
this directive will be ignored. To ensure backwards compatibility, we
suggest specifying both, like this:
Content-Security-Policy: ...; report-uri https://endpoint.com; report-to groupname
The report-uri
#report-uriReferenced in:5.2.
violation を廃止された方法でシリアライズしたものを取得する 5.3.
violation を報告する 6.2.1. report-uri (2) directive defines a set of endpoints to which violation reports will be sent when particular behaviors are prevented.
directive-name = "report-uri" directive-value = uri-reference *( RWS uri-reference ) ; The uri-reference grammar is defined in Section 4.1 of RFC 3986.
The directive has no effect in and of itself, but only gains meaning in combination with other directives.
6.2.2. report-to
The report-to
#report-toReferenced in:5.3.
violation を報告する (2)6.2.1. report-uri (2) directive defines a reporting
group to which violation reports ought to be sent [OOB-REPORTING]. The
directive’s behavior is defined in §5.3 violation を報告する. The directive’s name
and value are described by the following ABNF:
directive-name = "report-to" directive-value = token
6.3. 他の文書で定義されるディレクティブ
この文書では主要なディレクティブを定義しており、また他の仕様書によってモジュール的に拡張できるような枠組みを整備しています。この文書が作成された時点で、CSP を拡張する文書として安定しているものは以下の通りです。
-
[MIX] では
block-all-mixed-content
を定義しています -
[UPGRADE-INSECURE-REQUESTS] では
upgrade-insecure-requests
を定義しています -
[CSP-DOCUMENT] では
base-uri
、form-action
、frame-ancestors
、plugin-types
、sandbox
を定義しています。
CSP を拡張する際は draft-west-webappsec-csp-reg で説明されている手続きに従って内容を登録しなければなりません(MUST)。特に、その文書の 3.2 章で議論されている要件には注意してください。
Fetch や HTML と連携できるよう、新しいディレクティブは pre-request check と post-request check、initialization の各フックを用いるべきです(SHOULD)。
7. セキュリティに関して考慮すべき事項
7.1. nonce の再利用
ディレクティブに nonce が指定されている場合、そのディレクティブで指定された他の制限を nonce で回避することが可能です。従って、nonce を推定できないように維持することが肝心であり、さもないとリソースに適用されたポリシーを容易に回避できてしまいます。
サーバが policy の一部として nonce-source を伝達する場合、サーバはポリシーを送信するごとに固有な値を生成しなければなりません(MUST)。生成された値は(エンコーディング前で)最低 128 ビット 以上の長さを持つべきです(SHOULD)。また、攻撃者による値の予想を困難にするため、値の生成方法は暗号論的に安全な乱数生成器を用いるべきです(SHOULD)。
補足: インラインのスクリプトやスタイルをホワイトリスト化するために nonce を用いてしまうと、nonce を使わない場合よりも安全性が失われます。なぜなら、nonce を指定したディレクティブの制限を nonce によって回避できるからです。その nonce の値を知っている攻撃者は、任意のタイミングで任意のスクリプトを実行できてしまいます。しかしながら、既存のコードの上に Content Security Policy を構築する場合、'unsafe-inline' を用いるよりも nonce のほうが防御策として価値があります。もしあなたが開発者として 'unsafe-inline' の利用を検討している場合、代わりに nonce (またはハッシュ値)を用いることを推奨します。
8. 利用に関して考慮すべき事項
8.1. 複数のポリシーによる影響
この章は非規範的です。
複数のポリシーが提示された際の挙動については、それぞれを種類に応じて適用・報告しなければならない旨を以前の章で述べました。これが実際にどう動作すべきなのか明確にするため、以下に例を示します。以下の HTTP ヘッダを送出する Web サイトを考えた際、様々な理由で XMLHttpRequest
の動作が分かりにくくなるかもしれません。
Content-Security-Policy: default-src 'self' http://example.com http://example.net; connect-src 'none'; Content-Security-Policy: connect-src http://example.com/; script-src http://example.com/
example.com へのアクセスは許可されるでしょうか?端的に言えば「許可されない」が答えとなります。両方のポリシーが適用されるため、もしその接続が許可されるのであれば、両方のポリシーを無事に通り抜けることが必要となるでしょう。2 番目のポリシーはこの接続を許可しています。とはいえ、1 番目のポリシーには connect-src 'none'
が含まれているため、これが適用されて接続はブロックされます。複数のポリシーによる影響として、新たなポリシーを適用した場合は、保護されたリソースの能力を制限することのみが可能であるといえます。
さらに詳しく説明するため、このページに script タグがあった場合を考えます。1 番目のポリシーは default-src
ディレクティブの指定により、スクリプトの読込元を 'self'
と http://example.com
と http://example.net
に制限します。しかし、2 番目のポリシーでは http://example.com
のスクリプトを許可しています。ここで、スクリプトは両方のポリシーの要件を満たした場合にのみ読み込まれます。すなわち、今回の場合でマッチするオリジンは、両方のポリシーが許可している http://example.com
のみとなります。
9. 実装に関して考慮すべき事項
9.1. ベンダー独自の拡張機能やアドオン
リソースに適用された policy は、ユーザエージェントの機能(アドオン、拡張機能、ブックマークレットなど)の動作に干渉するべきではありません(SHOULD NOT)。[HTML-DESIGN] で提唱されている通り、一般にこれらの機能によって Web ページの作成者よりもユーザが優先されます。
加えて、このような機能に CSP を適用してしまうと、大量の違反レポートがノイズのように発生し、開発者から見た CSP の価値を大きく下げてしまいます。
例えば Chrome の場合、CSP の検査項目から chrome-extension:
スキームを除くことが一定の役割を果たします。すなわちページのポリシーに関係なく、拡張機能からコンテンツを注入できることが保障されます。
10. IANA に関して考慮すべき事項
permanent message header field のレジストリは、以下の登録手続きによって更新されるはずです。[RFC3864]
10.1. Content-Security-Policy
- Header field name
- Content-Security-Policy
- Applicable protocol
- http
- Status
- standard
- Author/Change controller
- W3C
- Specification document
- This specification (See §3.1 Content-Security-Policy HTTP レスポンスヘッダフィールド)
11. 謝辞
偉大なる多くの方々