AIと開発

コンテンツ セキュリティ ポリシー(CSP)

執筆:Jake Luo · 公開日:2026年9月23日

コンテンツ セキュリティ ポリシー(CSP)とは、Webサイトがブラウザに送るルールの集まりで、ふつうは Content-Security-Policy レスポンスヘッダーとして届きます。ページがスクリプト、スタイル、画像、フォント、フレームをどこから読み込んでよいか、そしてデータをどこへ送ってよいかを指定します。ポリシーが許していないものは、実行される前にブラウザが拒否します。それでもページ自体は表示されるため、CSPの設定ミスはエラーのようには見えません。何かが黙って欠けたページに見えるのです。

ポリシーが実際に制御するもの

ポリシーはディレクティブの一覧で、それぞれが一種類のリクエストを受け持ちます。もともとはクロスサイトスクリプティングに対する第二の防御線として設計されました。攻撃者がページにマークアップを差し込めたとしても、ポリシーが一度も名前を挙げていない読み込み元のスクリプトは、ブラウザが実行を拒みます。最初に出会うディレクティブは次のとおりです。

  • default-src — フォールバックです。専用のディレクティブを持たない取得タイプはすべてこれを引き継ぐため、default-src 'self' は、別途指定しない限りフォントやメディアなどまで黙って対象にします。
  • script-src、style-src、img-src、font-src — 各種のサブリソースをどこから読み込めるか。'self' はページ自身のオリジン、ホスト名を書けばそのホストを許可し、'unsafe-inline' はページ内に直接書かれたコードを許可します。
  • connect-src — ページ自身のコードが fetch、XHR、WebSockets でリクエストを送れる宛先。スクリプトが外部と通信できるかどうかを決めるのはこのディレクティブです。
  • form-action — フォームの送信先。frame-ancestors — そのページをフレームに埋め込めるのは誰か。X-Frame-Options に代わる現行の仕組みです。
  • nonce とハッシュ — インラインスクリプトをすべて許可せずに、特定の一つだけを許可する方法です。サーバーが自分で書いたスクリプトに印を付け、あとから差し込まれたものにはその印がありません。

配信方法について、つまずきやすい点が二つあります。ポリシーは <meta http-equiv> タグでも設定できますが、この形式はすべての機能に対応しているわけではなく、レポート専用のポリシーはこの方法ではそもそも配信できません。また、同じディレクティブが二回書かれていると、ブラウザは最初のものに従い二つ目を無視します。そのため「追加した」はずのルールが、ソース上は正しく見えたまま何の効果も持たないことがあります。

ブロックされたリソースが黙って失敗する理由

ブラウザはポリシーに基づいてリクエストを拒否すると、開発者コンソールに一行書き出して、そのまま描画を続けます。エラーページもアラートも出ず、訪問者やサイトをざっと見たオーナーが気づくものは何もありません。その後のページの見た目は、何が拒否されたかで決まります。アナリティクスのスクリプトがブロックされると、ページは寸分違わず同じ見た目のまま、数値はゼロになります。Webフォントがブロックされるとシステムフォントに置き換わり、ほとんどの人は気づきません。スタイルシートやCSSフレームワークがブロックされると、デザインされたページが装飾のないHTMLに変わります。

実務上の問題はこの幅にあります。同じ種類の違反が、目に見えないものからページを壊すものまであり、ポリシーの文面からはどちらに当たるのか分かりません。ローカルのコピーではなく、公開したURLでテストしてください。手元のPCで開いたファイルはふつうポリシーなしで表示されるため、公開ページでは拒否されるものまで全部読み込めてしまいます。AIで作ったページがプレビューでは正しく見え、公開すると崩れる理由として、これが最も多いものです。

他社のページでポリシーを運用して学んだこと

AgentCeres — agentceres.com のAI Growth Officer — は、エージェントが顧客のために作ったページを公開しており、そのすべてを厳格なポリシーのもとで配信しています。リソースはページ自身のオリジンからのみ、画像はオリジンからか直接埋め込んだもの、フォームの送信先はホスト自身のみ、他サイトへの埋め込みは不可、そして connect-src 'none' です。つまりページ上のコードは計算し、ローカルに記憶し、画面遷移はできますが、ネットワークリクエストは一つも送れません。この最後のルールがあるため、ページのコードに置いたシークレットは、公開ページからは使うことすらできません。

2026-09-04 にホストしている全ページを調べたところ、52ページ中5ページに、一度も読み込まれない外部リソースが少なくとも一つありました。最もひどかったのは、レイアウト全体を公開CDNから読み込むCSSフレームワークに頼っていたページです。ポリシーは外部ホストを一つも許可していないため、フレームワークは届かず、ページは装飾のない素のテキストとして公開されました。ほかにも、ラジオのストリームや埋め込みフレームを失ったページがありました。公開時にブロックされる参照を取り除くことも検討しましたが、採用しませんでした。取り除いたページは「問題なく公開」されたまま、やはり崩れて見えるからです。公開そのものを拒否するのも同じくらい悪い選択でした。同じルールが、代替フォントに切り替わるだけのフォントのためにページを止めてしまうからです。そこで公開ステップでは、ブロックされる参照ごとに、それを拒否するディレクティブを添えて報告し、誰かがページを見る前に修正できるようにしました。判定はサーバーが送るのと同じディレクティブ一覧から、フォールバックも含めて計算するため、警告がポリシーとずれることはありません。

この教訓は当社の構成に限りません。実際のページに当てて確かめていないポリシーは、何も告げずにページを壊すポリシーです。強制する前に Content-Security-Policy-Report-Only として送り、何もブロックせずに違反だけを報告させて、何が壊れていたはずかを読んでください。

ポリシーにできないこと

CSPが制御するのは、ページが何を読み込めて、どこへ接続できるかです。それ以上の役割を期待してしまいがちです。

  • Cookie 用のディレクティブはありません。 ポリシーが許可したスクリプトは、HttpOnly が付いたもの以外の Cookie を読み書きできます。親ドメインを共有するページ同士は Cookie も共有でき、それを塞ぐにはポリシーを厳しくするのではなく、別の仕組みが必要です。
  • インラインコードを安全にはしません。 'unsafe-inline' を許可すると、攻撃者が書き込めたものも含め、ページに書かれたものは何でも実行されます。それを避けるためにあるのが nonce とハッシュです。
  • エスケープや入力検証の代わりにはなりません。 インジェクションの被害を限定するだけで、インジェクション自体は防ぎません。ユーザー入力を信用するページは、悪用しにくくなっただけで、壊れたままです。
  • AIエージェントを入力から守りません。 ポリシーはブラウザが悪意あるスクリプトを読み込むのを止めますが、エージェントが読んで行動の根拠にする悪意ある*テキスト*には何もできません。それはプロンプトインジェクションという別の問題です。

よくある質問

画像やフォントがローカルでは表示されるのに、公開サイトでは表示されないのはなぜですか?
多くの場合、ホストはポリシーを配信していて、ローカルのコピーにはポリシーがないためです。公開ページを開き、ブラウザのコンソールで Content Security Policy に触れている行を探してください。それぞれの行に、リクエストを拒否したディレクティブが書かれています。対処は、そのファイルを自分のサイトから配信するか、そのファイル種別を受け持つディレクティブに外部ホストを追加するかのどちらかです。
エラーを消すために 'unsafe-inline' やワイルドカードを足してもいいですか?
できますし、動きます。ただし、ポリシーが守っていたものの大半も失われます。実際に使っているホストを個別に指定し、インラインスクリプトはすべてではなく、nonce やハッシュで一つずつ許可してください。必要なホストが分からないなら、しばらくレポート専用モードでポリシーを動かし、レポートを読んでください。
コンテンツ セキュリティ ポリシーはSEOに影響しますか?
直接には影響しません。検索エンジンはこれを順位付けに使っていません。ただし、描画されたページが依存しているもの、たとえばコンテンツや構造化データを挿入するスクリプトをブロックすると、間接的に影響することがあります。ブラウザでページを描画するクローラーも、たいてい同じ拒否に遭うからです。ソースだけでなく、描画後のページを確認してください。
関連用語
プロンプトインジェクションバイブコーディングデザインシステムレート制限(Rate Limit)

これを代わりに実行する AI グロースチーム

AgentCeres はマネージド型の AI マーケティングチームです。何を公開するかはあなたが承認します。14日間無料トライアル、月額 $39 から。

無料トライアルを開始用語集を見る