JavaScript | Web API:パフォーマンス・セキュリティ - CSP(Content Security Policy)

JavaScript JavaScript
スポンサーリンク

CSP は「このページで何をしていいか」をブラウザに教えるルールブック

CSP(Content Security Policy)は、
「このページでは、こういうリソースだけ読み込んでいい/こういうスクリプトだけ実行していい」
とブラウザに約束させる仕組みです。

イメージとしては、
「この部屋では、入っていい人・持ち込んでいい物をリストで決めておく」
そんなセキュリティゲートです。

特に効いてくるのは、XSS などの攻撃に対してです。

スクリプトを埋め込まれても、
「そのスクリプトはポリシー違反だから実行しない」と
ブラウザ側で止められるようになります。


CSP の基本的な指定方法と“最初の一歩”

どこで設定するのか

CSP は、主に次のどちらかで指定します。

HTTP レスポンスヘッダで指定する
Content-Security-Policy: ...

HTML の <meta> タグで指定する
<meta http-equiv="Content-Security-Policy" content="...">

本番サイトでは、基本的に「レスポンスヘッダ」で設定します。
ここではイメージを掴むために、文字列としてどう書くかに集中します。

一番シンプルな例

まずは、超シンプルな CSP から。

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

意味はこうです。

このページで読み込んでいいリソース(スクリプト・画像・CSS など)は
「自分自身のオリジン(ドメイン)」だけに限定する

つまり、

自分のサーバー上の JS / CSS / 画像は OK
CDN や他ドメインからの読み込みは NG

になります。

これだけでも、
「よく分からない外部スクリプトが勝手に読み込まれる」
といった事故をかなり防げます。


スクリプトを絞り込む script-src の考え方

「どこからのスクリプトなら実行していいか」を決める

XSS 対策として特に重要なのが script-src です。

例えば、こう書きます。

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

意味は、

このページで実行していい JavaScript は
「自分のオリジンから配信されたファイルだけ」

ということです。

ここで重要なのは、
インラインスクリプト(<script>... の中身)や、
onclick="..." のような HTML 属性内の JS は、デフォルトで禁止になる

という点です。

つまり、こんな HTML は CSP 違反になります。

<script>
  console.log("インラインスクリプト");
</script>

<button onclick="alert('クリック')">ボタン</button>

CSP 的には、
「HTML の中に直接 JS を書くのは危険だからやめてね」
というメッセージです。

じゃあどう書けばいいのか

CSP をちゃんと効かせる前提では、
「スクリプトは全部 .js ファイルに分離する」 のが基本になります。

<script src="/js/app.js"></script>

そして app.js の中に、
イベントリスナーなどをちゃんと書きます。

document.querySelector("#btn").addEventListener("click", () => {
  alert("クリック");
});
JavaScript

これは、セキュリティだけでなく
コードの整理という意味でも良い習慣です。


インラインスクリプトをどうしても使いたいときの nonce

「このスクリプトだけは特別に許可する」という仕組み

現実のプロジェクトでは、
「どうしてもインラインスクリプトを使いたい」
という場面もあります。

そのときに使えるのが nonce です。

流れはこうです。

サーバーがランダムな文字列(nonce)を生成する
CSP ヘッダに script-src 'self' 'nonce-ランダム文字列' を書く
同じ nonce を <script> タグの属性として付ける

ブラウザは、
「CSP に書かれた nonce と一致するものだけインライン実行を許可」
という動きをします。

例を見てみましょう。

レスポンスヘッダ:

Content-Security-Policy: script-src 'self' 'nonce-abc123';

HTML:

<script nonce="abc123">
  console.log("このインラインスクリプトは許可される");
</script>

この場合、
nonce="abc123" が CSP の 'nonce-abc123' と一致するので、
このインラインスクリプトは実行されます。

逆に、攻撃者が勝手に <script>alert(1)</script> を埋め込んでも、
nonce が付いていないので実行されません。

ここでの重要ポイントは、

nonce は毎回ランダムに変える(固定値にしない)
サーバー側で生成して、ヘッダと HTML の両方に埋め込む

ということです。


レポートモードで「まずは壊さずに様子を見る」

いきなり本番でガチガチにすると、普通の機能も壊れる

CSP をいきなり厳しくすると、
「自分のサイトの正しい機能」まで壊してしまうことがあります。

例えば、

CDN から読み込んでいるライブラリがブロックされる
インラインで書いていた小さなスクリプトが動かなくなる

などです。

そこで便利なのが、
レポート専用モード です。

Content-Security-Policy の代わりに
Content-Security-Policy-Report-Only を使うと、
「違反はログに出すけど、実際にはブロックしない」
という動きになります。

例:

Content-Security-Policy-Report-Only: default-src 'self';

これを設定しておくと、

本来ならブロックされる外部リソース
インラインスクリプト

などがあったときに、
ブラウザのコンソールに警告が出ます。

これを見ながら、

どのリソースを許可する必要があるか
どのインラインスクリプトを修正すべきか

を洗い出していき、
準備が整ったら本番の Content-Security-Policy に切り替える、
という流れが安全です。


よく使うディレクティブのざっくりイメージ

default-src と個別の *-src

CSP にはいろいろな「〜src」がありますが、
初心者のうちは次だけ覚えておけば十分です。

default-src
何も指定されていない種類のリソースのデフォルトルール

script-src
スクリプト(JavaScript)の読み込み・実行ルール

style-src
CSS の読み込みルール

img-src
画像の読み込みルール

例えば、こう書くとします。

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

意味はこうです。

基本は全部 ‘self’(自分のオリジン)だけ
スクリプトだけは、自分+cdn.example.com を許可
画像だけは、自分+images.example.com を許可

という感じで、
「種類ごとに、どこから読み込んでいいかを細かく決められる」
のが CSP の強さです。


初心者として CSP でまず掴んでほしいこと

CSP は、仕様を全部覚える必要はありません。
まずは「考え方」と「最初の一歩」だけで十分です。

この感覚を持っておいてください。

CSP は「このページで何をしていいか」をブラウザに宣言するルールブック
default-src 'self' で「基本は自分のサーバーだけ」をベースにする
script-src で「どのスクリプトを実行していいか」を絞る(XSS 対策の要)
インラインスクリプトは禁止が基本。どうしても必要なら nonce で「この一個だけ特別に許可」
いきなり本番で厳しくせず、まずは Content-Security-Policy-Report-Only で様子を見る

CSP は、
「コードの書き方」だけでは防ぎきれない攻撃を、
ブラウザ側のルールで一段ガードしてくれる仕組みです。

あなたがセキュリティを考えるときに、
「コードだけじゃなくて、ブラウザにルールを課すという手もある」
と発想できるようになったら、
それだけでエンジニアとしての視界が一段広がっています。

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