ウィジェットが壊れる問題
Content Security Policy(CSP)の導入はXSS対策として最も効果的な方法のひとつです。しかし、ディレクティブの設定を一箇所間違えるだけでインラインスクリプトが止まり、CDNリソースがブロックされ、アナリティクスが動かなくなる可能性があります。本番環境にいきなり Content-Security-Policy ヘッダーを適用してクリティカルなスクリプトが遮断されると、サイトは静かに壊れます。
Report-Only モード はこの問題を解決します。
Report-Only と Enforced の違い
CSP には2種類のヘッダーがあります:
| ヘッダー | 動作 |
|---|---|
Content-Security-Policy | 違反を即座にブロック |
Content-Security-Policy-Report-Only | 違反をブロックせずレポートのみ送信 |
Report-Only では、許可されていないスクリプトも実行されますが、ブラウザが JSON 形式の違反レポートを指定のエンドポイントに POST します。本番運用前にすべての誤検出を監査できるのです。
Report-Only の設定
Content-Security-Policy-Report-Only: default-src 'self';
script-src 'self' https://analytics.example.com;
report-uri https://your-site.example/csp-reports;
report-to csp-endpoint;
report-uri ディレクティブ(非推奨だが広くサポート)はレポート先URLを指定します。新しい report-to ディレクティブは Report-To ヘッダーで定義したエンドポイントグループ名を参照します。最大のブラウザカバレッジを得るには両方を併用します。
レポートの受信
違反レポートは次のような JSON ペイロードで送られます:
{
"csp-report": {
"document-uri": "https://example.com/page",
"blocked-uri": "https://evil.com/script.js",
"violated-directive": "script-src 'self'",
"effective-directive": "script-src",
"original-policy": "default-src 'self'; script-src 'self'"
}
}
レポートの収集方法:
- 専用サーバールートでファイルやDBにログ出力
- Report URI(report-uri.com)などのサードパーティサービス
- AWS S3 + Lambda や Cloudflare Workers によるクラウドログ分析
段階的 CSP ロールアウト戦略
安全な導入は4つのフェーズで構成します。
フェーズ1 — 監視(Report-Only)
バックエンドのトグルやリバースプロキシのルールで、一部のトラフィックにのみ Content-Security-Policy-Report-Only を適用します。1〜2週間 稼働させ、すべての正当なリソースパターンを収集します。
# nginx: ステージング環境でレポートのみ
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-reports;" always;
フェーズ2 — レポートトリアージ
収集したレポートを分析します。よくある誤検出のパターン:
- インラインイベントハンドラ(
onclick、onload)は'unsafe-hashes'または'nonce-...'が必要 script-srcに未登録のサードパーティCDNスクリプトconnect-srcでカバーされていない WebSocket 接続
フェーズ3 — ロックダウン(Enforced)
レポートの発生が落ち着いたら(数日間予期しない違反がゼロになったら)、Enforced ヘッダーに切り替えます。さらに厳しいポリシーを探索するため、Report-Only も併用し続けます。
フェーズ4 — 反復強化
Content-Security-Policy: default-src 'self';
script-src 'self' 'nonce-abc123';
report-uri https://your-site.example/csp-reports;
Content-Security-Policy-Report-Only: default-src 'self';
script-src 'none';
report-uri https://your-site.example/csp-reports;
Enforced ポリシーと並行して、さらに制限の厳しい将来バージョンを Report-Only でテストできます。
Report-Only の課題
- レポートはページロードごとに1回のみ送信されます。 最初の違反以降、同じページ上で同じ違反が繰り返されても、ほとんどのブラウザは無視します。
- ボディなしでレポートを送信するブラウザがあります。 空レポートは早期にフィルタリングしましょう。
form-actionの違反は Report-Only ではキャッチできません。 フォーム送信先の制限は Enforced モードでなければブロックされません。
まとめ
Content-Security-Policy-Report-Only は、リスクゼロで CSP をロールアウトするための必須ツールです。本番トラフィックで違反を観察し、実際のデータに基づいてポリシーを調整し、確信が持てた段階で Enforced モードに移行できます。レポート収集サービスと組み合わせて、最低1週間は運用してから本適用を行いましょう。
