
## この記事でわかること

- CSP（Content-Security-Policy）が「ブラウザに対する許可リスト」であること
- CSP で防げる攻撃（XSS / 改ざん / 情報漏洩）と防げないもの
- Web サイト運営者が最低限導入すべき CSP の例
- 事故を出さずに導入する 3 段階のロールアウト

## CSP は「ブラウザに対する許可リスト」

CSP（Content-Security-Policy）は、Web サイトのレスポンスヘッダで「**このページが読み込んでよいリソースの出所**」を宣言する仕組みです。スクリプト・スタイル・画像・iframe などのリソースが、許可されていない出所から来た場合にブラウザが**読み込みをブロック**します。

簡単な例:

```
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com
```

これは「自社ドメインからのリソースは全て OK、加えて Google Tag Manager の JS だけ許可」という宣言です。攻撃者が XSS で別ドメインの悪意あるスクリプトを注入しても、ブラウザがそれを実行する前に拒否します。

![CSP の役割と効果範囲](/blog/csp-content-security-policy-toha/csp-overview.svg)

## CSP で防げる攻撃 / 防げない攻撃

### 防げる
- **XSS（クロスサイトスクリプティング）**: 注入されたインラインスクリプトや外部スクリプトの実行を阻止
- **データ漏洩を狙う通信**: connect-src で API 通信先を限定すれば、攻撃者が情報を別のサーバーに送ろうとしても止まる
- **意図しないサードパーティタグ**: 広告 SDK / 解析ツール等の出所制限
- **iframe による埋め込み攻撃**: frame-ancestors / frame-src で制限可能

### 防げない
- **サーバー側の脆弱性**: SQL インジェクション・認可バイパスなどはサーバーで対処
- **人的ミス**: フィッシングメールに誘導された結果のアカウント情報入力
- **DDoS / Brute Force**: WAF / レート制限の領域

CSP は「クライアント側に到達したリソースを制御する」防御層です。サーバー側の対策と組み合わせて初めて意味が出ます。

## 最低限の CSP 例（小〜中規模サイト向け）

`default-src 'self'` を起点に、必要な外部ドメインだけ追加するのが安全です。

```
Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com 'nonce-{{generated}}';
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://www.google-analytics.com;
  frame-ancestors 'self';
  base-uri 'self';
  form-action 'self';
```

ポイント:
- `'unsafe-inline'` を script-src に入れない（XSS 防御効果が大きく下がる）。代わりに **nonce** または **hash** で個別許可
- style-src の `'unsafe-inline'` は WordPress 等のテーマで必要になりがち。許容するか、徐々に外すかは判断
- `frame-ancestors 'self'` は X-Frame-Options の上位互換（[クリックジャッキング対策](/blog/x-frame-options-clickjacking)）
- `base-uri` / `form-action` を入れておくと攻撃面が更に狭まる

## いきなり Enforce にしない（3 段階のロールアウト）

CSP の最大の落とし穴は「いきなり Enforce すると本番画面が崩壊する」ことです。サードパーティタグ・CDN・解析ツールが見えない場所で動いているため、ポリシー違反 = ブロック = 画面崩れになります。

![CSP 導入の 3 段階](/blog/csp-content-security-policy-toha/csp-rollout-stages.svg)

### ステップ 1: Report-Only モードで観察

```
Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self';
  report-uri /csp-report
```

このヘッダはブラウザに「ポリシー違反を検出したら report-uri に通知して。でもブロックはしない」と指示します。実際の画面表示には影響しません。

`report-uri` の受け口は自前実装でも、Sentry / Datadog 等の監視サービスでも構いません。違反内容を 2〜4 週間蓄積します。

### ステップ 2: ポリシー調整

レポートを精査して、

- 「自社で使っている SDK だ」→ そのドメインを script-src に追加
- 「見覚えのない出所」→ 攻撃の可能性 / 不要なタグの可能性を調査

を仕分けします。**違反が 1 日数件以下に落ち着くまで**観察を続けます。

### ステップ 3: Enforce 切り替え

ヘッダ名を `Content-Security-Policy-Report-Only` から `Content-Security-Policy` に変更すれば本番適用です。違反したリソースは実際にブロックされ、XSS 防御が効きます。

## CSP の `unsafe-inline` を巡る現実

WordPress や古いテーマでは、JavaScript / CSS がインラインで埋め込まれているケースが多く、`'unsafe-inline'` を入れないと画面が崩れます。一方 `'unsafe-inline'` を入れると CSP の XSS 防御効果は大きく下がります。

このトレードオフと現実的な移行手順は [CSP unsafe-inline の問題と移行手順](/blog/csp-unsafe-inline-mondai) で詳しく解説しています。

## まずは現状を把握しましょう

自社サイトの CSP 設定状況は、ドメイン番人の [Web セキュリティヘッダ 単発チェック](/security-headers/check) で 30 秒で確認できます。CSP の有無、unsafe-inline の検出、Report-Only モードの判定までまとめてレポートします。

CSP の段階的な導入支援、CSP 違反レポートの精査、Enforce 切り替えのスポット対応は [Web セキュリティヘッダ診断＋設定支援](/contact)（3 万円〜）でご相談いただけます。判断に迷う場合は [お問い合わせ](/contact) からお気軽にどうぞ。

他社チェッカー（securityheaders.com / Mozilla Observatory）との違いは [Web セキュリティヘッダのチェッカー比較](/blog/security-headers-checker-comparison) を、ブラウザ API（カメラ / マイク / 位置情報など）を制限する隣接ヘッダーは [permissions-policy 設定の入門](/blog/permissions-policy-toha) を参照してください。

メール認証や SSL も含めた総合点検は [無料のドメイン診断](/diagnose) を、SSL 単独の確認は [SSL 単発チェック](/ssl/check) をご利用ください。
