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.

3 minread 621words last updated

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

StepWhat happens
At build timeA cryptographic hash of the exact file you tested is computed and placed in the tag’s integrity attribute
At load timeThe browser downloads the file and computes its hash
MatchThe script runs as normal
MismatchThe script is blocked, an error is logged, nothing from it executes

Where it applies, and where it cannot

  1. Pinned library versions from a CDN: a specific version of a specific file, which never changes. Integrity fits perfectly.
  2. Fonts and stylesheets from third parties, when pinned. Same rule.
  3. Self-hosted files: still worth adding for defence against tampering in transit or on an edge cache.
  4. 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.

Written by the CivSec S.M.A.R.T team

We build and run websites, software and AI systems for businesses. We write about what we see in that work, in plain language, and we update articles when things change.

Last checked . Spotted something outdated? Tell us.

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

  1. MDN: Subresource Integrity (accessed 2026-09-11)