結論(CSPがレスポンスヘッダーで強制されている)
CSPがレスポンスヘッダーで強制されているとは、Content Security Policyが Content-Security-Policy レスポンスヘッダーで配信され、違反する読み込みや実行をブラウザが実際にブロックする状態です。Content-Security-Policy-Report-Only は違反を報告するだけで攻撃を止めず、HTMLのmeta要素ではframe-ancestorsやreport-uri、sandboxが使えません。CSPの効果を確実に得るには、強制モードのレスポンスヘッダーで配信する必要があります。
この記事のポイント
- CSPの届け方は、強制ヘッダー・Report-Onlyヘッダー・meta要素の3通りで、すべての機能が使えて攻撃を止められるのは強制ヘッダーだけです。
- meta CSPでは frame-ancestors・report-uri・sandbox が使えず、meta要素より前の要素にも適用されません(W3C CSP Level 3)。
- Report-Onlyは違反を報告するだけで、放置すると防御効果はゼロです。
- セキュリティAIチェッカーは、強制ヘッダーありで○、Report-Onlyまたはmetaのみで△、CSPなしで×(重み4)と判定します。
- Report-Onlyで1〜4週間影響を確認してから強制ヘッダーへ切り替えるのが安全な導入手順です。
| 診断項目名 | CSPがレスポンスヘッダーで強制されている |
|---|---|
| 項目ID | headers.csp-enforcement |
| 分類 | コンテンツセキュリティポリシー(CSP) |
| 重大度・配点の重み | 重要(high) 重み 4 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V3.4.3(Level 2「HTTP 応答に Content-Security-Policy レスポンスヘッダーを含め、信頼できるコンテンツだけを読み込み・実行させること」)、OWASP ASVS 5.0.0 V3.4.6(Level 2、frame-ancestors)、V3.4.7(Level 3、違反報告先)、OWASP WSTG-CONF-12(Test for Content Security Policy)、W3C Content Security Policy Level 3(第3.1〜3.3節:ヘッダー、Report-Only、meta 要素)、IPA「安全なウェブサイトの作り方」1.5 クロスサイト・スクリプティング(保険的対策 5-(x))、CWE-79(XSS)、CWE-1021(クリックジャッキング) |
CSPがレスポンスヘッダーで強制されているとは
CSPがレスポンスヘッダーで強制されているとは、Content Security Policy(CSP)が Content-Security-Policy レスポンスヘッダーで配信され、ポリシーに違反する読み込みや実行をブラウザが実際にブロックしている状態のことです。
CSPは、ページが読み込めるスクリプト・スタイル・画像などの配信元や、フレーム埋め込み・フォーム送信先をブラウザに制限させる仕組みです。CSPには3つの届け方があります。
| 届け方 | 動作 | 制約 |
|---|---|---|
Content-Security-Policy レスポンスヘッダー | 強制(違反をブロック) | なし |
Content-Security-Policy-Report-Only レスポンスヘッダー | 違反を報告するだけで、ブロックしない | 防御効果なし |
HTML の <meta http-equiv="Content-Security-Policy"> | 強制 | 一部のディレクティブが使えない |
この項目は、ポリシーの中身ではなく「強制力のある形で届いているか」を判定します。中身の妥当性は、「Content Security Policy」、「CSPの基幹ディレクティブ」、「CSPでunsafe-inlineを許可していない」、「CSPでunsafe-evalを許可していない」などの別項目で判定します。
CSPはなぜmetaやReport-Onlyではなくヘッダーで強制すべきなのか
ヘッダーとmeta要素の違い
W3C CSP Level 3 は、meta要素では frame-ancestors、report-uri、sandbox ディレクティブが使えず、Report-Only もmetaでは使えないと定めています。さらにmetaのポリシーは、そのmeta要素より前にある要素や、Link ヘッダーで先読みされた資源には適用されません。つまり、metaだけのCSPには次の制約があります。
- クリックジャッキング対策(frame-ancestors)が効かない
- 違反報告(report-uri)を受け取れない
<head>の先頭に置かないと、前に書かれたスクリプトは制限されない
OWASP WSTG-CONF-12 も、ヘッダーでの配信を推奨しています。
Report-Onlyの位置づけ
Content-Security-Policy-Report-Only は違反を報告するだけで、スクリプトの実行や外部読み込みは止めません。導入時に「何が壊れるか」を調べる段階としては最適ですが、そのまま放置すると防御効果はゼロです。WSTG-CONF-12 も「Report-Onlyしかない場合、ポリシーは強制されていない」と明記しています。
複数ポリシーの扱い
CSPヘッダーは複数回送ることができ(またはカンマ区切りで複数ポリシーを並べられ)、ブラウザはすべてのポリシーを同時に適用します。ポリシーを追加すると、制限は厳しくなる方向にしか働きません。ヘッダーとmetaの両方がある場合も、両方が適用されます。
CSPの強制についてよくある誤解
- 「metaでCSPを書いたからクリックジャッキングも防げる」:誤りです。frame-ancestors はmetaでは無視されます(クリックジャッキング対策の全体は「クリックジャッキング対策」で確認します)。
- 「Report-Onlyを入れたからCSP対応済み」:これも誤りです。報告されるだけで、攻撃は止まりません。
- 「CSPがあればXSSは起きない」:誤りです。CSPは出力エスケープなどの根本対策を補う多層防御で、IPAの「安全なウェブサイトの作り方」(1.5 クロスサイト・スクリプティング、5-(x))でも、CSPなどのレスポンスヘッダーは保険的対策の位置づけです。
CSPがレスポンスヘッダーで強制されているの診断基準(セキュリティAIチェッカー)
取得方法
診断対象URLの最終応答(リダイレクト追跡後のトップページ)1件について、次の3点を確認します。追加の通信はありません。
Content-Security-Policyレスポンスヘッダーの有無(複数ある場合はカンマで連結された値)Content-Security-Policy-Report-Onlyレスポンスヘッダーの有無- HTML内の
<meta http-equiv="content-security-policy">要素の有無(大文字小文字は区別しない。http-equivの値が引用符で囲まれているものを検出。タグ内の属性値に<や>を含むmeta要素は検出しません)
判定条件
| 判定 | 条件 | 根拠文の例 |
|---|---|---|
| ○ 問題なし(pass) | 強制CSPヘッダーあり(Report-Onlyやmetaの有無は問わない) | 強制CSPヘッダーを確認 |
| △ 要確認(warn) | 強制ヘッダーなし、Report-Onlyヘッダーのみ | Report-Onlyのみで強制CSPはない |
| △ 要確認(warn) | 強制ヘッダーなし、meta CSPのみ(Report-Onlyなし) | meta CSPのみ。frame-ancestors等はmetaでは強制できない |
| × 要改善(fail) | いずれもなし | CSPを確認できない |
この項目は、ヘッダーの「存在と強制モード」だけを見ます。たとえば Content-Security-Policy: upgrade-insecure-requests のように、スクリプトの制限を含まないポリシーでも○になります。その場合は「CSPの基幹ディレクティブ」「CSPのdefault-src」などの項目で弱さが指摘されます。
得点への影響
| 判定 | 得点 |
|---|---|
| ○ 問題なし(pass) | 4点(重み4) |
| △ 要確認(warn) | 1.8点 |
| × 要改善(fail) | 0点 |
CSP未設定のサイトは「Content Security Policy」項目(重み4)でも×となるため、CSP未導入は合計で大きく減点されます。
自治体サイトでの判定例
| 状況 | 判定 |
|---|---|
| CMSのHTMLテンプレートにmeta CSPを入れているだけ | △ |
WAF・CDNで Content-Security-Policy-Report-Only を試験導入中 | △ |
.htaccess で Content-Security-Policy: frame-ancestors 'self'; upgrade-insecure-requests を送っている | ○(中身の評価は別項目) |
| ヘッダーもmetaもない | × |
CSPが強制されていないとどんなリスクがあるか
- XSSの被害拡大:CSPが強制されていないと、XSS脆弱性が1つでもあれば任意の外部スクリプトを読み込まれ、入力フォームの内容(住所・氏名・申請内容)を外部へ送信されるおそれがあります(CWE-79)。
- クリックジャッキング:frame-ancestors が強制されないと、自治体サイトを透明なiframeで重ね、利用者に意図しない操作(申請の送信、設定変更)をさせる攻撃が成立しやすくなります(X-Frame-Optionsで代替している場合を除く。CWE-1021)。
- 改ざんスクリプトの実行:CMSや外部ウィジェット経由で不正なスクリプトが挿入された場合に、ブラウザ側で止める手段がありません。
- 「対策済み」という誤認:Report-Onlyのまま運用すると、違反報告が届いていても攻撃は防げず、「対策済み」という誤認が残ります。
CSPをレスポンスヘッダーで強制する設定方法(Apache・nginx・IIS・Next.js)
段階的導入の手順
- 現状の外部資源(Google Analytics、地図、動画埋め込み、翻訳ウィジェット、CDN)を洗い出す。
Content-Security-Policy-Report-Onlyで試験ポリシーを配信し、違反報告や開発者ツールのコンソールで影響を確認する(1〜4週間)。- 問題がなくなったら、同じポリシーを
Content-Security-Policyに切り替える。 - 切替後も、Report-Only で、より厳しい次期ポリシーを並行して試す。
Apache(.htaccess)
<IfModule mod_headers.c>
# 段階1: まずは報告のみ
# Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'"
# 段階2: 強制(既存のインライン script/style が多い CMS 向けの現実的な初期値)
Header always set Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; upgrade-insecure-requests"
</IfModule>
上記の初期値は「サイトを壊さないこと」を優先した妥協案で、'unsafe-inline' を含むため別項目では減点されます。最終的には nonce/hash を使う Strict CSP へ移行します。
nginx
add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'" always;
add_header は、location ブロックに別の add_header があると親の設定が継承されない点に注意します。always を付けるとエラー応答にも付与されます。
IIS(web.config)
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'" />
</customHeaders>
</httpProtocol>
</system.webServer>
Next.js(next.config.js)
module.exports = {
async headers() {
return [{
source: "/(.*)",
headers: [{
key: "Content-Security-Policy",
value: "default-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'",
}],
}];
},
};
nonce を使う場合は、proxy.ts(Next.js 15 以前は middleware.ts)でリクエストごとに nonce を生成してヘッダーに設定します。nonce を使うページは動的レンダリングが必要です。
設定後の確認方法
curl -sI https://www.city.example.lg.jp/ | grep -i '^content-security-policy'
content-security-policy: の行が出れば強制、content-security-policy-report-only: だけなら未強制です。
サイトを壊さないための注意点(ガードレール)
- 上位ディレクトリの
.htaccessで厳しいCSP(script-src 'self'のみ等)を設定すると、配下のインラインスクリプトを使うアプリがすべて動かなくなります。必ず Report-Only で確認してから強制します。 - meta CSPとヘッダーCSPを両方置くと両方が適用され、意図より厳しくなることがあります。移行後はmetaを削除して一本化します。
- CMSのプレビュー画面や管理画面、外部決済・地図の埋め込みなど、トップページ以外の画面も確認します。
- 違反報告先の設定は「CSP違反の報告先」で確認します。
よくある質問(FAQ)
CSPはmetaタグで設定しても効果がありますか?
meta要素のCSPも強制されますが、一部の機能が使えません。W3C CSP Level 3では、metaでは frame-ancestors・report-uri・sandbox が使えず、Report-Onlyも使えません。またmeta要素より前にある要素やLinkヘッダーで先読みされた資源には適用されないため、レスポンスヘッダーでの配信が推奨です。
Content-Security-Policy-Report-Onlyだけでも対策済みと言えますか?
言えません。Report-Onlyは違反を報告するだけで、スクリプトの実行や外部読み込みは止めません。WSTG-CONF-12もReport-Onlyしかない場合はポリシーが強制されていないと明記しています。導入時の影響調査として使い、確認後に強制ヘッダーへ切り替えます。
meta CSPでクリックジャッキングは防げますか?
防げません。frame-ancestorsディレクティブはmeta要素では無視されるため、クリックジャッキング対策にはContent-Security-Policyレスポンスヘッダー(またはX-Frame-Options)が必要です。
ヘッダーとmetaの両方にCSPを書くとどうなりますか?
両方のポリシーが同時に適用され、どちらか一方でも禁止された読み込みはブロックされます。ポリシーを追加すると制限は厳しくなる方向にしか働かないため、意図より厳しくなることがあります。ヘッダーへ移行したらmetaは削除して一本化します。
CSPヘッダーが強制されているかを確認する方法は?
curl -sI でヘッダーを取得し、content-security-policy で始まる行を確認します。content-security-policy: の行があれば強制、content-security-policy-report-only: だけなら未強制です。
CSPヘッダーがあれば中身はどんな値でも○になりますか?
この項目は強制モードのヘッダーがあるかだけを見るため、upgrade-insecure-requests のみのようなポリシーでも○になります。ポリシーの中身の弱さは「CSPの基幹ディレクティブ」「CSPのdefault-src」などの別項目で指摘されます。
CSPを入れればXSS対策は不要ですか?
不要にはなりません。CSPは出力エスケープなどの根本対策を補う多層防御で、IPA「安全なウェブサイトの作り方」(1.5 クロスサイト・スクリプティング、5-(x))でも、CSPなどのレスポンスヘッダーは保険的対策の位置づけです。
この項目を含む127項目を、URLを入れるだけで無料診断します。
参考資料
- W3C Content Security Policy Level 3
- MDN Content-Security-Policy
- OWASP ASVS 5.0.0 V3 Web Frontend Security(V3.4.3・V3.4.6・V3.4.7)
- OWASP WSTG-CONF-12 Test for Content Security Policy
- OWASP Content Security Policy Cheat Sheet
- IPA「安全なウェブサイトの作り方」
- nginx ngx_http_headers_module(add_header)
- Next.js「Content Security Policy」ガイド