Content Security Policyは遮断する前にReport-Onlyで読込先を確認する
公開日: 執筆:佐藤
Content Security Policyを既存siteへ入れるときは、最初から外部の読み込みを遮断しないでください。計測、地図、動画、広告などの読込先を把握しないまま制限すると、ページの一部が表示されなくなります。まずContent-Security-Policy-Report-Onlyで違反を記録し、必要な読込先を確かめます。
Content Security Policyは、どのsourceからscript、style、画像などを読み込むかをbrowserへ伝える仕組みです。改ざんや意図しないscriptへの対策を補う手段ですが、入力の検証や更新管理に代わるものではありません。
設定することと遮断することを分ける
Content Security Policy Level 2では、Content-Security-Policy HTTP headerでpolicyを適用すると、browserがそのpolicyを実際に強制します。一方、Content-Security-Policy-Report-Onlyは、policyに反する読み込みを監視して報告しますが、該当するresourceは読み込ませます。
この違いを使うと、既存siteを止めずに必要な読込先を調べられます。たとえば、scriptを自siteだけに限定するpolicyを仮に置いたとき、外部の計測scriptが必要なら違反の報告に現れます。そこで初めて、そのscriptを残すのか、外すのか、読み込み先として許可するのかを決めます。
| 段階 | 行うこと | 表示への影響 |
|---|---|---|
| Report-Only | 仮のpolicyを送信し、違反を記録する | 違反してもresourceは読み込まれる |
| 適用 | 確認したpolicyをContent-Security-Policyで送信する |
policyに反するresourceは読み込まれない |
読込先は機能ごとに記録する
外部domainをまとめて許可する前に、そのdomainが何のために必要かを記録します。site全体で使うものと、一部のページだけで使うものを同じpolicyに入れると、後で不要な許可を外せません。
| 読込先の用途 | 確認する内容 |
|---|---|
| 計測 | 誰が管理し、どのページでscriptを読み込むか |
| 地図と動画 | 埋め込み先のdomainと、表示が必要なページ |
| 画像とfont | 外部配信を続ける理由と、止めた場合の表示 |
| 自siteの資源 | CSS、JavaScript、画像をどのhostから返しているか |
Report-Onlyの報告に出たからといって、すべて許可する必要はありません。使っていないtag、誰が設置したか分からないscript、古い外部部品は、許可する前に削除候補として確認します。違反報告は許可リストを増やすためではなく、siteが何へ依存しているかを知るために使います。
報告にはURLと読込先を対応させる
Report-Onlyを送ると、同じ外部domainでも、どのページの何が読み込もうとしたのかで意味が変わる。トップページのアクセス解析用scriptと、記事末尾に残った使っていない外部部品を、domain名だけで同じ必要な読み込みと判断してはいけない。
報告を確認するときは、違反したdirective、読み込もうとしたURL、報告が出たページを一組で残す。そのうえで、ページの表示と操作を確認する。
| 記録する組み合わせ | 判断すること |
|---|---|
| 違反したページとscriptの読込先 | そのページで本当に必要なscriptか |
| 違反したページと画像の読込先 | 外部配信を続ける必要があるか |
| 違反したページとstyleの読込先 | 表示に必要なstyleか、古い部品か |
| 同じ読込先と設置者 | 誰が削除、更新、許可を判断するか |
この対応が取れないままpolicyへsourceを足すと、何のために許可したか分からない外部domainが残る。外部serviceを変更したときも、誰が影響を受けるかを追えない。Report-Onlyの期間は、単に待つ期間ではなく、読み込みの所有者と用途を整理する期間である。
policyはページ単位の違いも確認する
Content Security Policyは、HTTP応答に付けたresourceへ適用されます。問い合わせform、管理画面、記事、画像一覧のように、読み込む内容が違うページを一件だけ確認しても足りません。
最初は、代表的なページを選びます。トップページ、記事、問い合わせform、外部serviceを埋め込んだページをそれぞれ開き、Report-Onlyの記録と実際の画面を比べます。その後で、共通して必要なsourceだけをpolicyへ残します。
Report-Onlyはmeta要素では使えません。まずserverの設定でHTTP headerを送れるか、誰がその設定を戻せるかを確認してください。制作会社やサーバー管理者へ作業を頼む場合は、policyの文だけでなく、対象URL、報告先、確認者、戻し方を受け取ります。
強制適用へ切り替えるときは、Report-Onlyで確認したpolicyと、実際に適用するpolicyを同じものとして保存する。途中で許可するsourceを増やしたなら、その理由と対象ページを追記する。問題が起きたときに、どのheaderをいつ変えたかが分からなければ、戻す判断もできない。security headerは設定文字列だけを納品物にせず、確認したURLと復旧手順まで運用記録に残す。
最初の一手は、現在読み込んでいる外部scriptを、用途と設置者とともに一覧にすることです。そこにない読込先がReport-Onlyの報告へ出たとき、許可ではなく調査から始めます。
関連記事

