【実務・中級編】CSP Level 3のstrict-dynamicによる柔軟なスクリプト管理 – アプリケーションセキュリティ & 安全な開発防御ガイド

CSP Level 3の「strict-dynamic」で、フロントエンドの悪夢を終わらせる

現場でセキュリティを語る時、一番の敵は「利便性と安全性の間の妥協」だ。
「このライブラリを動かすために、

これに対し、strict-dynamic と nonce(使い捨てトークン)を組み合わせれば、攻撃者がいかに巧妙なスクリプトを注入しようとも、HTMLの中に「正しいnonce」が含まれていない限り、ブラウザは一切の実行を拒否する。

---

実装:コピペで動くセキュアな構成

実務では、Nginx側のヘッダー設定と、サーバーサイドでのNonce生成がセットになる。

1. Nginx設定(セキュリティヘッダー)

まずは、CSPヘッダーを厳格に定義する。'unsafe-inline' は nonce があれば無視される仕組みを利用する。

Nginxの設定例
'strict-dynamic' を指定することで、信頼されたスクリプトからの動的ロードを許可
'nonce-...' は動的に生成するため、ここではプレースホルダーとして扱う
add_header Content-Security-Policy "default-src 'self'; script-src 'nonce-RANDOM_NONCE' 'strict-dynamic'; object-src 'none'; base-uri 'self';" always;

2. バックエンド(PHP)でのNonce生成

リクエストごとに一意の文字列を生成し、テンプレートとヘッダーの両方に渡す。

console.log('このスクリプトは実行されます'); // ここで動的に読み込まれるライブラリも自動的に信頼される ";
?>

---

プロフェッショナルとしての注意点

この設計を採用する際、一つだけ絶対に忘れてはならないことがある。「古いブラウザの挙動」だ。

strict-dynamic は CSP Level 3 の仕様であり、古いブラウザ(IEなど)はこれを無視して、従来のドメイン・ホワイトリストを優先する。そのため、堅牢性を担保するには「フォールバック」の設定が必須だ。

推奨設定例
script-src 'nonce-RANDOM' 'strict-dynamic' 'self' https:;

このように、'self' や https: を並記しておくことで、最新ブラウザでは strict-dynamic が効き、古いブラウザでは従来のドメイン制約が働く多層防御の形になる。

まとめ:泥臭い検証の先にある安心

セキュリティは「設定して終わり」ではない。
strict-dynamic を導入すると、これまで動いていたサードパーティ製プラグインが突然動かなくなることがある。それは「これまで脆弱性を放置していた」という事実を突きつけられた瞬間だ。

その時、「動かなくなったから設定を戻そう」と妥協するのか、あるいは「なぜそのスクリプトは信頼できないドメインから読み込まれているのか?」と精査するのか。この姿勢の差が、インシデントに強い組織と、いつか事故を起こす組織の分かれ道になる。

コードはシンプルに、防御は徹底的に。それがプロの仕事だ。

コメント

タイトルとURLをコピーしました