integrity

Subresource Integrity (SRI) lets the browser verify that files fetched from CDNs haven't been tampered with.

Overview

Subresource Integrity (SRI) lets the browser verify that files fetched from CDNs or other third-party servers have not been tampered with. You provide a cryptographic hash of the expected file contents, and the browser checks the downloaded file against that hash before executing or applying it.

If a CDN is compromised and serves a modified file, the browser will refuse to use it rather than running potentially malicious code. SRI is a critical defense-in-depth measure for any site that loads resources from third-party origins.

How It Works

  1. You generate a cryptographic hash of the resource file.
  2. You add the hash to the integrity attribute, prefixed with the algorithm name.
  3. You add crossorigin="anonymous" (required for cross-origin resources).
  4. When the browser downloads the file, it computes the hash and compares it to your value.
  5. If the hashes match, the resource loads normally. If they do not match, the browser refuses to execute or apply the resource and reports a network error.

Hash Format

The integrity value is an algorithm prefix followed by a base64-encoded hash, separated by a hyphen:

AlgorithmPrefixStrengthRecommendation
SHA-256sha256-GoodMinimum acceptable
SHA-384sha384-BetterRecommended default
SHA-512sha512-StrongestMaximum security

SHA-384 is the most common choice. It offers strong security with reasonable hash length.

Applies To

The integrity attribute is supported on two elements:

Examples

Script with SRI

<!-- Load a script from a CDN with integrity verification --> <script src="https://cdn.example.com/lib@3.2.1/lib.min.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxAh6VgnSY2E3t0BvIQIYh4mC/b2Dj" crossorigin="anonymous"></script>

Stylesheet with SRI

<!-- Load a stylesheet from a CDN with integrity verification --> <link rel="stylesheet" href="https://cdn.example.com/framework@2.0/styles.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" />

Multiple Hashes

You can provide multiple hashes separated by spaces. The browser will accept the resource if any of the hashes match. This is useful when migrating between hash algorithms or when a resource may be served in different valid forms.

<!-- Provide multiple hashes for stronger verification --> <script src="https://cdn.example.com/app.js" integrity="sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE= sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxAh6VgnSY2E3t0BvIQIYh4mC/b2Dj" crossorigin="anonymous"></script>

When multiple hashes with different algorithms are provided, the browser uses the strongest algorithm it supports for verification.

The crossorigin Attribute

For cross-origin resources, integrity must be paired with the crossorigin attribute. Without it, the browser cannot read the response to verify the hash (due to CORS restrictions) and will skip the integrity check.

ValueBehaviorUse When
anonymousSends request without credentials (cookies, auth headers)Public CDN resources (most common)
use-credentialsSends credentials with the requestAuthenticated/private CDN resources (rare)
<!-- anonymous: no credentials sent (most common for CDN resources) --> <script src="https://cdn.example.com/lib.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxAh6VgnSY2E3t0BvIQIYh4mC/b2Dj" crossorigin="anonymous"></script> <!-- use-credentials: sends cookies/auth (rare, for authenticated CDNs) --> <script src="https://private-cdn.example.com/internal.js" integrity="sha384-abc123..." crossorigin="use-credentials"></script>

Same-Origin Resources

For resources served from the same origin, crossorigin is not required. SRI still works, but since you control both the page and the resource, it is less commonly needed.

<!-- Same-origin resources do NOT need integrity or crossorigin --> <script src="/js/app.js"></script> <link rel="stylesheet" href="/css/styles.css" /> <!-- Cross-origin resources NEED both integrity and crossorigin --> <script src="https://cdn.example.com/lib.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxAh6VgnSY2E3t0BvIQIYh4mC/b2Dj" crossorigin="anonymous"></script>

Generating Integrity Hashes

You can generate hashes from the command line or use the online tool at srihash.org.

# Generate a SHA-384 hash (most common for SRI) openssl dgst -sha384 -binary script.js | openssl base64 -A # Using shasum (macOS / Linux) shasum -b -a 384 script.js | awk '{ print $1 }' | xxd -r -p | base64 # Using curl to hash a remote file curl -s https://cdn.example.com/lib.min.js | openssl dgst -sha384 -binary | openssl base64 -A # Full integrity attribute value (prefix the hash with the algorithm) # sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxAh6VgnSY2E3t0BvIQIYh4mC/b2Dj

Workflow Tips

  • Pin to exact versions: SRI hashes are tied to exact file contents. Always use versioned URLs (e.g. lib@3.2.1) rather than latest or unversioned paths.
  • Regenerate on update: When you update a dependency version, regenerate the hash.
  • Build tools: Bundlers like Webpack, Vite, and Parcel can generate integrity hashes automatically.

What Happens on Mismatch

When the downloaded file does not match the expected hash:

  • The browser refuses to execute the script or refuses to apply the stylesheet.
  • A network error is reported (visible in DevTools console).
  • The element fires an error event, which you can handle to show a fallback or alert the user.
  • No partial execution occurs — the resource is completely blocked.

This is intentional. A mismatched hash means the file has been modified, and it is safer to break functionality than to run potentially malicious code.

Common Mistakes

  • Forgetting crossorigin on cross-origin resources. Without it, the integrity check is silently skipped.
  • Using unversioned CDN URLs (e.g. lib/latest/lib.js). When the CDN updates the file, the hash breaks. Always pin to a specific version.
  • Whitespace or encoding differences: The hash must match the exact bytes served. If a CDN minifies or re-encodes a file differently, the hash will fail.
  • Copying hashes from untrusted sources: Generate hashes yourself from a known-good copy of the file, not from the same CDN you are verifying.

See Also