導入
Web開発において、外部から読み込むスクリプトやスタイルシートが「本当に改ざんされていないか」を保証することは極めて重要です。もしCDN上のファイルが攻撃者に書き換えられていたら、あなたのサイトのユーザーに悪意あるコードが実行されてしまうかもしれません。そこで役立つのが、ブラウザ標準機能である「Subresource Integrity (SRI)」と、それをプログラムから制御できる Request.prototype.integrity プロパティです。
基礎知識
Subresource Integrity (SRI) とは、読み込むリソースに対して「ハッシュ値」を付与し、ブラウザがダウンロードしたファイルのハッシュ値と照合することで、ファイルの整合性を検証する仕組みです。
Request.prototype.integrity は、Fetch APIを使用してリクエストを行う際、そのリクエストに関連付けられたSRIのハッシュ文字列を保持・取得するためのプロパティです。これを利用することで、JavaScriptから動的にリソースを取得する際にも、厳格なセキュリティチェックを適用できます。
実装/解決策
Fetch APIでリソースを取得する際、Requestオブジェクトの初期化オプションとして `integrity` プロパティを指定します。ブラウザはリクエスト時にこのハッシュ値を参照し、ダウンロードしたコンテンツが一致しない場合にリクエストを拒否(エラー)します。
具体的な手順は以下の通りです。
1. 対象ファイルのハッシュ値を計算する(オンラインツールやopensslコマンドを使用)。
2. `new Request()` のオプションに `integrity` キーでハッシュ文字列を渡す。
3. `fetch()` を実行し、整合性が保証されたデータのみを取得する。
サンプルプログラム
以下のコードは、特定のスクリプトファイルを安全に取得するための実装例です。
// 取得したいリソースのURL
const url = 'https://example.com/script.js';
// 事前に計算したSRIハッシュ値(sha384形式が推奨)
const expectedIntegrity = 'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC';
// Requestオブジェクトを生成し、integrityオプションを設定
const request = new Request(url, {
method: 'GET',
// ここで整合性を定義します
integrity: expectedIntegrity,
// キャッシュを避け、毎回検証を行う場合は設定
cache: 'no-cache'
});
// fetchを実行
fetch(request)
.then(response => {
if (!response.ok) throw new Error('ネットワークエラー');
return response.blob();
})
.then(blob => {
console.log('整合性が確認されました。安全なリソースです。');
})
.catch(err => {
// ハッシュ値が一致しない場合、ここでエラーがキャッチされます
console.error('セキュリティエラー: リソースが改ざんされている可能性があります', err);
});
応用・注意点
現場で活用する際の重要な注意点がいくつかあります。
・CORSの必要性: SRIによる検証を行う場合、リソースを配信するサーバー側で CORS (Cross-Origin Resource Sharing) が有効になっている必要があります。そうでない場合、セキュリティ上の理由でブラウザが検証をブロックすることがあります。
・ハッシュの更新漏れ: ファイルの内容を更新した際は、必ず新しいハッシュ値を再計算してコードに反映させる必要があります。これを忘れると、正規のアップデートであっても「改ざん」とみなされ、サイトが機能しなくなります。
・デバッグ時の挙動: 開発中にローカル環境でハッシュ値がずれるとエラーで止まるため、開発モードと本番モードでintegrityの適用を切り替える構成にするとスムーズです。
この機能を適切に使うことで、サードパーティ製ライブラリの読み込みリスクを大幅に低減できます。ぜひ今日から導入を検討してみてください。