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.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 を生成し、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はさらにスクリプト、スタイル、画像などもコントロールします。