Skip to main content
PCI Monitor

Subresource Integrity (SRI): how it works and what it cannot do

Defenses · 6 min read · Last reviewed: October 17, 2026

Subresource Integrity (SRI) lets a web page say, in the script tag itself, what the exact content of an external file must be. The browser fetches the file, computes its hash and refuses to run it if the hash does not match. SRI protects against a file being changed on the server that hosts it, but it cannot protect scripts that change on purpose, scripts built on the fly, inline scripts or the page that carries the tag.

How SRI works

SRI adds an integrity attribute to a <script> or <link> tag. The attribute holds a cryptographic hash of the file you expect, written as the name of the algorithm, a hyphen and the base64 value. SHA-256, SHA-384 and SHA-512 are supported; SHA-384 is a common choice.

<script src="https://cdn.example.com/lib/1.2.3/lib.min.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

(The hash above is only an illustration of the format.) The browser downloads the file, hashes it and compares the result with the attribute. If they match, the script runs. If not, the browser blocks the file and the page carries on without it. A tag can list more than one hash, and the browser accepts the file if it matches the strongest one it supports.

The crossorigin attribute

For a file from another origin, the browser can check the hash only if the server allows it through CORS. That is why external tags with integrity also carry crossorigin="anonymous", and the server must send an Access-Control-Allow-Origin header. If it does not, the file fails to load.

Making the hash

Any tool that can produce a SHA-384 digest and base64-encode it will do. A common command-line way is openssl dgst -sha384 -binary file.js | openssl base64 -A, then putting sha384- in front of the result. Generate it from the exact file your page will load, and from your own copy or a verified download, not from a live address you have not checked.

What SRI protects against

SRI is aimed at one risk: an external file that is changed after you approved it. That includes a hosting or CDN provider that is breached, a library account that is taken over, and tampering between the server and the browser. If the file changes by even one character, the hash no longer matches and the browser refuses it. For static, versioned files from third parties it is a cheap and effective control, and it is one way to assure integrity for the purposes of PCI DSS 6.4.3.

What SRI cannot protect

  • Scripts that change on purpose. A vendor that updates its script every week, or serves a different file to different visitors, cannot be pinned to one hash. The polyfill.io service, for example, generated its code dynamically from request details, which is the kind of delivery SRI does not suit (see third-party JavaScript risk). Tag manager containers are another example: the file changes whenever someone publishes.
  • Inline scripts. The integrity attribute works on external files. For inline scripts use CSP hashes or nonces instead (Content Security Policy for payment pages).
  • Scripts that load other scripts. SRI checks the file it is attached to, not what that file goes on to load.
  • The page that carries the tag. An attacker who can change your HTML can change or remove the integrity attribute. SRI protects against a compromised file host, not a compromised page.
  • A file that was already malicious when you hashed it. SRI proves sameness, not safety.

Why SRI breaks, and how to live with it

The most common failure is a legitimate update: the vendor publishes a new file at the same address, the hash no longer matches, and the browser blocks a script your payment page may depend on. Plan for that:

  • Use versioned addresses (for example a version number in the path) so a file at an address does not change after you pinned it.
  • Keep the hash and the address in one place, and update them together after you have reviewed and tested the new version.
  • Test on a staging page before changing a live payment page, because a blocked script can break checkout.
  • Monitor for integrity failures and for change on the vendor's side, so you hear about a mismatch before customers do.
  • Consider hosting a reviewed copy yourself when the vendor will not provide versioned files.
  • Remember the cross-origin requirement: if the vendor stops sending the CORS header, the file fails to load even though its content is unchanged.

SRI is best treated as one layer. Together with a Content Security Policy, an inventory and change detection, it covers the cases the others miss.

Key takeaways

  • SRI puts a hash of the expected file in the script tag; the browser blocks the file if its content differs.
  • It needs crossorigin="anonymous" and a CORS header from the file host for cross-origin files.
  • It protects against a changed file on the host, not against dynamic scripts, inline scripts, scripts that load others, or a compromised page.
  • Updates by the vendor will break a pinned script unless you manage hashes and versions deliberately.
  • Use SRI together with CSP, an inventory and change detection.

Frequently asked questions

What does the integrity attribute do?

It tells the browser the expected hash of an external file. The browser hashes what it downloads and runs the file only if the result matches.

Why does SRI need the crossorigin attribute?

The browser can only inspect the content of a cross-origin file for hashing if the server permits it through CORS. The crossorigin attribute makes the request a CORS request, and the server must answer with a suitable Access-Control-Allow-Origin header.

Would SRI have stopped the polyfill.io attack?

Only for sites that had pinned a file by hash, which was hard because the service generated different code depending on the visitor's request. Self-hosting a reviewed copy or removing the dependency were the usual responses.

Does SRI satisfy PCI DSS 6.4.3?

It can be one method for assuring the integrity of static external scripts, which is part of 6.4.3. It does not cover inline or dynamic scripts, and 6.4.3 also needs authorization and an inventory, so it is usually one layer among several. Your assessor decides what is sufficient.

References

Last reviewed: October 17, 2026