Subresource integrity: making sure third-party scripts are what they claim
When a page loads a script from another server, visitors run whatever it sends. Subresource integrity lets the browser refuse anything changed.
The short answer
When your page includes a script from someone else’s server, a library from a CDN, a widget, a tag, your visitors’ browsers download and run whatever that server sends, with full access to the page. If that server is compromised or the file is changed, your visitors run the new code and your site is the one that appears to have attacked them. Subresource integrity is a browser feature that closes this gap for files that should never change: you attach a fingerprint of the expected file to the tag, and the browser refuses to run anything that does not match. It costs nothing and it belongs on every pinned third-party file.
How it works
| Step | What happens |
|---|---|
| At build time | A cryptographic hash of the exact file you tested is computed and placed in the tag’s integrity attribute |
| At load time | The browser downloads the file and computes its hash |
| Match | The script runs as normal |
| Mismatch | The script is blocked, an error is logged, nothing from it executes |
Where it applies, and where it cannot
- Pinned library versions from a CDN: a specific version of a specific file, which never changes. Integrity fits perfectly.
- Fonts and stylesheets from third parties, when pinned. Same rule.
- Self-hosted files: still worth adding for defence against tampering in transit or on an edge cache.
- Vendor scripts that update themselves, such as analytics, tag managers, chat widgets and ad scripts: integrity cannot be used, because the file changes without notice. That is the honest signal that these scripts are a trust decision.
The wider pattern
Integrity is one layer of a short list for third-party code. Load as little third-party code as possible; bundle and self-host libraries through the build step, which is the default on a modern static site. Pin versions and add integrity to anything still loaded externally. Restrict what any script can do with a content security policy. Review the list of third parties quarterly and remove what is no longer needed. The fewer scripts you load from elsewhere, the fewer trust decisions you are making on your visitors’ behalf.
What this means for you
Every external script is code you did not write running on your visitors’ machines under your name. Bundle and self-host what you can, pin and fingerprint what you load externally, restrict everything with a content security policy, and keep the self-updating vendor scripts to the few you genuinely need. Integrity is the free, mechanical part of that discipline, and there is no reason for a pinned file to be without it.
Frequently asked questions
Can we use integrity checks on our analytics or chat widget?
Usually not, because those vendors change the script whenever they like and an integrity check would break it. That is a real limitation and a real signal: a script that can change under you at any time is a trust decision, not a technical one. Keep the list of such scripts short, load them from vendors you would trust with your page, and restrict what they can do with a content security policy.
Does self-hosting a library make integrity checks unnecessary?
Self-hosting removes the third-party server from the equation, which is the larger benefit. Integrity attributes still add protection against tampering in transit or on a compromised CDN edge, and they cost nothing to add for files that do not change. On a static site with a build step, most libraries are bundled and self-hosted anyway.
What happens to visitors if the check fails?
The browser does not run the script and logs an error. Whatever that script did on the page does not happen. For a library your page depends on, that is a visible break, which is the point: a silent substitution would be far worse. Monitoring picks up the error, and the fix is to verify why the file changed.
Sources
- MDN: Subresource Integrity (accessed 2026-09-11)