CSPヘッダーチェッカー

Content-Security-Policyヘッダーの値を貼り付けるだけでディレクティブ・ソース値を一括検証。unsafe-inline等の危険な設定やdefault-src未指定、ディレクティブ名のスペルミスを検出し、ディレクティブごとの許可ソースを視覚的に一覧表示します。

CSPヘッダーの中身を点検する

Content-Security-Policy はセミコロンで区切られた1本の長い文字列で、目で追うだけでは危ういところを見落としがちです。このツールは値を貼り付けるだけでディレクティブとソースを分解し、危険な設定・抜けている指定・綴りの誤りを洗い出して、どのディレクティブが何を許可しているのかを一覧にします。

**とくに厄介なのがディレクティブ名の綴り間違いです。** ブラウザは知らないディレクティブを黙って無視するため、`script-src` を `scipt-src` と書いても**エラーは一切出ず、そのポリシーが丸ごと効かないまま動き続けます。** 同様に見落とされやすいのが `default-src` の未指定で、これが無いと明示していないディレクティブには制限がかからず、防御に穴が空きます。そして `unsafe-inline` を script-src に入れると、**CSP を導入する最大の目的であるインラインスクリプトの遮断がほぼ無効になります。**

使い方

  1. CSPヘッダーの値を貼り付ける `default-src 'self'; script-src ...` の形の文字列をそのまま入れます。
  2. サンプルで挙動を確かめる 良い例と悪い例が用意してあるので、判定の違いを先に見ておけます。
  3. 指摘された項目を読む **`unsafe-inline` や `default-src` の欠落、綴りの誤りが指摘されます。**
  4. ディレクティブごとの許可ソースを確認する どこからの読み込みを許しているかが一覧で見えます。

使いこなすためのヒント

  • CSPは通常HTTPレスポンスヘッダーとして配信しますが、<meta http-equiv="Content-Security-Policy">タグでも指定できます(ただしreport-uri等一部のディレクティブはmetaタグでは無効です)。
  • 本番環境にいきなり適用する前に、Content-Security-Policy-Report-Onlyヘッダーで違反レポートだけを収集し、既存機能への影響範囲を確認してから本適用する運用がおすすめです。
  • ワイルドカード(*)や'unsafe-inline'は動作確認を通しやすい反面、CSP本来のXSS対策効果を大きく損ないます。開発中に使った緩い設定は公開前に必ず絞り込みましょう。
  • 同じディレクティブを複数回書いても最初の1つしか有効になりません。設定を追加・上書きしたい場合はソースを1本のディレクティブにまとめる必要があります。
  • ブラウザのDevToolsコンソールには、CSP違反でブロックされたリソースが「Refused to load...」という赤字メッセージでそのまま表示されるため、デバッグ時にまず確認すべき場所です。

活用シーン

CSPを新しく導入する

いきなり本番へ入れる前に、書いたポリシーが意図どおりかを確かめられます。

既存の設定を棚卸しする

**継ぎ足しで伸びたポリシーには、もう使っていないドメインの許可が残りがちです。**

レポート専用から強制へ切り替える

`Content-Security-Policy-Report-Only` で試した値を、強制へ移す前に点検できます。

コードレビューの補助にする

変更されたポリシーを貼って、弱くなっていないかを確かめられます。

CSPの用語

ディレクティブ
`script-src` や `img-src` のように、**資源の種類ごとに読み込み元を指定する項目**です。
default-src
個別のディレクティブが指定されていない場合の既定値です。**これを書かないと、明示していない種類は無制限になります。**
'self'
同一オリジンからの読み込みだけを許す指定です。
'unsafe-inline'
HTMLに直接書いたスクリプトやスタイルを許す指定です。**XSS への防御がほぼ失われるため、nonce や hash への置き換えが勧められます。**
nonce
1回きりの乱数をスクリプトタグとポリシーの双方に書いて対応づける方式です。インラインを安全に許可する手段になります。
frame-ancestors
自サイトを frame に埋め込める相手を指定します。**X-Frame-Options の後継にあたる指定です。**

よくある質問

CSPはブラウザに対して「このページで読み込んでよいスクリプト・画像・スタイル等の送信元」を宣言する仕組みです。許可リストにないソースからのリソース読み込みやインラインスクリプトの実行がブロックされるため、XSS攻撃で外部の悪意あるスクリプトが実行されるリスクを大幅に下げられます。

nonceソース('nonce-ランダム値')やhashソース('sha256-ハッシュ値')を使う方法があります。スクリプトタグにnonce属性を付与し、レスポンスヘッダーの値と一致させることで、そのタグだけを個別に許可しつつ他の不正なインラインスクリプトはブロックできます。

CSPが許可リストにないオリジンからのリソース読み込みをブロックしたためです。ブラウザのコンソールに表示される「Refused to load...because it violates the following Content Security Policy directive」というメッセージに該当ドメインが記載されているので、そのオリジンを該当ディレクティブの許可リストに追加してください。

多くの場合は不十分です。default-srcは個別のディレクティブ(script-src等)が指定されていない場合のフォールバックとして機能しますが、script-srcやobject-src等は攻撃面が大きいため、それぞれ明示的に厳しく設定することが推奨されます。

どちらもCSP違反時にブラウザが送信するレポート先を指定するディレクティブですが、report-uriは旧仕様でレポート送信先URLを直接指定します。report-toは新しいReporting API仕様に基づき、事前にReport-Toヘッダーで定義したグループ名を参照する形式です。両対応のブラウザに配慮し、両方を併記することが推奨されています。
ツールくん

余談ですが ― CSPはなぜ生まれたのか ― 「エスケープの徹底」だけでは守れなかったXSS対策の歴史

CSP(Content Security Policy)は、2004年頃にRobert Hansenが提唱したアイデアを起点に、2008年前後からMozillaのエンジニアであるBrandon Sterneが中心となって仕様化を進め、2012年にW3Cの最初の勧告候補(Level 1)としてまとめられました。当時Webアプリケーションの脆弱性の中でもXSS(クロスサイトスクリプティング)が特に深刻視されており、「出力のエスケープを徹底する」という開発者の注意力だけに頼った対策には限界があるという反省から、ブラウザ側で強制的にスクリプトの実行元を制限する多層防御の仕組みとして設計されました。

CSP Level 2ではnonceやhashによるインラインスクリプトの許可が導入され、'unsafe-inline'を使わずに特定のインラインコードだけを個別に許可できるようになりました。さらにLevel 3で追加された'strict-dynamic'は、信頼済みスクリプトが動的に読み込む子スクリプトを自動的に信頼する仕組みで、大規模サイトでのホワイトリスト保守コストを大きく下げています。

Googleは自社の大規模サービス群にnonceベースの厳格なCSPを導入する取り組みを継続的に行っており、その知見から「ホスト名の許可リスト方式のCSPは迂回されやすく、nonce・hashベースの方が実効性が高い」という研究結果を公表しています。この知見は現在のCSP設計のベストプラクティスとして広く参照されており、単に「危険な値を禁止する」だけでなく「そもそもどの方式で許可を組み立てるか」という設計判断が重要であることを示しています。