Subresource Integrity (SRI): Protecting CDN Scripts
Subresource Integrity (SRI): Protecting CDN Scripts
Subresource Integrity (SRI) is the integrity attribute on <script> and <link> tags. The browser hashes the loaded file with SHA-256/384/512 and compares it to the expected value. A mismatch aborts execution. SRI defends against the classic "CDN compromised → malicious payload → every client popped" scenario — see event-stream and Magecart.
How SRI works
Spec: W3C Subresource Integrity. Example:
<script
src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"
integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
crossorigin="anonymous"></script>
Browser: 1) fetch file, 2) compute SHA-384, 3) compare to integrity, 4) on mismatch, block and emit a console error.
When to use SRI
- CDN scripts (jQuery, Bootstrap, React) — especially from jsdelivr, cdnjs, unpkg
- Third-party fonts when integrity matters
- Pinned-version analytics or chat widgets
Do not use it on auto-updating scripts — every release breaks integrity.
Generating the hash
curl -s https://cdn.example.com/file.js | openssl dgst -sha384 -binary | openssl base64 -A
Or use srihash.org. jsdelivr and cdnjs ship hashes in their copy-paste snippets.
crossorigin="anonymous"
Without it the browser will not expose SRI errors to your JS and cross-origin loads without CORS fail. Always pair SRI with crossorigin="anonymous".
CSP require-sri-for
CSP Level 3 directive enforcing SRI on all scripts and styles:
Content-Security-Policy: require-sri-for script style
Still experimental; deploy as defence-in-depth.
SRI + versioning
Problem: jsdelivr.net/jquery@latest mutates and integrity breaks. Solutions:
- Pin the version:
jquery@3.7.1 - Automate integrity updates in CI (npm audit, yarn, Vite SRI plugin)
- Or proxy through your own nginx cache
SRI for your own CDN
If the CDN is yours (CloudFront, Yandex Cloud CDN), SRI defends against the CDN infra itself being compromised (S3 keys leaked → file swapped). Worth enabling on critical flows (checkout, auth).
Webpack / Vite
// webpack
const SubresourceIntegrityPlugin = require('webpack-subresource-integrity').SubresourceIntegrityPlugin;
module.exports = {
output: { crossOriginLoading: 'anonymous' },
plugins: [ new SubresourceIntegrityPlugin({ hashFuncNames: ['sha384'] }) ],
};
// Vite
import { sriPlugin } from 'vite-plugin-sri';
export default { plugins: [sriPlugin()] };
Verification
DevTools → Network → click the script → Headers. Mismatches surface in the console as "Failed to find a valid digest in the 'integrity' attribute".
The enterno.io Security Scanner lists external scripts and flags missing integrity — useful for audit reviews.
FAQ
Need SRI on my own domain? Technically no — same-origin is implicitly trusted. But if one CDN serves many projects, SRI adds isolation.
SHA-256 or SHA-384? W3C recommends SHA-384. You can list multiple: integrity="sha256-... sha384-...".
Works on stylesheets? Yes — <link rel="stylesheet"> supports integrity identically.
Does SRI slow loading? Microseconds of hashing overhead, no measurable impact.
Conclusion
For every CDN script — integrity + crossorigin="anonymous". Automate via CI and track CDN file changes with enterno monitoring. Related: HTTP Security Headers, CSP Setup.
Check your website right now
Check now →