What is Subresource Integrity, and why does that third-party script need it?
Open the page source and look at the <script> tags in your <head>. The ones pointing at a CDN: jQuery from a public CDN, an analytics snippet, a chat widget, a font loader. Each of those tags is an instruction to your visitors' browsers that says "go fetch this file from someone else's server and run it as me."
Now suppose that someone else's server starts serving a different file tomorrow. Same URL, new bytes. Does anything in your page stop it from running?
For most sites, nothing does. The browser fetches whatever lives at that URL and executes it with full access to your page. Same URL, different bytes, no check. That's the gap Subresource Integrity closes, and it's a one-attribute fix that a lot of sites still don't have.
What SRI actually is
Subresource Integrity is a cryptographic fingerprint you pin to a script or stylesheet tag. You compute a hash of the exact file you trust, put it in an integrity attribute, and the browser refuses to run the file unless its bytes hash to that exact value.
<script
src="https://cdn.example.com/widget.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
The integrity value is the hash of the file you verified. The crossorigin="anonymous" part is required for the browser to read a cross-origin file's bytes well enough to check them. Get the file the browser expects, it runs. Get anything else, even one byte different, the browser blocks it and logs an error. The CDN can't sneak a changed file past the hash, because the whole point of a cryptographic hash is that you can't quietly produce different bytes with the same fingerprint.
integrity="sha384-oqVu…3kHd"
crossorigin="anonymous">
Why the missing attribute is the actual hole
Without integrity, you've extended full trust to every server in your script's delivery path, permanently, with no verification. That's a bigger surface than people realize.
A script loaded from a CDN runs in your origin. It can read the DOM, read non-HttpOnly cookies, see what users type, rewrite the page, and make requests as the logged-in user. It is, for all security purposes, your own code. The only difference is you don't control the file. Someone else does.
So picture the bytes at that URL changing. Maybe the CDN account gets compromised. Maybe a popular open-source package the CDN serves gets a malicious release pushed to it, which has happened repeatedly to the npm ecosystem. Maybe DNS for the CDN gets hijacked and your visitors get pointed at an attacker's copy. In every case the URL in your tag is unchanged, your HTML is unchanged, and your visitors quietly start running attacker code that has your page's full trust. You find out when someone reports a fake payment form or you notice card-skimming traffic, which is the form these attacks usually take. This pattern, hostile JavaScript injected through a trusted third-party script, is exactly what SRI is built to stop, and it's why an outdated library makes a worse target when it also lacks integrity. If you're still on an old jQuery build with a known XSS hole, you've got both problems on one tag.
The honest limits
SRI is precise, which also means it's narrow. Worth being clear about what it does not do.
It pins one exact file. If you point a tag at a "latest" URL that the CDN updates on purpose, SRI and that URL fight each other, because every legitimate update breaks the hash. So SRI goes on version-pinned URLs, not floating ones. It also doesn't help if the script was already malicious when you added it and hashed it. The hash locks in whatever you trusted at pin time. And it covers scripts and stylesheets. Images and fonts loaded other ways are out of scope. SRI is a tamper check on specific files, not a content-security policy on its own, so it won't restrict what loads or where requests go. Pair it with a real Content Security Policy for the broader control, and SRI stays the piece that verifies this exact third-party file and rejects everything else.
How to add it
For each cross-origin script and stylesheet, generate the hash and pin it. From the command line:
curl -s https://cdn.example.com/widget.min.js \
| openssl dgst -sha384 -binary \
| openssl base64 -A
Prefix the output with sha384- and drop it into the tag, then add crossorigin="anonymous". Many CDNs publish the SRI hash next to their snippet already, so you can often copy it rather than compute it. Toggle the difference here:
<script src="https://cdn.example.com/widget.min.js"></script>
Two cautions. Pin a versioned URL, not a "latest" one, or the next legitimate update will get blocked. And when you intentionally update the file, regenerate the hash, because a stale integrity value will block the new good file just as firmly as a bad one. That's the system working.
Which of your tags run on blind trust is already sitting in the HTML you serve to everyone. SurfaceCheckr fetches your pages, lists every cross-origin script and stylesheet, and flags the ones loading without an integrity attribute. That's the same enumeration an attacker does when they're deciding whether your supply chain is worth poking, and we run it from the outside in a couple of minutes without touching anything you host. What we can't tell you is whether the third party's code is doing something hostile once it runs. That part we don't see, and we won't pretend otherwise. What we will hand you is the list of third-party tags that load unverified and where each one comes from, which for most people is a list they've never actually looked at.
Find it before someone else does.
Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.