CSP Report-Onlyの運用方法|違反レポートを確認して本番制限へ移す手順
Content-Security-Policy(CSP)は、ブラウザが読み込めるスクリプト、画像、CSS、通信先などを制限し、クロスサイトスクリプティングをはじめとする不正なコード実行の影響を抑える仕組みです。ただし、既存サイトへ厳しいポリシーを一度に強制すると、問い合わせフォーム、アクセス解析、タグマネージャー、チャット、動画、決済など、正規の機能まで止めるおそれがあります。
この事故を避けるために使うのが、HTTPレスポンスヘッダーのContent-Security-Policy-Report-Onlyです。候補ポリシーに反する挙動を止めずに観測し、違反レポートを調べてコードと設定を直した後、Content-Security-Policyへ段階的に移します。単にドメインを許可リストへ追加するのではなく、各通信の目的、所有者、必要性、修正方法まで確認することが重要です。
結論として、CSP Report-Onlyは「このポリシーを強制したら何が止まるか」を本番相当の通信で確認する観測モードです。まず重要導線と外部リソースを棚卸しし、Report-Onlyヘッダーと受信先を設定します。集まった違反を必要な機能、修正すべきコード、不要な通信、ブラウザ拡張などのノイズに分類し、重要導線の未分類違反がなくなった範囲から強制します。CSP移行は「レポートがゼロになった時」ではなく、「重要導線の違反を分類し、必要なコードだけを直して、制限を戻せる状態で強制した時」に完了します。
本記事のポイント
- CSP Report-Onlyは候補ポリシーに違反する通信を報告するが、読み込みや実行は止めないため、本番影響を観測してから強制へ移せる。
- 違反レポートは許可リストの材料ではなく、必要なコード、不要な外部通信、ブラウザ拡張のノイズ、攻撃兆候を分ける調査票として扱う。
- 強制への移行条件はレポート件数ゼロではなく、重要導線の未分類違反がなく、段階適用・監視・ロールバックを実行できることで決める。
CSP Report-Onlyは通信を止めずに候補ポリシーを評価する
通常のContent-Security-Policyは、ポリシーに合わない読み込みや実行をブラウザが拒否します。一方、Content-Security-Policy-Report-Onlyは違反を監視してコンソールや指定先へ報告しますが、その挙動自体は止めません。W3CのCSP Level 3仕様も、候補ポリシーを反復的に組み立て、違反を観測して自信を得てから強制へ移る用途を定義しています。
| 項目 | Report-Only | 強制ポリシー |
|---|---|---|
| レスポンスヘッダー | Content-Security-Policy-Report-Only | Content-Security-Policy |
| 違反した通信 | 原則として継続し、違反を記録する | ブラウザが読み込み・実行を拒否する |
| 主な用途 | 新規導入、ポリシー変更、外部サービス追加前の影響確認 | XSSなどの被害を抑える本番防御 |
| 同時利用 | 将来の厳しい候補ポリシーを観測できる | 現在の安定したポリシーを強制できる |
| 注意点 | 監視しているだけなので、それ自体は防御にならない | 未確認の導線や外部通信を止める可能性がある |
Report-OnlyはHTMLの<meta>要素では設定できず、HTTPレスポンスヘッダーとして配信する必要があります。すでに緩いCSPを強制しているサイトでも、別のReport-Onlyヘッダーを同じレスポンスへ付ければ、現在の防御を維持しながら次のポリシーを試せます。
ただし、Report-Onlyを長期間置くだけでは安全性は上がりません。観測開始時に、対象ページ、重要導線、担当者、違反の分類期限、強制へ移す判断者、戻し方を決めます。ヘッダー変更の責任や公開承認を曖昧にしない考え方は、Webサイトのコンテンツガバナンスと共通します。
レポート受信先と候補ポリシーを先に設計する
最初に決めるのは「何を許可するか」だけではありません。どの環境とページへヘッダーを付けるか、レポートをどこで受けるか、誰が分類するか、受信データをどの期間保管するかを一組で設計します。Report-Onlyを全ページへ付けても、受信先が機能していなければ、ブラウザのコンソール以外に判断材料が残りません。
Reporting APIを使う場合は、Reporting-Endpointsで受信先に名前を付け、CSPのreport-toでその名前を指定します。MDNは、report-toのブラウザ対応を補うため、非推奨になったreport-uriも併記する方法を案内しています。次は構造を示す例であり、許可元や受信先は自社環境に合わせて変更してください。
Reporting-Endpoints: csp-endpoint="https://reports.example.com/csp"
Content-Security-Policy-Report-Only:
default-src 'self';
script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic';
style-src 'self';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
object-src 'none';
base-uri 'none';
form-action 'self';
frame-ancestors 'self';
report-uri https://reports.example.com/csp-legacy;
report-to csp-endpoint
動的HTMLでnonceを使う場合、{RANDOM}はレスポンスごとに暗号学的に十分な乱数から生成し、許可する<script>だけへ同じ値を付けます。静的HTMLやキャッシュ中心のサイトでは、インラインスクリプトのハッシュを使う方が適する場合があります。'unsafe-inline'や'unsafe-eval'を安易に加えると、CSPの防御効果を大きく下げます。
受信する形式はReporting APIと旧report-uriで異なりますが、調査の中心になる項目は共通しています。
| 確認する項目 | 分かること | 調査での使い方 |
|---|---|---|
documentURL / document-uri | 違反が起きたページ | 問い合わせ、ログイン、資料取得など重要導線へひも付ける |
blockedURL / blocked-uri | 候補ポリシーに合わなかったリソースや通信先 | 提供元、実装箇所、データ送信目的を確認する |
effectiveDirective | 実際に違反したscript-src-elemなどの指示 | スクリプト、接続、画像、フレームなど修正担当を分ける |
originalPolicy | 違反判定に使われたポリシー | ポリシーの版とデプロイ時刻を照合する |
sourceFile、行・列 | 違反を発生させたコード位置の候補 | ソースマップやデプロイ版と合わせて原因を探す |
disposition | reportかenforceか | 観測中の候補ポリシーと本番ブロックを区別する |
sample | 'report-sample'指定時のインラインコード断片 | 機密情報を含む可能性を考慮し、必要時だけ収集する |
CSPレポートは攻撃者が送れるデータとして扱います。受信APIではリクエストサイズ、Content-Type、件数、保管期間を制限し、値をHTMLとして表示せず、URLのクエリやコード断片から個人情報・トークン・入力値を除去します。受信先の可用性低下が本体サイトへ波及しない構成にし、レポート本文だけを根拠に自動で許可元を増やしてはいけません。
正当な通信・修正対象・ノイズ・攻撃兆候を分ける
Report-Onlyを有効にすると、最初は大量の違反が届くことがあります。件数の多いドメインから順に許可すると、使われていない広告タグや不明な外部通信まで恒久的な例外になります。まずページ、実装版、指示、通信先を正規化して同じ事象をまとめ、次の区分で所有者と処理を決めます。
| 分類 | 判断材料 | 処理 |
|---|---|---|
| 必要な自社コード | 現行仕様に必要で、実装箇所と担当者が明確 | nonce・hash・外部ファイル化などで、広い例外を使わず適合させる |
| 必要な外部サービス | 契約、目的、送信データ、対象ページ、停止手順が確認できる | 必要な指示へ最小限の配信元を追加し、変更責任者を記録する |
| 不要・期限切れ | 所有者不明、契約終了、重複タグ、利用実績なし | 許可せず、タグ・埋め込み・ライブラリを削除して再テストする |
| ブラウザ拡張などのノイズ | 自社コードや通常端末で再現せず、利用者環境に依存する | 既知ノイズとして隔離し、ポリシーを緩める根拠にしない |
| 攻撃・改ざんの兆候 | 未知の送信先、急増、特定ページへの集中、異常なインライン実行 | 配信変更を止め、アクセスログ・変更履歴・端末・依存関係を調査する |
blockedURLのドメインだけでは正当性を判断できません。同じCDNに正規ライブラリと不要なスクリプトが混在することがあり、タグマネージャー経由では管理画面の公開操作で通信先が変わります。実装リポジトリ、タグ管理画面、契約台帳、ネットワークログを照合し、「誰が、何の目的で、どのデータを、いつまで送るか」を確認します。
問い合わせフォームでは、script-srcだけでなく、送信先を制御するconnect-srcやform-action、CAPTCHAや埋め込みのframe-srcが関係します。見た目が表示できても、送信通知や外部API連携だけが止まることがあります。公開前後の確認は、問い合わせフォームの通知漏れを防ぐ監視設計のように、テスト送信から受信・担当通知・代替導線まで通して行います。
ブラウザ拡張やマルウェア由来のノイズが混ざるため、レポート件数ゼロを目標にしてはいけません。重要なのは、重大度の高い未分類違反が残っていないこと、必要な通信に所有者がいること、例外がコード修正より先に増えていないことです。新しい外部サービスを追加するときは、Report-Onlyへ先に反映し、観測と承認を経てから強制ポリシーへ入れます。
6段階でReport-Onlyから本番の強制へ移す
CSP導入は、ヘッダーを一度書いて終わる作業ではありません。重要導線の把握、観測、分類、修正、段階適用、継続監視を一つの変更フローとして回します。以下の6段階を、ステージングと本番の両方で再現できるようにします。
- 重要導線と外部リソースを棚卸しする
トップ、記事、問い合わせ、ログイン、資料取得、決済などをページ群に分け、スクリプト、CSS、画像、フォント、API、フレーム、フォーム送信先を記録します。所有者不明のタグを先に調査し、最低限のE2Eテストを用意します。 - 候補ポリシーと受信先をステージングで確認する
nonceまたはhashを軸に候補ポリシーを作り、Reporting APIと互換用受信先へテストレポートが届くことを確認します。受信APIの制限、マスキング、アラート、保存期間も試します。 - 本番へReport-Onlyを限定配信する
最初は社内利用、特定ページ群、低い割合などへ絞り、ヘッダーの版と配信時刻を記録します。代表的なブラウザ、端末、地域、ログイン状態、同意状態を含む実利用を観測します。 - 違反を分類してコードと設定を直す
必要な自社コードはnonce・hash・外部ファイル化で直し、必要な外部通信だけを最小の指示へ追加します。不要タグは削除し、拡張機能ノイズは隔離します。修正後は同じ導線を再実行します。 - 重要導線から強制範囲を広げる
ステージングで強制し、次に限定した本番トラフィックでContent-Security-Policyを有効にします。現在の強制ポリシーと、次の候補Report-Onlyを並行させると、保護を維持しながら改善できます。 - 監視・変更承認・ロールバックを定常化する
強制後のブロック、フォーム成功率、JavaScriptエラー、主要CVを監視します。外部サービス追加やコード変更はReport-Onlyで事前確認し、障害時は直前のポリシー版へ戻せるようにします。
観測期間を一律に「7日間」などと決めるより、代表的な利用パターンを通過したかで判断します。月末だけ動くタグ、ログイン後だけ表示される画面、同意後に発火する計測、キャンペーンLP、管理画面など、低頻度でも重要な経路を含めます。公開時の表示・フォーム・計測を一つの点検表にする方法は、BtoB LP実装チェックリストも参考になります。
CDN、リバースプロキシ、アプリ、ホスティング設定の複数箇所でCSPを付けると、想定外に複数ポリシーが同時適用されます。ヘッダーの正本を一つにし、ビルド後のHTMLだけでなく、本番レスポンスをcurl -IやブラウザのNetworkパネルで確認します。サイト運用をリポジトリとデプロイへ寄せる考え方は、Webサイト制作を内製化する手順で整理しています。
強制への移行条件とロールバックを数値・状態で決める
移行判断は「担当者が大丈夫そうと言った」ではなく、ページ群ごとの受入条件でそろえます。強制するポリシーの版、対象範囲、承認者、監視指標、停止条件、戻す版をリリース記録へ残します。
| 判定軸 | 強制へ進める状態 | 止めて調査する状態 |
|---|---|---|
| 重要導線 | ログイン、フォーム、資料取得、決済などが対象環境で完了する | 送信・認証・通知・埋め込みの一部でも失敗する |
| 違反の分類 | 高・中重大度の未分類違反がなく、例外に所有者と期限がある | 未知の送信先、所有者不明のタグ、急増するインライン違反がある |
| ブラウザと端末 | 主要な利用構成で同じ受入テストを通過する | 特定ブラウザ、同意状態、ログイン状態でだけ失敗する |
| 適用方法 | 限定配信から段階的に対象を広げられる | 全ページ一括しか選べず、影響を切り分けられない |
| 監視 | CSPブロック、JavaScriptエラー、フォーム成功率、主要CVを比較できる | ヘッダー配信後の影響を検知できない |
| ロールバック | 直前版へ戻す手順と担当があり、短時間で実行確認済み | 設定箇所や戻す値が不明で、承認待ちになる |
ロールバックはCSPを永久に無効化することではありません。障害が出たページ群を直前の強制ポリシーへ戻し、問題の候補はReport-Onlyへ戻して再調査します。*、広すぎるスキーム許可、'unsafe-inline'、'unsafe-eval'を緊急対応として追加し、そのまま残す運用は避けます。やむを得ない暫定例外には、対象、理由、担当、削除期限、置換作業を必ず持たせます。
CSPはXSS対策の補助層であり、入力処理、出力エスケープ、依存関係更新、認証・権限、セキュアな開発を置き換えません。OWASPも、CSPだけへ依存せず、基本的なXSS防止策の上に追加する防御として位置付けています。ポリシーが厳しく見えることより、実装と変更運用が継続して守られることを優先してください。
よくある質問
CSP Report-Onlyとは何ですか?
候補のContent Security Policyに違反する読み込みや実行を監視し、コンソールや指定した受信先へ報告するHTTPレスポンスヘッダーです。違反した挙動は原則として止めないため、本番影響を観測して修正してから強制ポリシーへ移せます。監視だけなので、Report-Only自体を本番防御として扱ってはいけません。
CSP違反レポートには何が記録されますか?
違反が起きたページ、候補ポリシーに合わなかったリソース、実効指示、元のポリシー、送信元ファイル、行・列、HTTP状態、reportかenforceかなどが記録されます。形式はReporting APIと旧report-uriで異なります。URLやコード断片に機密情報が含まれる可能性があるため、保存前に正規化・マスキングします。
正当な外部リソースと不要な通信をどう見分けますか?
ドメイン名だけで判断せず、実装箇所、契約、業務目的、送信データ、対象ページ、所有者、停止手順を照合します。必要な機能は最小の指示へ許可し、所有者不明・契約終了・重複したタグは削除します。ブラウザ拡張など自社コードで再現しないノイズを理由にポリシーを緩めないことも重要です。
Report-Onlyから強制ポリシーへいつ移行しますか?
重要導線の受入テストが完了し、高・中重大度の未分類違反がなく、必要な例外に所有者と期限があり、限定配信・監視・ロールバックを実行できるときです。レポート件数ゼロは条件にしません。ブラウザ拡張や低頻度の外部挙動がノイズとして残ることがあるためです。
report-toとreport-uriはどちらを使いますか?
現在の推奨はReporting APIのReporting-EndpointsとCSPのreport-toです。ただしreport-toはすべてのブラウザで同じように使えるわけではないため、MDNは非推奨のreport-uriも互換用に併記する方法を案内しています。受信側は両形式を区別して処理します。
CSP違反レポートがゼロにならないのは問題ですか?
ゼロでなくても直ちに失敗ではありません。ブラウザ拡張、マルウェア、低頻度の利用条件、古いタブなどがノイズを発生させます。ページ群・指示・通信先で集約し、重大度、再現性、所有者、実害で優先順位を付けます。未知の送信先や急増はノイズと決めつけず、変更履歴やアクセスログまで調査します。
仕様と実装条件を確認できる公式情報
Reporting APIやブラウザ対応は変わるため、2026年7月27日時点の公開情報に基づき、実際に利用するブラウザ、CDN、アプリ基盤、受信サービスで最終確認してください。
- W3C:Content Security Policy Level 3では、Report-Onlyヘッダーの監視動作、HTTPヘッダーによる配信、違反レポート、
report-toの仕様を確認できます。 - MDN:Content-Security-Policy-Report-Only headerでは、
Reporting-Endpoints、report-to、互換用report-uriの設定例を確認できます。 - MDN:Content Security Policy guideでは、強制ポリシーとの同時利用、Reporting APIのJSON形式、テスト方法を確認できます。
- MDN:CSP report-uri directiveでは、旧形式の違反項目、
report-sample、受信データを攻撃者制御として扱う注意点を確認できます。 - web.dev:Mitigate cross-site scripting with a strict CSPでは、nonce・hashを使う厳格なCSP、ステージングからReport-Only、本番強制へ移す手順を確認できます。
- OWASP:Content Security Policy Cheat Sheetでは、Report-Onlyと強制の併用、Strict CSP、CSPを他のXSS対策と組み合わせる原則を確認できます。