Featured image of post Subresource Integrity: Protecting Your CDN Dependencies Featured image of post Subresource Integrity: Protecting Your CDN Dependencies

Subresource Integrity: Protecting Your CDN Dependencies

Complete guide to Subresource Integrity (SRI) for web security: hash generation, crossorigin config, build-time integration, CSP correlation, and monitoring.

Subresource Integrity (SRI) is a security feature that lets browsers verify that resources fetched from CDNs or third-party origins have not been tampered with. In an era of supply chain attacks — the British Airways Magecart breach, the Polyfill.io compromise, and numerous CDN incidents — SRI provides cryptographic assurance that the resource your page loads is exactly what you intended.

How SRI Works

When you add an integrity attribute to a <script> or <link rel="stylesheet"> tag, the browser computes the hash of the fetched resource and compares it to the attribute value. If they don’t match, the browser refuses to execute or apply the resource.

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

Multiple hashes (comma-separated) allow graceful fallback when multiple versions of a resource are acceptable:

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

The crossorigin="anonymous" attribute is required for SRI on cross-origin resources. Without proper CORS headers, the browser loads the resource in opaque mode and cannot verify its integrity — the resource is silently ignored with no error.


Generating SRI Hashes

You can generate SRI hashes using OpenSSL, online tools, or build-time plugins:

# OpenSSL command
openssl dgst -sha384 -binary file.js | openssl base64 -A

For automation, integrate SRI generation into your build pipeline. Build tool support is mature:

ToolPlugin / Config
webpackwebpack-subresource-integrity
Vitevite-plugin-sri or built-in via experimental.renderBuiltUrl
Next.jsexperimental.sri in next.config.js
AstroBuilt-in integrity prop on asset components
// Next.js SRI configuration
// next.config.js
module.exports = {
  experimental: {
    sri: {
      hash: "sha384",
    },
  },
};

Ensure hashes are computed after minification and source map generation — the hash must match the final served content, not the development source.


SRI and CSP Correlation

Content Security Policy and SRI complement each other. CSP restricts which origins can load resources; SRI ensures resources from allowed origins have not been modified. Combined, they provide defense-in-depth for third-party resource loading.

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

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

Use CSP’s report-uri or report-to directives to monitor SRI violations. A mismatched hash may indicate CDN compromise, a build pipeline issue, or content transformation by middleware.


Monitoring SRI Violations and Advanced Patterns

Listen for error events on elements with integrity attributes, or use the Reporting API to collect SRI violation reports from browsers:

// Client-side SRI violation monitoring
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(),
      }),
    });
  });
});

CDN providers differ in SRI support. Verify your CDN’s capabilities:

CDNSRI SupportNotes
cdnjsFullHashes provided for all libraries
jsDelivrFullHashes in package API responses
UNPKGVia ?metaHash available via query parameter
Google Hosted LibrariesPartialOnly for supported libraries

Advanced SRI patterns include dynamic verification for scripts loaded after user interaction, SRI for web workers (new Worker("script.js", { integrity: "..." })), and integrity on import map entries for ES module sharding.

// Dynamic SRI verification for runtime-loaded scripts
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");
  }
  // Execute the script safely
  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);
}

Implement a fallback strategy: load from the primary CDN with SRI, and fall back to a self-hosted copy if integrity verification fails. This ensures your application remains functional even if a CDN is compromised or changes its content.

SRI is a critical security control that is simple to implement: generate a hash, add the integrity attribute, configure CORS headers, and automate hash generation in CI. Combined with CSP, it provides robust protection for third-party resource loading. Add SRI to all external resources, automate the process, and monitor for failures proactively.