ウェブのセキュリティ モデルは、同一オリジン ポリシーがベースになっています。https://mybank.com
のコードは https://mybank.com
のデータにのみアクセスでき、https://evil.example.com
にはアクセスできないようにする必要があります。各オリジンはウェブの残りの部分から隔離されるので、デベロッパーがコードをビルドして実行できる安全なサンドボックスが提供されます。理論上これは非常に優れたモデルです。実際には、攻撃者は巧妙な方法を見つけてシステムを妨害します。
たとえば、クロスサイト スクリプティング(XSS)攻撃は、意図するコンテンツとともに悪質なコードを提供するようにサイトを仕向けることによって、同一生成元ポリシーを回避します。これは大きな問題です。ブラウザは、ページに表示されるすべてのコードを、そのページのセキュリティ オリジンに正当に含まれているものとして信頼するからです。XSS クイック リファレンスは、攻撃者が悪意のあるコードを注入してこの信頼を侵害するために使用する可能性がある手法のうち、古いものだが代表的な例です。攻撃者がなんらかのコードの注入に成功すると、それでほぼゲームオーバーです。ユーザー セッション データが侵害され、知らないうちに機密情報が悪意を持つ人に渡されてしまいます。明らかにこれは可能な限り回避する必要があることです。
この概要では、最新のブラウザにおける XSS 攻撃のリスクと影響を大幅に軽減できるコンテンツ セキュリティ ポリシー(CSP)に焦点を当てます。
要約
- 許可リストを使用して、許可または不許可の対象をクライアントに指示します。
- 使用可能なディレクティブについて説明します。
- ディレクティブに指定できるキーワードについて説明します。
- インラインコードと
eval()
は有害と見なされます。 - ポリシーを適用する前に、ポリシー違反をサーバーに報告します。
ソースの許可リスト
XSS 攻撃によって引き起こされる問題は、ブラウザが、アプリケーションに含まれるスクリプトと、悪意のある第三者が注入したスクリプトを区別できなくなることです。たとえば、このページの下部にある Google +1 ボタンは、オリジンがこのページのオリジンであるという条件で、https://apis.google.com/js/plusone.js
から取得したコードを読み込み、実行します。私たちはこのコードを信頼していますが、ブラウザに対して、apis.google.com
から取得したコードはすばらしいが apis.evil.example.com
から取得したコードは問題がある、と見分けることは期待できません。このブラウザは参照元にかかわらず、ただ素直にページが要求するコードをダウンロードして実行します。
CSP では、サーバーから配信されるすべてのすべてをやみくもに信頼するのではなく、Content-Security-Policy
HTTP ヘッダーを定義します。これにより、信頼できるコンテンツのソースの許可リストを作成し、それらのソースからのリソースのみを実行またはレンダリングするようにブラウザに指示できます。攻撃者がスクリプトを注入するセキュリティ ホールを見つけたとしても、許可リストに一致しなければそのスクリプトは実行されません。
apis.google.com
は有効なコードを配信すると信頼しています。また、自身のドメインも同様に信頼できるので、この 2 つのリソースのうちどちらかを取得した場合にのみスクリプトを実行できるポリシーを定義してみましょう。
Content-Security-Policy: script-src 'self' https://apis.google.com
実に簡単ですね。お気づきのとおり、script-src
は、特定のページでスクリプト関連の権限を制御するディレクティブです。スクリプトの有効な参照元として 'self'
ともう 1 つ、https://apis.google.com
を指定しました。ブラウザは HTTPS を介して、オリジンが現在のページおよび apis.google.com
の JavaScript を従順にダウンロードし、実行します。
このポリシーを定義すると、ブラウザはそれ以外の参照元からのスクリプトは読み込まず、単純にエラーをスローします。巧妙な攻撃者がサイトにコードを挿入しようとすると、予期していた成功ではなく、逆方向にエラー メッセージが表示されます。
幅広いリソースに適用するポリシー
スクリプト リソースは、最も明確なセキュリティ リスクですが、CSP では、ページで読み込みが許可されるリソースをさらに細かく制御できるポリシー ディレクティブの豊富なセットを提供しています。script-src
についてはすでに説明したので、そのコンセプトはもうおわかりでしょう。
続いて、その他のリソース ディレクティブについて簡単に説明します。次のリストは、レベル 2 時点でのディレクティブの状態を示しています。レベル 3 の仕様は公開されていますが、主要なブラウザではほとんど実装されていません。
base-uri
は、ページの<base>
要素に表示できる URL を制限します。child-src
には、ワーカーと埋め込みフレーム コンテンツの URL が一覧表示されます。たとえば、child-src https://youtube.com
に設定すると、YouTube からの動画の埋め込みが有効になりますが、他のオリジンの動画は埋め込みできません。connect-src
は、XHR、WebSocket、EventSource を介して接続できる送信元を制限します。font-src
は、ウェブフォントを配信できるオリジンを指定します。Google のウェブフォントはfont-src https://themes.googleusercontent.com
で有効にできます。form-action
には、<form>
タグからの送信に有効なエンドポイントが一覧表示されます。frame-ancestors
は、現在のページを埋め込むことができるソースを指定します。このディレクティブは、<frame>
タグ、<iframe>
タグ、<embed>
タグ、<applet>
タグに適用されます。このディレクティブは<meta>
タグで使用できず、非 HTML リソースにのみ適用されます。frame-src
はレベル 2 で非推奨になりましたが、レベル 3 で復元されています。存在しない場合は、以前と同様にchild-src
にフォールバックします。img-src
は、画像の読み込み元となるオリジンを定義します。media-src
は、動画と音声を配信できるオリジンを制限します。object-src
は、Flash などのプラグインを制御できます。plugin-types
は、ページで起動できるプラグインの種類を制限します。report-uri
は、コンテンツ セキュリティ ポリシーが違反されたときにレポートを送信する URL を指定します。このディレクティブは、<meta>
タグでは使用できません。style-src
は、スタイルシートのscript-src
に相当します。upgrade-insecure-requests
は、ユーザー エージェントに指示して URL スキーマを書き直し、HTTP を HTTPS に変更します。このディレクティブは、書き直しが必要な古い URL が多数存在するウェブサイトに使用します。worker-src
は、ワーカー、共有ワーカー、または Service Worker として読み込まれる URL を制限する CSP レベル 3 ディレクティブです。2017 年 7 月現在、このディレクティブの実装は制限されています。
デフォルトでは、ディレクティブに制限はありません。ディレクティブに特定のポリシーを設定しない場合(font-src
など)、そのディレクティブは、有効な参照元として *
を指定した場合と同じようにデフォルトで動作します(たとえば、制限なしでどこからでもフォントを読み込むことができます)。
このデフォルトの動作は、default-src
ディレクティブを指定することでオーバーライドできます。このディレクティブは、指定しないほとんどのディレクティブのデフォルトを定義します。一般に、これは末尾が -src
のディレクティブに適用されます。default-src
が https://example.com
に設定され、font-src
ディレクティブを指定しなかった場合、https://example.com
からフォントを読み込むことはできますが、それ以外からは読み込めません。上記の例では script-src
のみを指定しました。つまり、画像やフォントなどを任意のオリジンから読み込めます。
次のディレクティブは、フォールバックとして default-src
を使用しません。設定しない場合はすべて許可したのと同じです。
base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox
これらのディレクティブは、アプリケーションに合わせて目的の数だけ使用でき、HTTP ヘッダーにそれぞれ記述します。各ディレクティブはセミコロンで区切ります。1 つのディレクティブで、必須のリソースタイプをすべて記述していることを確認してください。script-src https://host1.com; script-src https://host2.com
のように記述すると、2 番目のディレクティブは無視されます。次のように指定すると、両方のオリジンが有効として正しく指定されます。
script-src https://host1.com https://host2.com
たとえば、コンテンツ配信ネットワーク(https://cdn.example.net
など)からすべてのリソースを読み込むアプリケーションの場合、フレーム付きコンテンツまたはプラグインが不要だとわかっていれば、ポリシーは次のようになります。
Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'
実装の詳細
ウェブの各種チュートリアルで、X-WebKit-CSP
ヘッダーと X-Content-Security-Policy
ヘッダーを目にすることがあるでしょう。今後は、これらの接頭辞付きヘッダーは無視する必要があります。最新のブラウザ(IE を除く)は、接頭辞のない Content-Security-Policy
ヘッダーをサポートしています。こちらのヘッダーを使用してください。
使用するヘッダーによらず、ポリシーはページごとに定義されます。保護する必要があるレスポンスには毎回、この HTTP ヘッダーを付けて送信する必要があります。これにより、各ニーズに応じて特定のページのポリシーを微調整できるため、柔軟性が向上します。サイトに +1 ボタンが存在するページもあれば、ないページもあります。その場合、必要なときにだけボタンのコードの読み込みを許可できます。
各ディレクティブのソースリストは柔軟に使用できます。ソースはスキーム(data:
、https:
)で指定することも、ホスト名のみ(example.com
、そのホスト上の任意のオリジン、スキーム、ポートのいずれかに一致)から完全修飾 URI(https://example.com:443
、HTTPS のみ、example.com
のみ、ポート 443 のみに一致)の範囲で指定することもできます。ワイルドカードも使用できますが、スキーム、ポート、またはホスト名の一番左端のみに限定されます。*://*.example.com:*
は、example.com
のすべてのサブドメインに一致し、スキームとポートはどれでも使用できます(ただし、example.com
自体は一致しません)。
ソースリストには、次の 4 つのキーワードも指定できます。
'none'
: 予想どおり、何も一致しません。'self'
: 現在のオリジンと一致します。ただしサブドメインは除外されます。'unsafe-inline'
: インライン JavaScript と CSS を許可します。(このキーワードについては、後でもう少し詳しく説明する予定です)。'unsafe-eval'
は、eval
などの text-to-JavaScript の仕組みを許可します。(このキーワードについても後述します)。
これらのキーワードには一重引用符が必要です。たとえば、script-src 'self'
(引用符付き)は、現在のホストからの JavaScript の実行を許可します。script-src self
(引用符なし)は、(現在のホストからではなく)「self
」という名前のサーバーからの JavaScript を許可します。これはおそらく意図と異なるでしょう。
サンドボックス化
もう 1 つ説明すべきディレクティブがあります。sandbox
です。これまで説明してきたディレクティブとは若干異なり、ページが読み込めるリソースにではなく、ページで実行できるアクションに制限を加えます。sandbox
ディレクティブが存在する場合、ページは sandbox
属性を指定した <iframe>
内に読み込まれるように処理されます。このディレクティブは、ページを一意のオリジンに限定したり、フォームの送信を禁止したり、ページに幅広い効果をもたらします。この記事の範囲からややはずれますが、有効なサンドボックス属性の完全な詳細については、HTML5 仕様の「Sandboxing」セクションをご覧ください。
メタタグ
CSP が推奨する配信メカニズムは HTTP ヘッダーです。ただし、ページのマークアップに直接ポリシーを設定することもできます。その場合、http-equiv
属性を持つ <meta>
タグを使用します。
<meta
http-equiv="Content-Security-Policy"
content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>
これは frame-ancestors
、report-uri
、sandbox
には使用できません。
インラインコードは有害と見なされる
CSP が許可リストの送信元に基づいていることを明確にする必要があります。これにより、特定のリソースセットを許容可能として扱い、残りは拒否するようにブラウザに指示できる明確な方法になります。ただし、オリジンベースの許可リストは、XSS 攻撃の最大の脅威であるインライン スクリプト インジェクションを解決するものではありません。攻撃者が、悪意のあるペイロード(<script>sendMyDataToEvilDotCom();</script>
)を直接含むスクリプトタグを挿入できる場合、ブラウザには、それを正当なインライン スクリプトタグと区別するメカニズムがありません。CSP でこの問題を解決するには、インライン スクリプトを完全に禁止します。これが唯一確実な方法です。
この禁止には、script
タグに直接組み込まれたスクリプトに限らず、インライン イベント ハンドラと javascript:
URL も含まれます。script
タグのコンテンツを外部ファイルに移動し、javascript:
URL と <a ... onclick="[JAVASCRIPT]">
を適切な addEventListener()
呼び出しに置き換える必要があります。たとえば、次のコードを書き換えるとします。
<script>
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>
次のようになります。
<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>
<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('amazing').addEventListener('click', doAmazingThings);
});
書き換えられたコードには、CSP とうまく連動する以上のメリットがあります。CSP を使用するかにかかわらず、これはベスト プラクティスです。インライン JavaScript は、望ましくない形で構造と動作を組み合わせています。外部リソースはブラウザでキャッシュしやすく、デベロッパーにとってわかりやすく、編集と圧縮のメリットがあります。外部リソースにコードを移動すれば、より適切なコードを書くことができます。
インライン スタイルも同様に処理します。style
属性と style
タグは、外部スタイルシートに統合し、CSS で可能な各種の驚くほど巧妙なデータ抽出方法に対して保護する必要があります。
どうしてもインライン スクリプトやインライン スタイルが必要な場合は、script-src
または style-src
ディレクティブで許可される参照元として 'unsafe-inline'
を追加することで有効にできます。nonce または hash(以下を参照)を使用することもできますが、使用しないでください。
インライン スクリプトを禁止することは、CSP が実現するセキュリティ上の最大のメリットです。インライン スタイルを禁止することで、アプリケーションも強化されます。すべてのコードを外部に移動した後は、正しく動作するかの事前確認が多少は必要になりますが、その手間をかけるだけの価値はあります。
やむを得ずインライン スクリプトを使用しなければならない場合
CSP レベル 2 では、暗号ノンス(1 回使用する数値)またはハッシュのいずれかを使用して、特定のインライン スクリプトを許可リストに追加できるため、インライン スクリプトの下位互換性が提供されます。これは扱いにくいかもしれませんが、いざというときに役立ちます。
ナンスを使用するには、script タグに nonce 属性を指定します。この値は、信頼できる参照元リストに含まれる値と一致する必要があります。例:
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Some inline code I can't remove yet, but need to asap.
</script>
続いて、nonce-
キーワードに付加したナンスを、script-src
ディレクティブに追加します。
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
ノンスはページ リクエストごとに再生成する必要があり、推測できないものにする必要があります。
ハッシュもほぼ同じように機能します。script タグにコードを追加する代わりに、スクリプト自体の SHA ハッシュを作成して script-src
ディレクティブに追加します。たとえば、ページに次のような内容が含まれているとします。
<script>
alert('Hello, world.');
</script>
ポリシーは次のようになります。
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
いくつか注意点があります。sha*-
接頭辞は、ハッシュを生成するアルゴリズムを示します。上記の例では、sha256-
を使用しています。CSP は sha384-
と sha512-
もサポートしています。ハッシュを生成する際は、<script>
タグを含めないでください。先頭や末尾の空白など、大文字や空白文字も重要です。
SHA ハッシュの生成について Google で検索すると、さまざまな言語のソリューションが得られます。Chrome 40 以降では、DevTools を開いてページを再読み込みできます。[Console] タブには、インライン スクリプトごとに、エラー メッセージと正しい sha256 ハッシュが含まれています。
評価にも注意
攻撃者がスクリプトを直接挿入できない場合でも、攻撃者はアプリケーションを騙して、通常は実行されないテキストを実行可能な JavaScript に変換し、攻撃者の代わりに実行させることができます。eval()
、新しい Function()、setTimeout([string], ...)
、setInterval([string], ...)
はすべてベクトルです。挿入されたテキストは、予期しない悪意のあるものの実行を招く可能性があります。CSP のこのリスクに対する基本的な回答は、このような媒介となる関数をすべて完全にブロックすることです。
これは、アプリケーションの構築方法に少なからず影響を及ぼします。
eval
に依存するのではなく、組み込みのJSON.parse
を介して JSON を解析する必要があります。ネイティブの JSON 演算は、IE8 以降のすべてのブラウザで利用でき、高い安全性が確保されています。- 現在実行している
setTimeout
またはsetInterval
呼び出しを、文字列ではなくインライン関数を使用するように書き直してください。例:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
次のように改善します。
setTimeout(function () {
document.querySelector('a').style.display = 'none';
}, 10);
- 実行時のインライン テンプレート生成は避けてください。多くのテンプレート ライブラリは
new Function()
を大量に使用し、実行時のテンプレート生成を高速化しています。これは動的プログラミングの優れた応用方法ですが、悪意のあるテキストが評価されるリスクがあります。一部のフレームワークでは、eval
が存在しない場合は堅牢なパーサーにフォールバックし、CSP をサポートしています。AngularJS の ng-csp ディレクティブがその好例です。
ただし、プリコンパイルを実行できるテンプレート言語(Handlebars など)を使用することをおすすめします。テンプレートをプリコンパイルすると、最速のランタイム実装よりもユーザー エクスペリエンスがさらに高速になり、安全性も高まります。eval および同様の text-to-JavaScript 関数がアプリケーションに欠かせない場合は、許可される参照元として 'unsafe-eval'
を script-src
ディレクティブに追加することで有効化できますが、この方法を使用しないことを強く推奨します。文字列の実行を禁止すれば、攻撃者にとって、不正なコードをサイトで実行することが非常に難しくなります。
レポート
信頼できないリソースをクライアント側でブロックする CSP の機能は、ユーザーに多大なメリットをもたらします。さらに、なんらかの通知をサーバーに返送し、悪意のある注入を許すバグを最初の段階で特定して防ぐために非常に役立ちます。そのためには、report-uri
ディレクティブで指定した場所に JSON 形式の違反レポートを POST
するようブラウザに指示します。
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
レポートは次のようになります。
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
これには、違反が発生したページ(document-uri
)、そのページの参照元(HTTP ヘッダー フィールドとは異なり、キーのスペルは間違っていないことに注意してください)、ページのポリシーに違反したリソース(blocked-uri
)、違反した特定のディレクティブ(violated-directive
)、ページの完全なポリシー(original-policy
)など、違反の具体的な原因を特定するのに役立つ多くの情報が含まれています。
レポート専用
CSP を初めて使用する場合は、厳格なポリシーをユーザーにロールアウトする前に、アプリケーションの現在の状態を評価することをおすすめします。完全なデプロイへのステップとして、ポリシーのモニタリングをブラウザに依頼し、違反を報告するだけで制限を適用しないこともできます。Content-Security-Policy
ヘッダーを送信する代わりに、Content-Security-Policy-Report-Only
ヘッダーを送信します。
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
report-only モードで指定されたポリシーは、制限対象リソースをブロックせず、違反レポートを指定した場所に送信します。両方のヘッダーを送信して、1 つのポリシーを適用し、もう 1 つのポリシーを監視することもできます。これは、アプリケーションの CSP を変更した場合の影響を評価する方法として非常におすすめです。新しいポリシーのレポートを有効にして、違反レポートを監視し、見つかったバグを修正します。その効果に満足できたら、新しいポリシーの適用を開始します。
実際の使い方
CSP 1 は、Chrome、Safari、Firefox では十分に使用できますが、IE 10 ではサポートが非常に限られます。詳細については、caniuse.com をご覧ください。CSP Level 2 は、バージョン 40 以降の Chrome で使用できます。Twitter や Facebook のような大規模なサイトは、このヘッダーをデプロイしています(Twitter のケーススタディは一読の価値があります)。この標準を使用して、すぐにでも自分のサイトでデプロイを開始できます。
アプリケーションのポリシーを作成するための最初のステップは、実際に読み込んでいるリソースを評価することです。リソースを自分のアプリにどうまとめればよいかを把握できたら、その要件に基づきポリシーを設定します。一般的なユースケースをいくつか取り上げ、CSP の保護範囲内でこれらのユースケースをサポートする最適な方法を判断しましょう。
ユースケース 1: ソーシャル メディア ウィジェット
Google の +1 ボタンには、
https://apis.google.com
からのスクリプトとhttps://plusone.google.com
からの<iframe>
が埋め込まれています。ボタンを埋め込むには、この両方のオリジンを含むポリシーが必要です。最小限のポリシーはscript-src https://apis.google.com; child-src https://plusone.google.com
です。また、Google が提供する JavaScript のスニペットを外部 JavaScript ファイルに取り出す必要があります。frame-src
を使用するレベル 1 ベースのポリシーがある場合、レベル 2 ではchild-src
に変更する必要があります。これは CSP レベル 3 では不要になりました。Facebook の高評価ボタンには、実装オプションがいくつかあります。サイトの他の部分から安全に切り離せるため、
<iframe>
バージョンだけを使用することをおすすめします。適切に機能するには、child-src https://facebook.com
ディレクティブが必要です。デフォルトでは、Facebook が提供する<iframe>
コードは相対 URL である//facebook.com
を読み込みます。これをhttps://facebook.com
に変更し、明示的に HTTPS を指定してください。あえて HTTP を使用する理由はありません。Twitter のツイート ボタンは、スクリプトとフレームの両方にアクセスする必要があります。どちらも
https://platform.twitter.com
でホストされています。(Twitter もデフォルトで相対 URL を提供します。ローカルにコピー / 貼り付けるときは、コードを編集して HTTPS を指定してください)。Twitter が提供する JavaScript スニペットを外部の JavaScript ファイルに移動すれば、script-src https://platform.twitter.com; child-src https://platform.twitter.com
で準備は完了です。その他のプラットフォームにも類似の要件があり、同じように対処できます。
default-src
を'none'
に設定し、コンソールを監視して、ウィジェットを機能させるために有効にする必要があるリソースを特定することをおすすめします。
複数のウィジェットを含めるのは簡単です。ポリシー ディレクティブを結合するだけです。必ず、1 つのタイプのすべてのリソースを 1 つのディレクティブにマージします。3 つのソーシャル メディア ウィジェットがすべて必要な場合は、ポリシーは次のようになります。
script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com
ユースケース 2: ロックダウン
あなたは銀行のサイトを運営しており、自分で記述したリソースだけを読み込めるようにする必要があるとします。このシナリオでは、すべてを完全にブロックするデフォルトのポリシーから開始して(default-src 'none'
)、そこから作り上げていきます。
この銀行ではすべての画像、スタイル、スクリプトを https://cdn.mybank.net
にある CDN から読み込むとします。また、XHR 経由で https://api.mybank.com/
に接続し、各種のデータを取得します。フレームは使用されますが、サイトのローカルページのみに使用されます(サードパーティのオリジンは使用しません)。サイトに Flash もフォントも、エクストラも追加されていません。送信できる最も制限の厳しい CSP ヘッダーは次のとおりです。
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'
ユースケース 3: SSL のみ
結婚指輪のディスカッション フォーラムの管理者が、すべてのリソースを安全なチャンネルからのみ読み込めるようにしたいと考えていますが、あまり多くのコードを記述したくありません。インライン スクリプトとインライン スタイルが多数使われているサードパーティ フォーラム ソフトウェアの大量のコードを書き直すことは、管理者の能力を超えています。効果的なポリシーは次のとおりです。
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
default-src
で https:
が指定されていますが、スクリプトとスタイルのディレクティブは、その参照元を自動的に継承することはありません。各ディレクティブは、特定のタイプのリソースでデフォルト値を完全に上書きします。
今後について
Content Security Policy Level 2 は 候補の推奨事項です。W3C の Web Application Security Working Group はすでに、次の規格である Content Security Policy Level 3 のイテレーションに着手しています。
今後の機能に関する議論に興味をお持ちの方は、public-webappsec@ メーリング リストのアーカイブを一読するか、このメーリング リストにご参加ください。