Featured image of post Subresource Integrity:CDN依存関係を保護する Featured image of post Subresource Integrity:CDN依存関係を保護する

Subresource Integrity:CDN依存関係を保護する

Subresource Integrity(SRI)の完全ガイド:ハッシュ生成、crossorigin設定、ビルド時統合、CSP連携、違反監視によるCDN依存関係のセキュリティ保護。

Subresource Integrity(SRI)は、ブラウザがCDNやサードパーティオリジンから取得したリソースの改ざんを検証するセキュリティ機能です。British AirwaysのMagecart侵害、Polyfill.ioのサプライチェーン侵害など、サプライチェーン攻撃が増加する現代において、SRIは読み込んだリソースが開発者の意図したものであることを暗号学的に保証します。

SRIの仕組み

<script><link rel="stylesheet">タグにintegrity属性を追加すると、ブラウザは取得したリソースのハッシュを計算し、属性値と比較します。一致しない場合、ブラウザはリソースの実行や適用を拒否します。

<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

複数のハッシュをカンマ区切りで指定すると、複数バージョンが許容される場合のグレースフルフォールバックが可能です:

<script
  src="https://cdn.example.com/app.js"
  integrity="sha384-ABC... sha512-XYZ..."
  crossorigin="anonymous"
></script>

クロスオリジンリソースにSRIを適用するには、crossorigin="anonymous"属性が必須です。適切なCORSヘッダーがない場合、ブラウザはリソースをopaqueモードで読み込み、整合性を検証できません。この場合、リソースはエラーなしで静かに無視されます。


SRIハッシュの生成

SRIハッシュはOpenSSL、オンラインツール、ビルド時プラグインで生成できます:

openssl dgst -sha384 -binary file.js | openssl base64 -A

自動化のためには、ビルドパイプラインにSRI生成を統合します。各ツールの対応状況は以下の通りです:

ツールプラグイン / 設定
webpackwebpack-subresource-integrity
Vitevite-plugin-sri または experimental.renderBuiltUrl
Next.jsnext.config.jsexperimental.sri
Astroアセットコンポーネントのビルトイン integrity プロップ
// Next.js SRI設定
// next.config.js
module.exports = {
  experimental: {
    sri: {
      hash: "sha384",
    },
  },
};

ハッシュはミニファイ後かつソースマップ生成後に計算します。ハッシュは最終的に配信されるコンテンツと一致する必要があり、開発用ソースとは異なります。


CSPとの連携と違反監視

Content Security PolicyとSRIは補完関係にあります。CSPはリソースの読み込み元を制限し、SRIは許可されたオリジンから読み込んだリソースの改ざんを検証します。

<!-- CSPヘッダー -->
Content-Security-Policy:
  script-src https://cdn.example.com 'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC';
  report-uri https://reporting.example.com/csp-violations

<!-- SRI付きHTML -->
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

CSPのreport-urireport-toディレクティブでSRI違反を監視します。ハッシュの不一致はCDN侵害、ビルドパイプラインの問題、ミドルウェアによるコンテンツ変換を示す可能性があります。

// クライアント側SRI違反監視
document.querySelectorAll("script[integrity]").forEach((el) => {
  el.addEventListener("error", (event) => {
    fetch("/api/sri-violation", {
      method: "POST",
      body: JSON.stringify({
        src: el.src,
        integrity: el.getAttribute("integrity"),
        timestamp: new Date().toISOString(),
      }),
    });
  });
});

高度なSRIパターン

動的に読み込まれるスクリプトのランタイム検証、Web WorkerのSRI、Import Mapでの整合性チェックなど、高度なパターンも重要です:

// 動的SRI検証
async function loadWithIntegrity(url, integrity) {
  const response = await fetch(url);
  const buffer = await response.arrayBuffer();
  const hash = await crypto.subtle.digest("SHA-384", buffer);
  const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));
  if (base64 !== integrity.replace("sha384-", "")) {
    throw new Error("Integrity check failed");
  }
  const blob = new Blob([buffer], { type: "text/javascript" });
  const blobUrl = URL.createObjectURL(blob);
  const script = document.createElement("script");
  script.src = blobUrl;
  document.body.appendChild(script);
}

フォールバック戦略も重要です。プライマリCDNからSRI付きで読み込み、検証に失敗した場合はセルフホストコピーにフォールバックします。これにより、CDNが侵害されたりコンテンツが変更されたりしてもアプリケーションの機能を維持できます。

SRIはシンプルに実装できる重要なセキュリティ制御です。ハッシュを生成し、integrity属性を追加し、CORSヘッダーを設定し、CIでハッシュ生成を自動化します。CSPと組み合わせることで、サードパーティリソース読み込みに対する堅牢な保護を提供します。全ての外部リソースにSRIを追加し、プロセスを自動化し、障害をプロアクティブに監視しましょう。