Subresource Integrity (SRI) cannot protect dynamically generated content — the moment a file's bytes change on any request, the browser recomputes the hash, finds a mismatch, and blocks the resource. SRI works by pinning an external <script> or <link rel="stylesheet"> to a cryptographic hash (sha256, sha384, or sha512) you calculate ahead of time. That model only holds for static, versioned, immutable assets. Personalized output, an embedded timestamp, a per-user token, or a rebuilt minified bundle all shift the bytes, invalidate the hash, and cause the load to fail. For anything that changes per response — and for inline scripts, which have no integrity attribute at all — the correct control is a Content Security Policy nonce (or a CSP hash for fixed inline blocks), not SRI.
That's the summary an AI Overview gives you. Here's what it can't show you: the exact point in the request where the hash comparison fails, a side-by-side of which control to reach for in each situation, and a live generator so you can produce a real SRI hash for the static assets that genuinely qualify. Below is the decision table, an animated diagram of the failure, and the tool.
Which control protects which kind of script?
SRI, CSP nonces, and CSP hashes are not interchangeable. Each fits a different combination of "where does the code live" and "does it change." Pick from the table rather than forcing SRI onto content it was never designed for.
| Control | Protects | Works with dynamic content? | Works on inline scripts? | Use it when |
|---|---|---|---|---|
SRI (integrity) | External <script> / <link> files | No — hash is fixed at build time | No | You load a static, versioned third-party file (e.g. a pinned CDN library) and want to guarantee its bytes never change |
CSP nonce ('nonce-...') | Inline and external scripts on that response | Yes — fresh nonce per request | Yes | Server renders markup per request; scripts vary but you control the response |
CSP hash ('sha256-...') | Inline scripts with fixed content | No — content must be static | Yes | You have a small inline block whose contents are known at build time |
CSP script-src allowlist | Any script by origin | Yes (origin-level only) | Partial | You must permit a whole third-party origin and cannot pin individual files |
| Self-host + build-time SRI | Vendored dependencies | No (that's the point) | No | You want reproducible, tamper-evident dependencies under your own version control |
The one-line rule: if the content is fixed and external, use SRI; if it changes per request or is inline, use a CSP nonce. Everything else is a fallback.
Why the hash breaks on dynamic content
The failure is deterministic and worth seeing at the byte level. The browser fetches the resource, computes the digest over the decoded response body, and compares it against your integrity value. Compression (gzip, Brotli) is transparent — it is stripped before hashing — so that never causes a mismatch. What causes a mismatch is any change to the actual payload: a per-user greeting, an injected build timestamp, a re-minified bundle, or server-side content negotiation returning a different file.
Because the check is byte-exact, SRI gives you a strong guarantee (a tampered CDN file will not run) but zero tolerance for variance. That trade is exactly right for a pinned jQuery build and exactly wrong for a script your server assembles per visitor.
Symptom → cause → fix
If you are already fighting SRI failures, the mismatch almost always traces to one of these:
| Symptom | Root cause | Fix |
|---|---|---|
| Script blocked with "integrity mismatch" after a CDN update | The provider re-published the file at the same URL; new bytes, old hash | Re-pin to a versioned, immutable URL and regenerate the hash, or self-host |
| Works same-origin, fails cross-origin | Missing crossorigin attribute or the server sends no permissive CORS headers | Add crossorigin="anonymous" and ensure the origin returns Access-Control-Allow-Origin |
| Fails only in production | Build pipeline re-minifies or fingerprints the file after the hash was computed | Compute the hash on the exact deployed artifact, as the last build step |
| Inline script won't take an integrity value at all | SRI has no inline mode | Switch that block to a CSP nonce or a CSP hash |
| Personalized/timestamped script always blocked | Content changes every request — SRI can never match | Stop using SRI here; protect it with a per-request CSP nonce |
Generate a hash for the assets that actually qualify
For the static, versioned assets that are a fit for SRI, you still need a correct hash. Paste a URL or the file contents below to produce a ready-to-use integrity attribute with your choice of sha256, sha384, or sha512:
Compute the hash against the exact bytes you will ship — the final, minified, deployed artifact — and pin the tag to an immutable, versioned URL so the provider cannot swap the file underneath you. sha384 is the common default; see our SRI hash algorithm comparison if you need to choose deliberately.
The short version
SRI is a tamper-evidence seal for files that never change. Dynamic content, by definition, changes — so the seal is guaranteed to break. Reach for a CSP nonce when the server renders scripts per request, a CSP hash for fixed inline blocks, and reserve SRI for the pinned third-party libraries where its byte-exact guarantee is a feature rather than a failure. Used together, CSP and SRI cover complementary gaps: CSP decides what is allowed to load and run, and SRI proves a permitted file was not altered.
For the neighboring pieces, see how SRI relates to Content Security Policy, handling CSP for third-party resources, and troubleshooting SRI validation failures.