CSP(Content Security Policy)とは?
CSP(Content Security Policy)は、Webページが読み込めるリソースの種類と発生元を制御するセキュリティの仕組みです。HTTPレスポンスヘッダーとして設定することで、スクリプト・スタイル・画像・フォントなどの読み込み元をホワイトリスト形式で指定できます。XSS(クロスサイトスクリプティング)やデータインジェクション攻撃のリスクを低減する効果が期待できます。
ただし、CSPはすべての攻撃を防ぐ「銀の弾丸」ではありません。適切な設定と定期的な見直しが必要です。
CSPヘッダーの基本的な書き方
CSPヘッダーは、ディレクティブ(設定項目)とそれぞれの許可ソースをセミコロン区切りで並べます。
Content-Security-Policy: default-src 'self'; script-src 'self'; img-src 'self' data:;
-
default-src:他のディレクティブのデフォルト値 script-src:JavaScriptの読み込み元style-src:CSSの読み込み元'self':同一オリジンのみ許可'none':すべて禁止
「Content Security Policy(CSP)がありません」と表示されたときは?
セキュリティスキャナーやChrome拡張などが「CSPヘッダーがありません」と警告することがあります。これは、CSPが設定されていないことを示す情報的な通知です。
CSPを初めて設定する場合は、必ずReport-Onlyモードから始めてください。いきなり本番適用すると、サイトの表示が崩れたり機能が動作しなくなる可能性があります。
.htaccessでCSPを設定する方法
Apache環境では
.htaccess に以下のように記述します。mod_headers
モジュールが有効になっている必要があります。
<IfModule mod_headers.c>
Header always set Content-Security-Policy-Report-Only "default-src 'self';"
</IfModule>
サーバー環境によっては
Header always set ではなく
Header set
が適切な場合もあります。設定後は必ず動作を確認してください。
NginxでCSPを設定する方法
Nginxでは
nginx.conf
またはサーバーブロック内に以下のように記述します。
add_header Content-Security-Policy-Report-Only "default-src 'self';" always;
always
を付けると、エラーレスポンス時にもヘッダーが付与されます。設定後は
nginx -t で構文チェックを行ってください。
Report-Onlyでテストしてから本番反映する
Content-Security-Policy-Report-Only
ヘッダーを使うと、CSPポリシーの違反を記録するだけでリソースのブロックは行いません。まずこちらで設定し、ブラウザのコンソールやレポートエンドポイントで違反を確認してから、問題がないと判断できた段階で
Content-Security-Policy
に切り替えるのが安全です。
WordPressでCSPを設定するときの注意点
WordPressは、テーマ・プラグイン・Gutenbergエディタ・解析タグ・広告スクリプトなど、多くの外部リソースを読み込む場合があります。CSPを厳しく設定すると、管理画面の機能やプラグインが動作しなくなることがあります。
- 必ずReport-Onlyモードで動作確認する
-
Gutenbergエディタは
'unsafe-inline'を必要とする場合がある - Google AnalyticsやFacebook Pixelなどを使う場合は関連ドメインを許可する必要がある
- テーマ・プラグインのアップデートで必要な許可元が変わることがある
unsafe-inline / unsafe-eval の注意点
'unsafe-inline'
を設定すると、インラインのscriptやstyleタグが実行されるようになりますが、XSSの防御効果が大幅に低下します。既存サイトの動作確認の一時的な用途にとどめ、可能であればnoncesまたはhashへの移行を検討してください。
'unsafe-eval' は
eval() やその派生関数(setTimeout
に文字列を渡すなど)を許可しますが、コードインジェクション攻撃のリスクが高まります。必要な理由が明確な場合のみ使用してください。
nonce / hash を使う場合の考え方
nonce(ナンス):リクエストごとにサーバー側でランダムな値を生成し、CSPヘッダーと対象のscript/styleタグの両方に同じnonceを付与する方法です。インラインコードを安全に許可できますが、サーバーサイドの実装が必要です。
hash:インラインコードの内容をSHA-256でハッシュ化し、その値をCSPに記述する方法です。コードが変わるたびにCSPの更新が必要です。内容が固定のインラインコードに適しています。
❓ よくある質問(FAQ)
- CSPとは何ですか?
- Content Security Policyの略で、Webページが読み込めるリソースの発生元を制限するHTTPヘッダーです。XSSなどの攻撃リスクを低減する効果が期待できます。
- CSPヘッダーはどこに設定しますか?
-
Apacheなら
.htaccessまたはhttpd.conf、Nginxならnginx.conf、PHPならheader()関数で設定します。WordPressではプラグインを使う方法もあります。 - .htaccessでCSPを設定できますか?
-
はい。
mod_headersが有効なApache環境では<IfModule mod_headers.c>内でHeader always setコマンドを使って設定できます。 - Nginxではどのように設定しますか?
-
add_header Content-Security-Policy "...";をserver{}ブロックまたはlocation{}ブロック内に記述します。alwaysを付けるとエラー時にも適用されます。 - WordPressでもCSPを使えますか?
- 使えますが、テーマ・プラグインによって必要な許可元が異なるため、必ずReport-Onlyで確認してから本番適用してください。Gutenbergや解析ツールが想定外にブロックされる場合があります。
- unsafe-inlineは使ってもよいですか?
- 既存サイトの動作確認など一時的な用途では使われますが、インラインスクリプトを許可するためCSPのXSS防御効果が低下します。nonceまたはhashへの移行を検討してください。
- nonceとは何ですか?
- リクエストごとにサーバーが生成するランダムな値です。CSPヘッダーとscript/styleタグに同じnonceを付与することで、インラインコードを安全に許可できます。サーバーサイドの実装が必要です。
- hashとは何ですか?
- インラインコードの内容をSHA-256などでハッシュ化した値をCSPに記述する方法です。コード内容が変わるたびに更新が必要ですが、内容が固定のインラインコードに有効です。
- Report-Onlyとは何ですか?
-
Content-Security-Policy-Report-Onlyヘッダーを使うモードです。違反はコンソールやreport-uriに記録されますが、実際にリソースはブロックされません。本番適用前の安全なテスト方法です。 - CSPを設定するとサイトが崩れることはありますか?
- はい。外部CDNやインラインスクリプト・スタイル、外部フォント、解析タグなどがブロックされてサイト表示や機能に影響することがあります。必ずReport-Onlyで事前に確認してください。