Subresource Integrity is one of those browser features that quietly closes a hole most teams don’t even know is open – the moment a page pulls in a script from someone else’s server. If your site loads a font library, an analytics tag, a payment widget, or a UI framework from a CDN, you’re trusting that CDN’s infrastructure just as much as your own, and Subresource Integrity (SRI) is the mechanism that lets the browser catch it when that trust is broken.
What Subresource Integrity Actually Does
SRI works by attaching a cryptographic hash to a script or stylesheet tag. When the browser fetches the file, it computes the hash of what it actually downloaded and compares it against the hash you specified in the integrity attribute. If they don’t match, the browser refuses to execute the file. No warning banner, no silent fallback – it just won’t run.
That’s the entire mechanism. It’s simple, it’s built into every modern browser, and it costs nothing to implement beyond generating a hash once and pasting it into your HTML.
A Scenario That Plays Out More Often Than People Assume
A marketing site loads a carousel library from a public CDN. Six months later, that CDN account gets compromised – maybe through a stolen API key, maybe through a dependency in the CDN provider’s own build pipeline – and the file at that URL is quietly swapped for a version that skims form fields and sends them to an external domain.
Nothing changes on the website’s own server. No deployment happened. The site owner’s logs show nothing unusual because the request to the CDN succeeds exactly as before – it’s just serving different bytes now. Without SRI, the browser has no way to know the file it just executed isn’t the one the developer originally approved. This is the same underlying risk covered in supply chain attacks through compromised dependencies, and third-party script tags are one of the most common delivery paths for it.
Busting the “HTTPS Is Enough” Myth
A surprisingly common assumption is that loading a script over HTTPS already protects against this kind of tampering. It doesn’t. HTTPS secures the connection between the browser and the server – it stops someone from intercepting the request on the network and swapping the file in transit. It does nothing to verify that the file sitting on the origin server is the one you originally intended to load.
If the CDN itself is compromised, or an attacker gains write access to the storage bucket serving the script, HTTPS will faithfully deliver the malicious file with a valid padlock icon and everything. SRI is the only piece that checks the content itself, not just the pipe it travels through.
How to Add Subresource Integrity to Your Scripts
The process is mechanical once you understand it:
1. Download the exact version of the script you intend to use.
2. Generate a SHA-384 (or SHA-256/SHA-512) hash of the file. Most CDNs that support SRI, like cdnjs or jsDelivr, already publish the hash next to the copy-paste snippet.
3. Add the integrity attribute to the script or link tag, along with crossorigin=”anonymous”.
4. Test that the resource still loads – a mismatched hash will silently block execution, which can look like an unrelated bug if you’re not watching the console.
A typical tag looks like this in practice:
The crossorigin attribute matters more than people realize – without it, the browser won’t send the necessary CORS headers to validate the hash on a cross-origin request, and the integrity check effectively gets skipped.
Where SRI Falls Short
SRI isn’t a universal fix, and it’s worth being honest about its limits:
It only works for static files with predictable content. Scripts loaded dynamically with content that changes per request – personalization scripts, A/B testing tags, some analytics loaders – can’t use a fixed hash, since the hash would break the moment the file legitimately updates.
It requires discipline to maintain. Every time the third-party vendor ships a new version, the hash has to be updated too, or the resource stops loading entirely. Teams that set SRI once and forget about it often end up with either stale, unpatched dependencies or scripts that silently fail months later after an unrelated vendor update.
It doesn’t cover resources loaded by other scripts. If a script you’ve protected with SRI then reaches out and loads a second script dynamically, that second one isn’t covered unless it also has integrity attributes – and dynamically injected script tags often don’t get one.
Pairing SRI With the Rest of Your Script Policy
SRI works best as one layer among several, not a standalone control. A well-configured Content Security Policy restricts which origins can serve scripts in the first place, which narrows the attack surface SRI then protects within. Details on getting that configuration right without breaking legitimate functionality are covered in how to implement Content Security Policy correctly.
It’s also worth treating every third-party script the same way you’d treat any other dependency in your stack – tracked, version-pinned, and reviewed periodically rather than added once during a sprint and forgotten. The risks specific to relying on external JavaScript are broken down further in the security impact of third-party JavaScript libraries.
A recurring mistake worth flagging: teams add SRI to their main vendor bundle but skip smaller widgets – chat plugins, review embeds, cookie consent banners – because they seem lower risk. In practice, these smaller third-party scripts often have looser security practices on the vendor side and are just as capable of running arbitrary JavaScript in the page context as a major library would be.
Frequently Asked Questions
Does Subresource Integrity slow down page load?
No. Hash verification happens as part of the normal fetch process and adds negligible overhead – far less than the time already spent downloading the file itself.
Can SRI be used for self-hosted scripts, or only third-party ones?
It can be used anywhere, including self-hosted files, but the practical value is much lower there since you already control the origin server. It’s primarily useful when you don’t control the infrastructure serving the file.
What happens to the page if the hash doesn’t match?
The browser blocks the resource from executing and logs an error in the console, but the rest of the page continues to load normally. This is why it’s important to monitor for these errors – a silently blocked script can break functionality without an obvious visible cause.
Subresource Integrity won’t stop every third-party risk on its own, but it closes a specific and often-overlooked gap: the assumption that a script loaded today is the same script that will load tomorrow. Pin the hash, keep it updated alongside the vendor’s releases, and treat every external script tag as a dependency worth tracking rather than a line of HTML you paste once and forget.
