A correct HTTPS URL does not prove that the JavaScript at that URL is still the exact version your team reviewed. If a CDN, provider account, or release pipeline is compromised, a browser can receive modified code from an otherwise legitimate server. Subresource Integrity (SRI) adds a cryptographic fingerprint to HTML so the browser accepts only the expected content.
SRI is particularly useful for static JavaScript and CSS loaded from a CDN. It is not suitable for every URL: the resource must remain immutable, the hash must change with the version, and cross-origin requests must satisfy CORS. Understanding those boundaries turns SRI into a reliable control instead of an attribute that unexpectedly breaks production.
1. What problem does SRI solve?
When HTML includes <script src="...">, the page delegates execution to whatever content the URL returns. TLS authenticates the server connection and protects data in transit, but it does not prove that the server still hosts the bytes the development team audited.
The W3C Subresource Integrity specification defines a mechanism for user agents to compare a fetched response with declared hash metadata. When they do not match, the resource is blocked rather than executed or applied.
| Control | What it protects | What it does not solve alone |
|---|---|---|
| HTTPS/TLS | Connection, server identity, and data in transit | Whether a legitimate server's file changed |
| SRI | Resource bytes match a pinned hash | Source HTML modified together with the hash |
| CSP | Allowed sources and execution conditions | Does not automatically pin a CDN file's bytes |
| Version pinning | A URL names a specific release | Does not verify the response content |
2. How does the integrity attribute work?
<script
src="https://cdn.example.net/library/4.2.1/library.min.js"
integrity="sha384-BASE64_DIGEST_HERE"
crossorigin="anonymous"></script>
- The browser fetches the resource from its URL.
- It computes a digest using the algorithm named in the metadata.
- The computed digest is compared with the Base64 value in
integrity. - A matching value permits use; otherwise loading fails.
Metadata uses the form algorithm-base64-digest. SRI supports SHA-256, SHA-384, and SHA-512. SHA-384 is a practical baseline; do not use MD5 or SHA-1.
An SRI hash covers the resource content, not its URL, filename, or TLS certificate.
3. JavaScript and CSS examples
<script
src="https://cdn.example.net/app/2.4.0/app.min.js"
integrity="sha384-AbCdEf..."
crossorigin="anonymous"></script>
<link
rel="stylesheet"
href="https://cdn.example.net/ui/2.4.0/ui.min.css"
integrity="sha384-ZyXwVu..."
crossorigin="anonymous">
The shortened hashes are structural examples and cannot be used. Obtain the exact hash published for the file or download the artifact through a trusted process and calculate it. One character, newline, build banner, or different minification pass produces a different digest.
4. Why cross-origin resources need CORS
For resources on another origin, SRI requires a CORS-eligible request. crossorigin="anonymous" uses CORS without credentials; the CDN must return an appropriate Access-Control-Allow-Origin header, commonly * for a public asset.
Without CORS, the browser may reject the resource even when the digest is correct. This is not a hash failure. Use Network and Console diagnostics to distinguish CORS, HTTP, and integrity failures.
- Use
anonymousfor public CDN files. - Avoid
use-credentialsunless cookies or credentials are required and the server implements matching CORS behavior. - Keep the CORS mode consistent between a preload and the element consuming it.
5. Generate a SHA-384 hash with OpenSSL
Hash the final artifact that the CDN will serve:
openssl dgst -sha384 -binary library.min.js | openssl base64 -A
Prefix the result with sha384-:
sha384-<base64-output>
Do not pass the file through a tool that changes line endings before hashing. Ideally, the pipeline builds one artifact, computes SRI from it, uploads the same bytes to storage/CDN, and generates the HTML manifest from the result.
6. Generate a hash with PowerShell
$path = 'C:\release\library.min.js'
$bytes = [System.IO.File]::ReadAllBytes($path)
$sha384 = [System.Security.Cryptography.SHA384]::Create()
try {
$digest = $sha384.ComputeHash($bytes)
'sha384-' + [Convert]::ToBase64String($digest)
} finally {
$sha384.Dispose()
}
Get-FileHash displays hexadecimal by default, while SRI metadata requires a Base64 digest. Do not paste its hexadecimal output directly after sha384-.
7. Verify the deployed asset
Download the production URL to a temporary file and recompute the digest:
curl.exe -fL "https://cdn.example.net/app/2.4.0/app.min.js" `
-o ".\app.min.js"
# Then run the PowerShell SHA-384 snippet above.
Also verify the status code, final redirect, size, and content type. CDN transformations, content-level recompression, or region-specific banners may make bytes unstable. Ordinary HTTP content encoding is handled in the fetch stack, but the pipeline should still test the exact browser URL rather than infer behavior from a source file.
8. Resource URLs must be immutable
SRI conflicts directly with “always latest” URLs. If /library/latest.js changes while HTML retains the old hash, the browser blocks the new file. That is the intended behavior.
- Prefer URLs containing an exact version or content hash.
- Never overwrite a released artifact under the same URL.
- When upgrading, review code and update URL plus integrity metadata together.
- Purge CDN caches deliberately and verify that all edges return the same content.
- Keep a version → URL → SRI manifest in source control or build output.
9. Multiple hashes in one attribute
An integrity attribute may contain several whitespace-separated expressions:
integrity="sha384-DIGEST_A sha384-DIGEST_B"
Multiple digests for the same algorithm can support a short transition where two exact payloads are accepted. This expands the valid content set and should remain temporary. When algorithms differ, the user agent selects metadata from the strongest supported algorithm; do not assume a weaker correct hash rescues an incorrect stronger hash.
10. Keep SRI and preload synchronized
<link
rel="preload"
as="script"
href="https://cdn.example.net/app/2.4.0/app.min.js"
integrity="sha384-AbCdEf..."
crossorigin="anonymous">
<script
src="https://cdn.example.net/app/2.4.0/app.min.js"
integrity="sha384-AbCdEf..."
crossorigin="anonymous"></script>
The URL, integrity metadata, and CORS mode should match. If preload and script attributes differ, the browser may not reuse the response as intended, or one step may succeed while the other fails.
11. SRI does not automatically protect every dependency
A hash on an external script protects the response referenced by that element. If the script loads more code, workers, WASM, or data at runtime, those subsequent resources are not automatically protected by the loader's hash. For a module script, the element's metadata protects the initial fetch; the dependency graph needs its own build, CSP, and integrity strategy.
A small SRI-protected loader that fetches plugins from mutable URLs therefore retains a supply-chain surface. Inventory static HTML loads and runtime dynamic loads.
12. Design fallback without bypassing protection
An integrity mismatch fails the load; the browser does not automatically switch URLs. A handler that retries an unpinned copy from elsewhere can convert a security signal into a bypass.
- For nonessential features, accept degraded mode and emit telemetry.
- For essential assets, consider self-hosting an audited artifact as the primary source.
- Any fallback should be a specific controlled artifact with its own integrity check.
- Do not inline a large library merely to avoid CDN failure; patch management becomes harder.
13. Combining SRI with CSP
CSP restricts origins and conditions under which scripts or styles may load; SRI validates the bytes of a specific resource. They complement one another. CSP can limit script-src to your origin and an approved CDN, while SRI prevents a different payload at the approved CDN URL from executing.
Do not mechanically copy SRI hashes into CSP: syntax and policy matching have their own context. Roll out CSP in report-only mode, collect violations, then enforce according to the threat model. Newer proposals such as Integrity Policy continue to evolve; verify standards status and browser support before making them a production dependency.
14. SRI cannot protect compromised HTML
An attacker who can modify the source HTML can remove integrity, replace both the URL and hash, or inject a new script. Serve HTML over HTTPS, protect deployment pipelines, restrict CMS access, and apply an appropriate CSP. SRI is strongest when the trust boundary lies between a page you control and an external asset host.
15. Recommended delivery pipeline
- Lock the dependency version and retrieve the artifact from a verified source.
- Scan or review the dependency according to project policy.
- Produce the final artifact and never mutate it afterward.
- Calculate SHA-384 and store it in a build manifest.
- Upload the exact artifact to an immutable URL.
- Generate HTML with the URL,
integrity, andcrossorigin. - Test in staging through the real CDN and CORS path.
- Run a negative test with an incorrect hash to prove the browser blocks the asset.
- Deploy and monitor load errors, CSP reports, JavaScript errors, and UI health.
Production checklist
- The resource URL contains an exact version or content hash.
- The digest comes from the final artifact and is Base64 encoded.
- SHA-384 or SHA-512 is used; MD5 and SHA-1 are not.
- The CDN returns appropriate CORS headers for cross-origin requests.
crossoriginmatches between preload and the consuming element.- URL and integrity metadata change in the same pull request or release.
- No fallback loads a mutable resource without integrity.
- Dynamically loaded resources are separately inventoried and controlled.
- Positive and intentional mismatch tests pass.
- Telemetry detects load failures before users report a broken interface.
Conclusion
Subresource Integrity turns “the CDN should return the correct file” into a cryptographic check in the browser. For durable SRI, pin versions, hash an immutable final artifact, configure CORS correctly, and integrate URL–hash updates into the release pipeline. Combined with HTTPS, CSP, and supply-chain governance, SRI provides an independent layer of control instead of placing all trust in an external URL.




No comments yet. Be the first to share your thoughts.