How to generate a Subresource Integrity (SRI) hash
CentralCSP Team ·
Last update:
Subresource Integrity (SRI) is the integrity attribute that makes the browser verify an external file's bytes against a hash you supply, and block the file if it does not match. To use it you need two things: the hash, and the right attribute on the tag.
Generate the hash with the SRI generator: paste the file or URL and it returns the SHA-256, SHA-384, and SHA-512 values ready to paste. The value is the base64 digest of the raw file bytes. Prefix it with the algorithm and drop it on the tag, paired with crossorigin for a cross-origin file:
<script
src="https://cdn.example.com/script.js"
integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
crossorigin="anonymous"></script>New to the mechanism itself? Subresource Integrity (SRI) explained covers what it is and what it protects against. The rest of this post is the how-to and the traps that quietly break it.
Pick the algorithm
SRI accepts sha256, sha384, and sha512. Prefer sha384 or sha512. The digest is computed over the raw file bytes and base64-encoded, so the only thing that changes between algorithms is the strength and length of the value.
If you list more than one hash in the integrity value, the browser does not pick the first one. It uses the strongest algorithm present. A sha256 next to a sha384 means only the sha384 hash is checked, so listing a weaker one alongside a stronger one never weakens the check. The SRI generator returns all three values, so you can paste whichever you want.
Pair it with crossorigin
A cross-origin <script> or <link> that carries integrity but no crossorigin="anonymous" always fails to load. This is the single most common SRI mistake.
Without crossorigin, the browser fetches the file in no-cors mode and gets an opaque response it cannot read, so it cannot verify the bytes against your hash and refuses to run the file. Adding the attribute switches the fetch to CORS so the browser can read the response and check it.
<link
rel="stylesheet"
href="https://cdn.example.com/styles.css"
integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
crossorigin="anonymous">Same-origin files are already in a readable state, so they are checked without crossorigin. The attribute is the cross-origin requirement.
Verify it works
Load the page and watch for the file. A correct hash loads silently. A wrong hash, or a missing crossorigin on a cross-origin file, fails the load and logs an integrity error in the browser console.
To confirm a mismatch is caught on purpose, change one character in the integrity value and reload: the script should be blocked and the console should report that the resource failed its integrity check. Restore the correct value once you have seen the block.
Keep hashes fresh when files change
SRI does not auto-update. The hash is tied to the exact bytes of the file, so it must be regenerated every time the file content changes. That is the feature working as designed, a changed file with an old hash is treated as tampering and blocked.
This is why a "latest" or auto-minifying CDN URL breaks SRI: the bytes can change under you without warning, and the next deploy on their side blocks your page. Pin an immutable, versioned URL (a specific version path, not a moving tag) so the file you hashed is the file you keep getting.
The maintenance burden is also the reason teams track which third-party scripts they ship in the first place. CentralCSP builds a script inventory of every script running on your pages from CSP hash reports, so when a third-party file changes you see it instead of finding out from a blocked load.
Do it with build tools
Generating hashes by hand does not scale past a couple of files. Most bundlers can emit integrity attributes automatically as part of the build, so you can automate it with Webpack or Vite:
- Webpack: webpack-subresource-integrity adds the
integrityattribute to emitted<script>and<link>tags. - Vite: a community plugin such as @small-tech/vite-plugin-sri computes and injects the hashes at build time.
These keep the hash in sync with the file automatically, which removes the regenerate-on-change footgun for your own bundled assets.
Not the same as a CSP hash
An SRI hash and a CSP hash look alike and are easy to confuse. They hash different things.
- SRI hashes an external file and goes in the
integrityattribute on the tag. - A CSP
'sha256-...'source hashes inline script content and goes in thescript-srcdirective of your Content Security Policy.
If you are allowlisting an inline <script> block, you want the CSP hash, not SRI. How to generate a CSP hash (sha256) covers that case.
Where to require it
You add integrity per tag. To require SRI across a whole document instead of tag by tag, there is the Integrity-Policy header, which tells the browser to refuse any in-scope subresource that loads without integrity metadata.
Integrity-Policy: blocked-destinations=(script)Integrity-Policy recently became available across current Chrome, Firefox, and Safari. See the Integrity-Policy reference for the directives and the report it emits.
Next steps
Add integrity and crossorigin to your cross-origin scripts and stylesheets, pin their URLs, and wire your bundler to emit hashes for your own assets. If a scanner already pointed you here, see if a scanner flagged your SRI. To see what third-party code you are actually loading before you start hashing it, start free and let CentralCSP inventory your client-side scripts.