Back to Glossary
medium severity · Vulnerability Glossary

Missing Subresource Integrity (SRI)

Updated August 8, 2026

4 min read

subresource integrity
sri hash
integrity attribute
sri crossorigin
supply chain attack
magecart
cdn compromise
require-sri-for

Missing Subresource Integrity (SRI) is when your page loads an external script or stylesheet from a third-party CDN without an integrity hash, so the browser can't verify it's the file you expect. You detect it by finding external tags with no integrity attribute, and fix it by adding a sha384-... hash plus crossorigin="anonymous" to each.

What is Missing Subresource Integrity (SRI)?

Subresource Integrity (SRI) pins the exact contents of an external resource. You add an integrity attribute holding a cryptographic hash (usually SHA-384) of the file you expect; when the browser downloads that script or stylesheet, it hashes the received bytes and compares them to your value. If they don't match, it refuses to run the resource.

The finding "missing SRI" is the opposite: your page pulls a script or stylesheet from an origin you don't control — a public CDN, an analytics or widget vendor — with no integrity attribute, so the browser runs whatever bytes that host returns. It's common, because most CDN snippets omit the hash and the page still works.

This maps to OWASP A08:2021 – Software and Data Integrity Failures, the category for code and dependencies loaded without integrity verification. SRI is the browser-side control that closes that gap for front-end assets.

Why it's a risk / how it's exploited

You're trusting a third party never to be compromised. An external script runs in your origin with your own code's privileges — it can read the DOM, JavaScript-accessible cookies, form fields, and anything a user types — so if the CDN or its domain is hijacked, the attacker's code runs on your site and users can't tell. This is the supply-chain / Magecart card-skimming pattern seen in the 2018 British Airways and Ticketmaster breaches and the 2024 polyfill.io incident, where a hijacked, unversioned third-party script served malicious code to more than 100,000 sites.

Concrete scenario: your checkout page loads a helper script from cdn.example.com with no hash. Someone compromises that CDN and swaps in a card-skimming version — your server, TLS, and code are untouched, yet every customer's card details flow to the attacker. With SRI, the altered bytes wouldn't match the pinned hash and the browser refuses to run the file.

Severity is medium, not critical: the attack needs the third party to actually be compromised, so it's a latent risk rather than a live hole in your own code. But when it triggers the impact is severe and silent, so it's worth closing on high-value pages.

How to detect it

Inspect your HTML for external <script> and <link> tags and check each for an integrity attribute — via view-source, the DevTools Elements panel, or the command line:

curl -s https://example.com | grep -Eo '<(script|link)[^>]+(src|href)="https?://[^"]+"[^>]*>'

A vulnerable tag loads from another host with no hash:

<script src="https://cdn.example.com/lib@1.2.3/dist/lib.min.js"></script>

A safe tag pins the contents and sets crossorigin:

<script src="https://cdn.example.com/lib@1.2.3/dist/lib.min.js"
        integrity="sha384-Pc2H9pL1DLwP1dxz875YR+3wD+6aMcht0eLqwf3rUXB5wK2WzJODfq2lcH+ryVLD"
        crossorigin="anonymous"></script>

Any external src/href with no integrity attribute is the finding. Auditing every asset by hand gets impractical — an automated website vulnerability scan flags scripts and stylesheets loaded without SRI. See how to scan a website for vulnerabilities, or map it against your full OWASP Top 10.

How to fix it

Add both integrity and crossorigin="anonymous" to every external script and stylesheet. The crossorigin attribute is required so the browser fetches the file in CORS mode and can read the bytes to verify the hash.

Generate the hash from the exact file you're pinning:

curl -s https://cdn.example.com/lib@1.2.3/dist/lib.min.js \
  | openssl dgst -sha384 -binary \
  | openssl base64 -A

Paste the output into the tag, prefixed with the algorithm:

<link rel="stylesheet"
      href="https://cdn.example.com/app@2.4.0/app.min.css"
      integrity="sha384-<paste-base64-here>"
      crossorigin="anonymous">

Two caveats matter:

  • Pin a stable, versioned file. SRI only works if the bytes never change. Point at a specific version (lib@1.2.3), never an unversioned "latest" URL — when the file updates, the hash won't match and the browser blocks it. Regenerate the hash whenever you upgrade.
  • Self-hosting is often cleaner. Serving the asset from your own origin removes the third-party trust entirely and resolves any mixed-content issue if the CDN was reachable over HTTP. You keep control of versioning and no longer depend on someone else's host.

As a backstop, a Content-Security-Policy directive can demand SRI on every script and style:

add_header Content-Security-Policy "require-sri-for script style" always;

Treat this as theory only — require-sri-for was experimental and no current browser enforces it, so the per-tag integrity attributes remain what actually protects users.

FAQ

The CDN uses HTTPS — isn't that enough? No. HTTPS protects the file in transit but does nothing if the CDN itself is compromised and serves a malicious file over that encrypted connection. TLS verifies the transport; SRI verifies the contents — you need both.

Won't SRI break my site when the CDN updates the file? Only if you pin an unversioned URL. Point at a specific, immutable version and the hash stays valid indefinitely. When you intentionally upgrade, regenerate the hash as part of that change.


Not sure which third-party scripts load on your pages without an integrity hash? Run a free website vulnerability scan to find missing SRI and the rest of your attack surface in one pass.

Related vulnerabilities