すべての解説
深刻度:高セキュリティヘッダー

Content-Security-Policy(CSP)とは何か、どう追加するか

Content-Security-Policy(CSP)は、スクリプト、スタイル、その他のコンテンツをどのソースから読み込み・実行してよいかをブラウザに伝えるHTTP応答ヘッダーです。優れたCSPは、クロスサイトスクリプティング(XSS)に対する最も強力な防御の一つです。

これは何か

CSPは、ブラウザが強制する許可リストです。サーバーがContent-Security-Policyヘッダーを送ると、ブラウザはポリシーが明示的に許可していないもの——インラインスクリプト、サードパーティのドメイン、eval() など——の読み込みや実行を拒否します。

ポリシーはディレクティブのリストです。たとえば script-src 'self' は「自分のオリジンから配信されたJavaScriptだけを実行する」という意味であり、object-src 'none' は従来型のプラグインを完全にブロックします。

なぜ重要か

CSPがないと、あらゆるHTMLインジェクションやXSSのバグによって、攻撃者はユーザーのブラウザで任意のJavaScriptを実行できます——セッションの窃取、ページの書き換え、データの持ち出しなどです。

弱いCSPは、ないのとほとんど変わりません。'unsafe-inline' は攻撃者が頼るインラインスクリプトを再び許可してしまい、script-src * のようなワイルドカードのソースはどこからでもスクリプトを読み込めるようにして、目的を台無しにします。

直し方

Next.jsで基本ポリシーを追加する

next.config.js でヘッダーを設定し、すべての応答に適用されるようにします。厳格に始めて、必要な箇所だけ緩めましょう。

// next.config.js
const csp = [
  "default-src 'self'",
  "script-src 'self'",
  "style-src 'self' 'unsafe-inline'",
  "img-src 'self' data:",
  "base-uri 'none'",
  "frame-ancestors 'none'",
  "object-src 'none'",
].join("; ");

module.exports = {
  async headers() {
    return [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: csp }] }];
  },
};
unsafe-inline を nonce に置き換える

インラインスクリプトが必要な場合は、'unsafe-inline' を使う代わりに、リクエストごとの nonce を生成し、script タグとポリシーの両方(script-src 'self' 'nonce-<value>')に追加してください。

強化ディレクティブを必ず設定する

base-uri 'none'、frame-ancestors 'none'、object-src 'none' は、よくある回避手法(baseタグの注入、clickjacking、プラグインの埋め込み)を防ぎ、ほとんどのアプリにとって安全な既定値です。

FAQ

CSPを設定するとサイトが遅くなりますか?

いいえ。CSPはブラウザが評価するだけのヘッダーで、計測できるほどの遅延は生じません。実際のコストは、インラインスクリプトを取り除くための開発作業です。

Content-Security-Policyと X-Frame-Options の違いは何ですか?

X-Frame-Options はフレーム化(clickjacking)だけを制御します。CSPの frame-ancestors ディレクティブはそれを置き換えるもので、CSPはさらにスクリプト、スタイル、画像などもコントロールします。

あなたのアプリは大丈夫ですか?

AppSafeなら、この問題を含む数十項目を1回の無料スキャンでチェックできます。

アプリを無料でスキャン