Content Security Policy Lv3 (CSP3)でhashにより外部スクリプトを許可する

整理している人
©いらすとや.

前回、Content Security Policy Lv3 (CSP3)でhashによりスクリプトを許可するでインラインスクリプトのハッシュを求めて許可するというのをやったが、そこで少しだけ触れた外部スクリプトをそのまま外部スクリプトとしてハッシュで許可するというのをやってみる。元々は今回nonce(ナンス)を予定していたが思っていたより大変そうなので後回しにした。ごめんなさい。

先に結論だけ書いておきます。ハッシュで外部スクリプトを許可というのはまだとても採用できません。
前回すでに書いていたけど、結局これ。Chromeブラウザでしか使えないのでは話になりません。ハッシュで外部スクリプトを許可したい場合は前回の記事のようにインラインスクリプトから外部スクリプトを読み込むようにしてそのインラインスクリプトを許可してください。

外部スクリプトのハッシュの求め方

インラインスクリプトのハッシュの求め方と大きく違いません。とはいえ、外部スクリプトの内容を読み出す必要があるのでその部分が違います。

https://example.com/dir/script-file.js のハッシュ(sha256)を求める
$ curl --silent "https://example.com/dir/script-file.js" | openssl sha256 -binary | openssl base64
38t2ZdzI/Df3oFOk0g2IWs1/0CwV7NAEnyyMlsdxAVk=      ←求められたハッシュ

CSPヘッダにハッシュを含める (前回と同じ)

CSPヘッダに書くときは、求めたハッシュの前に「sha256-」を付けて「'」で囲む。
'sha256-38t2ZdzI/Df3oFOk0g2IWs1/0CwV7NAEnyyMlsdxAVk='

HTMLヘッダにCSPを書く場合
<meta http-equiv="Content-Security-Policy" content="script-src 'sha256-38t2ZdzI/Df3oFOk0g2IWs1/0CwV7NAEnyyMlsdxAVk=' 'strict-dynamic';">
Nginxの設定でHTTPレスポンスヘッダにCSPを書く場合
add_header Content-Security-Policy "script-src 'sha256-38t2ZdzI/Df3oFOk0g2IWs1/0CwV7NAEnyyMlsdxAVk=' 'strict-dynamic';";

スクリプトタグの変更

インラインスクリプトのハッシュを求めて許可する場合はスクリプトタグはそのまま触らなかったが、外部スクリプトのハッシュを求めて許可する場合は「integrity」を付けて、そこにもハッシュを書く。

HTMLページの中

変更前: <script src="https://example.com/dir/script-file.js"></script>

変更後: <script integrity="sha256-38t2ZdzI/Df3oFOk0g2IWs1/0CwV7NAEnyyMlsdxAVk=" src="https://example.com/dir/script-file.js"></script>

前回のインラインスクリプトをハッシュで許可する場合と僅かな違いはあるものの難しくはありません。ただし、外部スクリプトのURLが変わらないままその中身が変更された場合にはその外部スクリプトがブロックされることになります。許可したいスクリプトが自身の管理であれば変更後にハッシュを再作成してCSPヘッダを更新すればよいのですが、自身の管理でない他所のサイトやCDNにあるようなライブラリなどであれば知らない内にスクリプトが変更されてしまうといつの間にかブロックされていたということがあるかもしれません。(まともなライブラリはバージョン毎にURLが変わるようになっているとは思いますが)

試したのがChromeブラウザ(107.0.5304.62beta)とFirefoxブラウザ(108.0)だけですが、Firefoxではこの外部スクリプトを直接許可というのはまだ機能しませんでした。外部スクリプトをハッシュで許可するというのはCSP Level 3の内容で、CSP3はまだドラフトなので対応してなくても文句は言えません。(2022年12月13日現在)