Checking Subresource Integrity: Does That Script Match Its Hash?

Most pages load at least one script or stylesheet from somewhere else: a content delivery network, a font provider, an analytics service, or a widget supplier. That convenience carries a risk. If the third party's file changes, whether through compromise, mistake, or an update you did not expect, your page silently loads the new version, and your visitors run code you never reviewed. Subresource Integrity, usually called SRI, is the browser feature that closes that gap. It lets a page declare the expected hash of a file, and the browser refuses to run the file if its contents do not match. The SRI Checker examines a tag you paste in, checking whether its integrity attribute is present, well-formed, and consistent, so you can confirm that a page's protection is actually in place.

The mechanism is simple in outline. When you add a script or stylesheet from a third party, you add an integrity attribute containing the hash algorithm and the base64-encoded digest of the file, for example sha384 followed by a long encoded string. You also add a crossorigin attribute, because the browser needs to fetch the file in a mode that allows integrity checking. When the browser downloads the file, it computes the hash of what it received and compares it with the declared hash. If they match, the file runs. If they differ, even by a single byte, the browser blocks the file and reports an error, and the page continues without that script or stylesheet. That blocking is the protection: a tampered or unexpectedly changed file cannot execute under your page's origin.

How it works

Checking a pasted tag focuses on the pieces that commonly go wrong. First, is the integrity attribute present at all? A third-party script without one has no integrity protection, regardless of how reputable the provider is. Second, is the algorithm one browsers support for SRI, such as SHA-256, SHA-384, or SHA-512? SHA-384 is the most commonly recommended choice, balancing digest length against security margin, while SHA-1 and MD5 are not acceptable for SRI. Third, is the digest correctly encoded and of the right length for its algorithm? A truncated, mistyped, or wrongly padded digest will never match, so the browser will block a perfectly good file, which is a self-inflicted outage rather than a security event. Fourth, is the crossorigin attribute present and set correctly? Without it, the integrity check cannot run for a cross-origin file, and the browser may ignore the integrity attribute entirely, leaving the page unprotected while looking protected.

A checker also looks at context the tag alone can reveal. Is the file loaded over HTTPS? An integrity hash over an HTTP fetch is of limited value, because the hash itself could be altered in transit along with the file. Does the tag use any additional attributes that affect loading, such as async or defer for scripts, which change timing but not integrity? And is the hash plausible for the file it claims to describe, which can only be confirmed by hashing the actual file and comparing, a step a tag checker cannot do alone? That last point is important: checking a tag confirms the tag is well-formed, but only comparing the declared hash against a freshly computed hash of the real file confirms the file itself is the one you approved.

Worked example

Consider a sample script tag, with a shortened illustrative digest that is not a real hash for any file:

A checker reading this tag would report the following. The integrity attribute is present and uses SHA-384, which is acceptable. The crossorigin attribute is present and set to anonymous, which is correct for a public file. The source is HTTPS, which is good. The digest shown here is abbreviated with dots for illustration, so in a real check it would be flagged as incomplete, because a real SHA-384 digest is a specific length of base64 text, and anything shorter cannot match a real file. That flag is the checker doing its job: a placeholder digest in production would block the script on every load, and a truncated digest copied from a truncated display would do the same.

Now consider a real failure mode. A provider releases version 2.4.2 of the library and updates the file at the same address, but your page still declares the hash of version 2.4.1. The browser downloads 2.4.2, computes its hash, finds it differs from the declared hash, and blocks the script. Your page's feature that depended on the library stops working, and the console shows an integrity error. That outage is the protection working as designed: the page refused to run code it had not approved. The fix is to review the new version, compute its new hash, update the integrity attribute, and redeploy. The mistake would be to remove the integrity attribute to restore the feature quickly, because that removes the protection permanently in exchange for fixing one incident.

Mistakes to avoid

The most common mistake is adding SRI to a file whose address changes on every request, such as a file with a dynamic query string or a provider that updates files in place without versioning. Integrity requires a stable file, so always reference a versioned address, and treat any provider update as a hash update too. A second mistake is omitting the crossorigin attribute, which silently disables the check for cross-origin files. A third mistake is copying a hash from documentation, a blog post, or another site without verifying it against the file you actually load. A copied hash that does not match your file blocks the file, and a copied hash that matches a different version approves code you did not review, so always compute or verify the hash against the exact file your page loads.

A fourth mistake is applying SRI only to scripts and forgetting stylesheets. A malicious stylesheet cannot run code directly, but it can restyle a page to mislead users, hide warnings, or make a fake login form look genuine, so stylesheets from third parties deserve the same treatment. A fifth mistake is treating a passing tag check as proof the file is safe. A hash proves the file is unchanged since the hash was computed, not that the file was ever safe; a malicious file hashed by its own author passes its own integrity check perfectly. Integrity answers the question of whether the file changed, and only review answers whether it should be trusted. Finally, the handling rule: hashes and tags are public data, but credentials are not. Never paste private keys, tokens, or account passwords into a checker alongside a tag.

Putting it into practice

Add SRI to every third-party script and stylesheet you control, starting with the ones that run on pages handling sensitive actions, such as login, checkout, and account settings. Generate each hash from the exact file your page loads, store the hash alongside the tag so the next editor can see they belong together, and rebuild the hash whenever the provider version changes. When an integrity error appears, treat it as a signal, not a nuisance: find out what changed before deciding whether to update the hash. For neighbouring tools, the Hash Generator computes digests in the formats SRI uses, and the JavaScript Minify tool is relevant when you minify your own files before hashing, since minification changes the bytes and therefore the hash. For background reading, the related guide explains digests and checksums, which are the foundation SRI is built on.

Key points

  • SRI lets a page declare the expected hash of a third-party file, and the browser blocks mismatches
  • A valid SRI tag needs an integrity attribute, a supported algorithm, and a crossorigin attribute
  • Always reference a versioned file address, and update the hash when the version changes
  • A matching hash proves a file is unchanged, not that it was ever trustworthy