CSP(Content Security Policy)の設定方法

CSP(Content Security Policy)の設定方法

Webサイトのセキュリティ対策として重要なCSPですが、ディレクティブが多くて時々設定方法を忘れてしまうことがあります。今回は、自分用のメモとして基本的な設定方法から実践的な例までをまとめてみました。

セキュリティ #CSP#HTML#セキュリティ

CSP(Content Security Policy)の設定方法

サムネイル

Webサイトのセキュリティ対策として重要なCSPですが、ディレクティブが多くて時々設定方法を忘れてしまうことがあります。今回は、自分用のメモとして基本的な設定方法から実践的な例までをまとめてみました。

更新日: 7/19/2025

CSPとは?

CSPは、クロスサイトスクリプティング(XSS)などの攻撃を防ぐために、ブラウザがどのオリジン(ドメイン)からリソースを読み込んで良いかを制御するセキュリティ機能です。意図しないドメインからのスクリプトや画像の読み込みをブロックできます。

ちょっと大きめの会社だとセキュリティ要件やコーディング規則に入っていたりするので、「CSPってなんだろう?」と恥をかかないように覚えておきましょう。

基本的な設定方法

設定方法は主に2つあります。

1. HTMLのmetaタグで設定する

手軽に試せるのが、HTMLの<head>内にmetaタグを記述する方法です。

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Security-Policy" 
        content="default-src 'self'; script-src 'self' https://cdn.example.com;">
  
  <title>CSPの例</title>
</head>
<body>
  <script src="/js/app.js"></script>
  
  <script src="https://cdn.example.com/library.js"></script>
  
  <script src="https://evil.com/malicious.js"></script>
  
  <script>
    alert('このコードは実行されません');
  </script>
</body>
</html>

この例では、default-src 'self'で基本的に自ドメインからのリソースのみを許可し、script-srcで追加でhttps://cdn.example.comからのスクリプト実行を許可しています。デフォルトでインラインスクリプトはブロックされます。

2. HTTPヘッダーで設定する

より推奨される方法が、サーバーからのHTTPレスポンスヘッダーでCSPを指定する方法です。Node.js/Expressでhelmetミドルウェアを使うと簡単に設定できます。

import express from 'express';
import helmet from 'helmet';

const app = express();

// helmetを使用してCSPを設定
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://cdn.example.com"],
      styleSrc: ["'self'", "'unsafe-inline'"], // スタイルはインラインを許可
      imgSrc: ["'self'", "data:", "https:"],   // 画像はdata:とhttpsも許可
      objectSrc: ["'none'"], // objectタグはすべて禁止
      upgradeInsecureRequests: [], // HTTPリクエストをHTTPSに
    },
  })
);

よく使うディレクティブと値

CSPの設定はディレクティブと値の組み合わせで行います。

ディレクティブ 説明
default-src 全てのリソースタイプのデフォルトの読み込み元を指定します。
script-src JavaScriptファイルの読み込み元を指定します。
style-src CSSファイルの読み込み元を指定します。
img-src 画像ファイルの読み込み元を指定します。
connect-src fetchWebSocketなどの接続先を指定します。
font-src フォントファイルの読み込み元を指定します。
object-src <object>, <embed>, <applet>の読み込み元を指定します。
説明
'self' 同一オリジンからのリソースを許可します。
'none' すべてのリソースをブロックします。
'unsafe-inline' インラインの<script><style>を許可します。(非推奨)
'unsafe-eval' eval()のような動的コード実行を許可します。(非推奨)
https: HTTPSプロトコル経由のリソースを許可します。
data: data:URIスキーム(Base64エンコード画像など)を許可します。

非推奨のものもあるので注意

設定例(Next.js)

Next.jsのようなフレームワークでは、設定ファイルで一元管理するのが一般的です。next.config.jsに記述することで、全ページにCSPヘッダーを適用できます。

module.exports = {
  async headers() {
    const cspValue = `
      default-src 'self';
      script-src 'self' 'unsafe-eval' 'unsafe-inline' https://www.google-analytics.com;
      style-src 'self' 'unsafe-inline';
      img-src 'self' blob: data: https:;
      connect-src 'self' https://api.example.com;
      font-src 'self';
      object-src 'none';
      frame-ancestors 'none';
      upgrade-insecure-requests;
    `.replace(/\s{2,}/g, ' ').trim(); // 改行と余分なスペースを削除

    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: cspValue,
          },
        ],
      },
    ];
  },
};

この設定は、Google Analyticsのスクリプトを許可しつつ、APIサーバーとの通信も許可する、といった要件を想定したものです。

CSPは設定を間違えるとバグを生みやすく、原因が分かりづらいのでメンテナンス性が落ちる可能性もあります。導入する際は、ブラウザの開発者ツールでブロックされたリソースを確認しながら、少しずつ適用範囲を広げていくのが安全だと感じました。

検索

検索条件に一致する記事が見つかりませんでした