ASVS 5.0 requirement V3.6.1 says client-side assets such as JavaScript libraries, CSS or web fonts may be hosted externally, for example on a CDN, only if the resource is static and versioned and Subresource Integrity (SRI) is used to validate it. If that is not possible, there must be a documented security decision for each such resource. It is a Level 3 requirement.
Why it matters
A script tag pointing at someone else's server hands that server control of your page. If the CDN account is compromised, a file is replaced, or a package maintainer ships something hostile, every visitor runs the new code with full access to your DOM, forms and session. Supply chain incidents on public CDNs and polyfill hosts have shown this is not hypothetical. See CWE-830.
SRI fixes it by pinning the exact content. The browser downloads the file, hashes it and refuses to run it if the hash differs from the one in your HTML.
How to implement it
Pin a version and add a hash:
<script src="https://cdn.example.net/lib/chart-4.4.1.min.js"
integrity="sha384-BASE64HASHHERE"
crossorigin="anonymous"></script>
Compute the hash yourself from the exact file:
curl -s https://cdn.example.net/lib/chart-4.4.1.min.js \
| openssl dgst -sha384 -binary | openssl base64 -A
Prefix the output with sha384-. The crossorigin="anonymous" attribute is needed so the browser can check cross-origin files, and the CDN must send CORS headers.
Rules that follow from the requirement:
- The URL must name a specific version, not
latestor a floating major. - The content must be static, so the hash holds. Loaders that return different code per browser, such as some polyfill services, cannot use SRI. Document those or self host.
- Self hosting avoids the question: serve the same file from your own origin.
Make it routine. A build step can inject hashes, and a CI check can fail a build if any external script or link rel=stylesheet lacks integrity. Keep a short register of exceptions with owner, reason and review date.
Click through it at your own pace, or open it full screen.
SRI pins a file but does not tell you whether the pinned version has known vulnerabilities. Run your front end dependencies through the free in-browser dependency scan at gold.safeguard.sh/scan, and keep an inventory of what loads from where.
How to test it
Extract every external reference from your rendered pages:
curl -s https://app.example.com/ \
| grep -oE '<(script|link)[^>]+(src|href)="https?://[^"]+"[^>]*>' \
| grep -v 'integrity='
Anything printed is an external asset without SRI. Run the check on each page template, including pages behind login. In a browser, change one character of an integrity value in a test build and confirm the console reports a blocked resource.
Check web fonts and CSS from font providers too. Those stylesheets often vary by user agent, which makes SRI unworkable, so each needs a documented decision or self hosting.
Common mistakes
Integrity without a pinned version. If the file can change, the page will break instead of staying safe.
Hash copied from a blog post. Compute it from the file you actually serve.
Missing crossorigin. The browser skips or fails the check.
Tag managers. Scripts they inject at runtime bypass your HTML attributes. Treat them as exceptions to document.
No register of exceptions. The requirement asks for a documented decision per resource.
Quick check
Is self hosting better than SRI?
Usually simpler. You control the file and update it with your normal review. SRI is for when a CDN is worth the trade.
What happens when the hash does not match?
The browser blocks the resource and logs an error. Your page loads without it, so test failure behavior for critical scripts.
Sources
- OWASP ASVS 5.0, requirement V3.6.1
- MDN: Subresource Integrity
- CWE-830 on Gold