Content Security Policy(CSP)をApacheで設定する方法:ヘッダの書き方とよくあるエラー

本記事では、様々な企業がよく使用するWebサーバーのApacheでCSPヘッダを正しく設定するための前提知識(設定場所の選び方、mod_headers、Header set/always setの違い、HTTPS環境での注意)を整理します。
まずはdefault-src 'self'から始めるコピペ例、CDNやGoogle Fonts、data:画像の許可、object-src 'none'やframe-ancestorsまで実用例を紹介します。さらに「効かない」「画面が崩れる」原因になりやすいインラインScriptやイベント、許可漏れ、オリジン違い、書き方ミスの直し方も解説します。
目次
- そもそもContent Security Policy(CSP)とは?
- ApacheでCSPヘッダを設定する前に知ること(前提と注意点)
- Apacheでの設定方法:コピペで使えるCSP設定例(基本〜実用)
- よくあるエラー集:表示崩れ・機能停止を最短で直すコツ
- エラー:そもそもヘッダが付かない(mod_headersが無効)
- エラー:.htaccessに書いたのに無視される(AllowOverride)
- エラー:設定場所が違う(VirtualHostに書いたつもりが別サイトに効いてる)
- エラー:HTTPでは付くのにHTTPSでは付かない(*:443側に書いてない)
- エラー:Header set だと一部応答で付かない(alwaysを使うべき)
- エラー:同じヘッダが二重に付く(どこかで重複設定)
- エラー:反映されない(再起動/リロード忘れ or 読んでるファイルが違う)
- エラー:書式エラーでApacheが起動しない(引用符・セミコロン・クォート崩れ)
- エラー:304/キャッシュで「変わってないように見える」
- エラー:リバースプロキシ/上流がヘッダを消している
- まとめ
そもそもContent Security Policy(CSP)とは?
Content Security Policy(CSP)は、ブラウザに「読み込んでよいスクリプトや画像の範囲」を指示してXSSなどを抑える仕組みです。
詳しくは別の記事で解説していますので、参考にしてみてください。
参考記事:CSP(Content Security Policy)とは?XSS対策に欠かせない理由と注意点
ApacheでCSPヘッダを設定する前に知ること(前提と注意点)
ApacheでCSPヘッダを設定する場合は、Apache特有の設定方法や注意点があるので覚えていきましょう。
設定場所の選び方:httpd.conf / VirtualHost / Directory / .htaccess
CSPの設定方法は「どのファイル・ブロックでヘッダを付けるか」で挙動が変わります。
- httpd.conf:Apache全体に適用したいときに使う設定ファイル。CSPヘッダの書き方をここに置くと、原則すべてのサイト/パスに効く。全体方針を決めたい場合向き。
- VirtualHost:ドメイン・ポート(例:
:80/*:443)単位で設定を分けたいときに使う。HTTPSサイトだけCSPを強める、特定サイトだけ外部CDNやdata:を許可する、といった設定方法に向く。 - Directory:特定ディレクトリ配下にだけ適用したいときに使う。管理画面だけ厳しいCSP、公開側だけ緩める、などパス単位で調整できる。
- .htaccess:サーバ設定ファイルを触れない環境(レンタルサーバ等)で、ディレクトリごとに手軽に設定したいときに使う。ただしAllowOverrideの設定次第で無効だったり、上位(httpd.conf/VirtualHost)に上書きされて「ヘッダが効かない」原因になりやすい。
目的に応じて、適切なファイル・ブロックにCSPを設定するように意識しましょう。
mod_headers(Headerディレクティブ)が必要
CSPとはレスポンスヘッダでブラウザに制約を伝える仕組みなので、Apache側でそのヘッダを付ける機能が必要です。そこで使うのがmod_headersで、これが有効でないとHeader set Content-Security-Policy ...のような書き方をしてもCSPが返りません。
# 例:httpd.conf(または conf.modules.d/*.conf)で mod_headers を有効化 LoadModule headers_module modules/mod_headers.so
上記の様にmod_headersは LoadModule で読み込んで有効化することができます。
modules/mod_headers.so のパスは環境で違うので、既存の LoadModule 行の書き方に合わせてください。設定後は Apache を再読み込み/再起動します。
Header set と Header always set の違い(効かない原因になりがち)
ApacheでCSPヘッダを付ける設定方法では、Header setとHeader always setの違いが「効かない」原因になりがちです。
- Header set:通常のレスポンスに指定したヘッダを付ける書き方。状況によっては(リダイレクトやエラー応答など)ヘッダが付かず、CSPが「効いていない」と見える原因になりやすい。
- Header always set:通常のレスポンスに加えて、リダイレクトやエラー応答などでもヘッダを付けやすい書き方。CSPのように「常に返して効かせたい」ヘッダは基本こちらが無難。
HTTPS/SSL環境での設定位置(VirtualHost *:443 の考え方)
HTTPS/SSL環境では、CSPヘッダの設定位置を間違えると「HTTPでは付くのにHTTPSでは付かない」状態になりがちです。
Apacheでは443番ポート用に<VirtualHost *:443>が別に定義されていることが多く、CSPの書き方はその中に書くのが基本です。逆に*:80側だけに設定すると、実際に閲覧されるHTTPS応答には反映されません。
いきなり本番適用しない:まずReport-Onlyで安全に試す
CSPはいきなり本番適用すると、必要な外部JSやCSSまでブロックして画面崩れや機能停止を起こすことがあります。
# httpd.conf / VirtualHost / Directory など Header always set Content-Security-Policy-Report-Only "default-src 'self'"
そこで最初は上記の様にReport-Onlyを使い、実際にはブロックせず「違反ログだけ出す」設定方法で影響範囲を確認します。Content-Security-Policy-Report-Onlyヘッダとして通常と同じ書き方で付与でき、default-src 'self'から始めて段階的に影響範囲を調整していくといいです。
Apacheでの設定方法:コピペで使えるCSP設定例(基本〜実用)
ApacheにおけるCSPの設定例について、ここではシチュエーションごとにまとめます。参考にしてみてください。
例:default-src 'self'(まずはこれ)をApacheで返す
最小構成。基本は同一オリジン以外を遮断。
Header always set Content-Security-Policy "default-src 'self'"
例:script-srcで外部JSを許可(Google Analytics / CDNなど)
自サイト+特定ドメインだけJSを許可。必要な外部だけ追加する。
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com"
例:style-srcで外部CSSやフォントを許可(Google Fontsなど)
外部CSS(fonts.googleapis.com)とフォント本体(fonts.gstatic.com)を許可。
Header always set Content-Security-Policy "default-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com"
例:img-srcでdata:を許可(data URI画像が表示されない対策)
SVGアイコン等で data: を使うサイト向け。
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:"
例:object-src 'none' でプラグイン系を遮断(安全側の基本)
Flash等のプラグイン埋め込みを無効化。基本“none推奨”。
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'"
例:frame-ancestors で埋め込み制御(クリックジャッキング対策にも)
他サイトから iframe 埋め込みされるのを防ぐ(または許可先を限定)。
# 埋め込み全面禁止 Header always set Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
よくあるエラー集:表示崩れ・機能停止を最短で直すコツ
ここではApacheでCSPを設定する際によく起きるエラーの解決方法についてまとめましたので、参考にしてみてください。
エラー:そもそもヘッダが付かない(mod_headersが無効)
- 症状:Content-Security-Policy がレスポンスに出ない
- 原因:mod_headers が読み込まれていない
- 確認:apachectl -M | grep headers(headers_module が出るか)
- 対処(例)
LoadModule headers_module modules/mod_headers.so
エラー:.htaccessに書いたのに無視される(AllowOverride)
- 症状:.htaccess に書いたのにヘッダが付かない
- 原因:AllowOverride None などで .htaccess が無効、または FileInfo が許可されてない
- 対処(例)
<Directory "/var/www/html"> AllowOverride FileInfo </Directory>
エラー:設定場所が違う(VirtualHostに書いたつもりが別サイトに効いてる)
- 症状:Aサイトに入れたはずがBサイトに付く/付かない
- 原因:CSP設定が別の
<VirtualHost>に入っている、または想定と違う vhost がマッチしている - 対処:該当ドメインの
<VirtualHost>ブロック内に書く(ServerName/ServerAliasも確認)
エラー:HTTPでは付くのにHTTPSでは付かない(*:443側に書いてない)
- 症状:http:// だとヘッダが出るが https:// だと出ない
- 原因::80 の vhost にしか書いていない(SSL用は別の
<VirtualHost *:443>) - 対処(例)
<VirtualHost *:443> Header always set Content-Security-Policy "default-src 'self'" </VirtualHost>
エラー:Header set だと一部応答で付かない(alwaysを使うべき)
- 症状:通常ページは付くが、リダイレクト/エラー応答で付かないことがある
- 原因:Header set の挙動差
- 対処:基本は Header always set を使う
Header always set Content-Security-Policy "default-src 'self'"
エラー:同じヘッダが二重に付く(どこかで重複設定)
- 症状:レスポンスに Content-Security-Policy が2行以上出る
- 原因:httpd.conf と vhost、vhost と .htaccess などで二重設定
- 対処:設定箇所を統一するか、意図して上書きする
Header unset Content-Security-Policy Header always set Content-Security-Policy "default-src 'self'"
エラー:反映されない(再起動/リロード忘れ or 読んでるファイルが違う)
- 症状:設定を変えたのにヘッダが変わらない
- 原因:Apache再読み込みしてない/別の設定ファイルを編集している
- 対処:
apachectl -t -D DUMP_INCLUDESで読み込み元を確認、systemctl reload httpd等で反映
エラー:書式エラーでApacheが起動しない(引用符・セミコロン・クォート崩れ)
- 症状:起動時に設定エラー、またはCSPが途中で途切れる
- 原因:ダブルクォート
"の閉じ忘れ、全角記号、改行混入など - 対処:
apachectl configtestで検知して直す
エラー:304/キャッシュで「変わってないように見える」
- 症状:DevToolsで確認するとヘッダが見えたり見えなかったり
- 原因:304 Not Modified の扱い、表示方法の勘違い
- 対処:DevToolsのNetworkで該当リクエストを選び、Response Headers を見る/
curl -Iで確認
エラー:リバースプロキシ/上流がヘッダを消している
- 症状:Apacheで付けてるはずなのに、外から見ると無い
- 原因:手前のCDN/プロキシや別Apache(フロント)がヘッダを上書き/削除
- 対処:実際にインターネットから見える最終レスポンスで
curl -I https://...を確認し、どの層で消えてるか切り分け
まとめ
ここまでApacheでCSPを設定するやり方やエラーパターンなどについて解説しました。まとめると下記の通りです。
- CSPは、ブラウザに読み込みルールを指示してXSS等を抑えるセキュリティヘッダ
- Apacheでは「どこに書くか」(httpd.conf / VirtualHost / Directory / .htaccess)で効き方が変わる
- CSPヘッダ付与には mod_headers が必須で、
LoadModule headers_module ...で有効化する Header setは一部応答で付かない場合があるため、基本はHeader always setを使う- HTTPS環境では
<VirtualHost *:443>側にも設定しないと「HTTPSだけ効かない」になりやすい - いきなり本番適用せず、まずは
Content-Security-Policy-Report-Onlyで影響を確認してから切り替える - 設定は
default-src 'self'から始め、必要に応じて外部JS/CDN、Google Fonts、data:画像などを段階的に許可する - よくある「効かない」原因は、mod_headers未有効、.htaccess無効(AllowOverride)、設定箇所違い、HTTPS側未設定、ヘッダ重複、反映忘れ、書式ミス、キャッシュ/304、上流でのヘッダ削除
ApacheでCSPの設定をする際は是非参考にしてみてください。まずはReport-Onlyから入れて、DevTools等でヘッダを確認してみましょう。





