Web Security

What Are the Limitations and Browser Support for SRI?

Explore Subresource Integrity limitations with dynamic content, fallback scenarios, browser compatibility, and practical considerations for implementation.

By Inventive HQ Team

Understanding SRI's Scope and Limitations

Subresource Integrity (SRI) works only on <script> and <link rel="stylesheet"> elements, requires CORS (crossorigin="anonymous") for cross-origin resources, cannot protect inline scripts or dynamically imported modules, and blocks any resource whose bytes change — but it is supported in every modern browser (Chrome/Edge 45+, Firefox 43+, Safari 12.1+), covering roughly 96% of global web traffic. In practice that means SRI is a near-universal control for pinning static third-party files, with a small, well-defined set of things it deliberately does not do.

That's the summary an AI Overview gives you. What it can't give you is the why behind each boundary — why dynamic content breaks the hash, why a failed check has no fallback, why cross-origin needs CORS — or a side-by-side map of every limitation against the workaround. That's the rest of this page.

What Subresource Integrity can and cannot verify A browser fetches a script from a CDN, hashes it, and compares against the integrity attribute. External scripts and stylesheets are covered; inline scripts, dynamic responses, and imports are not. SRI: hash the fetched file, then compare Browser sha256- compare CDN library.js fetch + CORS match, run

Covered: external <script>, <link rel="stylesheet"> Not covered: inline scripts, @import, dynamic imports, changing files

Browser Support for SRI

SRI has shipped in every modern browser for years, so support is effectively universal outside of retired engines:

BrowserFirst version with SRIReleasedStatus
Chrome45+Aug 2015Full support
Edge45+ (Chromium)2015Full support
Firefox43+Dec 2015Full support
Safari12.1+Mar 2019Full support
Opera32+2015Full support
Internet ExplorerNever implemented
Legacy Android WebViewVariesSpotty / unreliable

User agent statistics: approximately 96%+ of global web traffic comes from browsers with full SRI support. Because a failed or unsupported check degrades gracefully (older browsers simply ignore the integrity attribute and load the file normally), you can add SRI today without breaking legacy clients — they just don't get the extra protection.

SRI Limitations at a Glance

Before the deep dives, here is every practical limitation mapped to what causes it and what to do instead:

LimitationWhy it happensWorkaround
Only <script> and <link rel="stylesheet"> are coveredThe spec targets those two fetch types onlyUse CSP for images, iframes, and other resources
No inline scriptsThere is no fetched file to hashUse a CSP nonce or hash for inline code
No CSS @import or dynamic import()Those fetches bypass the integrity attributeLoad the file with a real <link>/<script> tag
Breaks on dynamic / per-user contentThe hash must match fixed bytes exactlyUse CSP nonces/hashes instead of SRI
Cross-origin needs CORSBrowsers won't hash an opaque responseAdd crossorigin="anonymous" + Access-Control-Allow-Origin
No built-in fallback on failureA blocked resource just doesn't loadDetect failure in JS and load a backup manually
Breaks when the CDN updates the fileHash pins you to exact bytesPin immutable versioned URLs; update the hash on upgrade
Only SHA-256/384/512, base64-encodedWeak algorithms are disallowed by specGenerate hashes with a compliant tool
Loading interactive tool...

Dynamic Content: The Fundamental Limitation

SRI's core limitation is incompatibility with dynamic content. Any resource that changes between requests cannot use SRI:

Dynamic server responses:

// This content changes on each request (per-user configuration)
window.userId = {{ current_user.id }};
window.apiKey = {{ api_key }};

The hash changes with each response, making SRI impossible.

Template-rendered content:

<script src="https://example.com/config?user={{ user_id }}"></script>

Query parameters change the content, invalidating hash-based verification.

Real-time APIs:

<script src="/api/data"></script>

APIs return different content based on application state, time, or other factors.

Server-side template variables:

const version = '{{ app_version }}';
const timestamp = new Date('{{ now }}');

These values change, affecting the hash.

For any of these scenarios, you must use alternatives like CSP with nonces or other security mechanisms.

Query Parameters and URL Caching Issues

When using SRI with query parameters in URLs, you may encounter caching complications:

<script src="https://example.com/lib.js?version=1.0.0" integrity="sha256-..."></script>

If you later update the library:

<script src="https://example.com/lib.js?version=1.0.1" integrity="sha256-..."></script>

Browsers cache based on URL. If /lib.js?version=1.0.0 is cached, the browser might not re-fetch when the URL changes. You need to verify that:

  • Query parameters are sufficient to bust cache
  • CDN respects Cache-Control headers appropriately
  • Version identifiers are unique enough to trigger fresh fetches
Advertisement

Resource Substitution Without SRI

Even with SRI in place, you cannot easily substitute resources. If you need to update a library, you must:

  1. Update the library file
  2. Compute the new integrity hash
  3. Update all HTML references with the new hash

This can be challenging in applications with many HTML files or dynamically generated content.

Solutions include:

  • Using build tools to automatically compute and embed hashes
  • Versioning resources with unique URLs (lib-v1.js, lib-v2.js) and updating hashes in one central location
  • Using Content Security Policy with allowlist instead of SRI for more flexible resource management

Fallback Handling: What Happens When Verification Fails

When SRI verification fails, the browser simply doesn't load the resource. For scripts, this means no error callback or fallback is triggered:

<script src="https://cdn.example.com/library.js"
        integrity="sha256-wrong-hash">
</script>

<!-- This code runs regardless of whether the script loaded -->
<script>
  // library might not be available here!
  library.doSomething(); // ReferenceError if previous script failed to load
</script>

The second script executes even if the first failed, leading to errors. Your application must handle this gracefully:

<script src="https://cdn.example.com/library.js"
        integrity="sha256-...">
</script>

<script>
  if (typeof library === 'undefined') {
    console.error('Required library failed to load');
    // Implement fallback behavior
  }
</script>

Some frameworks provide better error handling, but you must always assume SRI verification might fail and plan accordingly.

Stylesheet and Font SRI Limitations

SRI works for stylesheets and fonts, but with important limitations:

Stylesheet SRI:

<link rel="stylesheet" href="https://cdn.example.com/style.css" integrity="sha256-...">

If verification fails, the stylesheet isn't loaded, and your page appears unstyled. Users might not understand why the page looks broken and doesn't know to try again.

Font SRI:

<link rel="preload" href="https://fonts.example.com/font.woff2" as="font" integrity="sha256-...">

If the font fails verification, the browser uses a fallback font. This is less critical than script failure but affects appearance.

For stylesheets especially, consider whether the risk of SRI failure (due to CDN issues, network corruption, or attacks) outweighs the security benefit of hash verification.

Performance Implications

Hash Computation Cost - The browser must compute the hash of every SRI-protected resource. This is typically fast (microseconds), but it's not completely free:

  • For a single resource, imperceptible
  • For many resources (20+), might add a few milliseconds
  • On slow devices, might be more noticeable

Network Transmission - Integrity attributes add bytes to your HTML:

<!-- Add 70+ characters per script -->
<script src="..." integrity="sha256-abcdefghijklmnopqrstuvwxyz1234567890abcd="></script>

This is minimal and typically worth the security benefit.

Caching Behavior - If you version resources properly, SRI doesn't negatively impact caching. If you don't, it can be an issue.

Cross-Origin Resource Sharing (CORS) Interactions

SRI doesn't directly interact with CORS, but they operate in the same space:

<script src="https://different-origin.com/lib.js"
        crossorigin="anonymous"
        integrity="sha256-...">
</script>

For cross-origin scripts with SRI:

  • The crossorigin attribute is required for integrity verification to work
  • Without it, SRI verification might be skipped
  • Ensure the cross-origin server sends appropriate CORS headers

No Fallback Resource Support

One limitation is that SRI doesn't support fallback resources:

<!-- This would be nice but isn't valid -->
<script src="https://cdn.example.com/lib.js"
        integrity="sha256-..."
        fallback="https://my-server.com/lib-backup.js">
</script>

Instead, you must implement fallback logic manually:

<script src="https://cdn.example.com/lib.js" integrity="sha256-..."></script>
<script>
  if (typeof library === 'undefined') {
    // Load from backup
    var script = document.createElement('script');
    script.src = 'https://my-server.com/lib-backup.js';
    document.head.appendChild(script);
  }
</script>

This adds complexity but ensures your application remains functional even if the primary CDN is compromised or unavailable.

Hexadecimal vs Base64 Hash Encoding

SRI uses base64-encoded hashes, not hexadecimal:

<!-- Correct: base64 encoding -->
<script src="https://example.com/lib.js" integrity="sha256-abc+/="></script>

<!-- Incorrect: hexadecimal encoding -->
<script src="https://example.com/lib.js" integrity="sha256-abc0def"></script>

Hash tools must output base64. Tools that output hexadecimal won't work with SRI. The SRI Hash Generator tool handles this correctly.

Lack of Support for Non-Standard Hash Algorithms

SRI supports specific hash algorithms:

  • SHA256 (most common, recommended)
  • SHA384 (stronger, supported)
  • SHA512 (strongest, supported)

Other algorithms aren't supported:

  • MD5 (cryptographically broken, not supported)
  • SHA1 (deprecated, not supported)
  • BLAKE2 (newer, not yet supported)

Use SHA256 for most cases. Use SHA384 or SHA512 if you need stronger hashing, though SHA256 is considered sufficient for security purposes.

Version Pinning vs Automatic Updates

SRI enforces version pinning—you pin to a specific version by its hash:

<script src="https://cdn.example.com/library-1.2.3.js"
        integrity="sha256-abcd1234">
</script>

If the CDN updates the library, the hash changes, and verification fails. This is intentional—it prevents automatic updates that might break your application or introduce vulnerabilities.

This means you must:

  • Manually manage library versions
  • Update SRI hashes when updating libraries
  • Test library updates before deploying
  • Accept that you won't automatically get security patches

For some teams, this is a feature; for others, it's a limitation.

Subdomains and SRI

SRI works across subdomains as long as CORS is properly configured:

<script src="https://cdn.subdomain.example.com/lib.js" integrity="sha256-..."></script>

As long as the subdomain serves the resource, SRI verification works. No special configuration is needed.

CSP Interaction and Reporting

SRI violations are reported through CSP when CSP is configured:

<meta http-equiv="Content-Security-Policy" content="report-uri /csp-violations">

SRI failures should be included in CSP violation reports, though browser support for reporting varies.

Recommendations for Managing SRI Limitations

For Dynamic Content - Use CSP with nonces or hashes instead of SRI.

For Update Flexibility - Accept manual update processes or automate them with build tools.

For Fallback Scenarios - Implement manual fallback logic or accept slight styling/functionality degradation.

For Browser Compatibility - 96%+ coverage is excellent, but monitor your specific user agent statistics and implement graceful degradation for legacy browsers.

For Performance - SRI adds minimal overhead; prioritize security over the tiny performance cost.

For Versioning - Use unique URLs (lib-v1.0.0.js) and automate hash computation in your build process.

Conclusion: Understanding SRI's Real-World Constraints

SRI is a powerful security control with excellent modern browser support, but it has real limitations. Dynamic content incompatibility is the most significant, but query parameter handling, fallback scenarios, and version pinning also require careful consideration. Understanding these limitations helps you use SRI effectively where it's appropriate and choose alternative security mechanisms where it isn't. In combination with other security measures like CSP, SRI provides important protection for external static resources while recognizing that no single security control solves all problems.

Frequently Asked Questions

Which browsers support Subresource Integrity?

All modern browsers support SRI: Chrome and Edge since version 45 (2015), Firefox since 43 (2015), Safari since 12.1 (2019), and Opera since 32. Internet Explorer never implemented it. Roughly 96%+ of global web traffic now runs on browsers with full SRI support.

What elements can SRI protect?

SRI works only on <script> elements and <link rel="stylesheet"> elements. It cannot protect inline scripts, resources pulled in via CSS @import, images, iframes, or dynamically imported ES modules. For those you need Content Security Policy or other controls.

Why does cross-origin SRI need the crossorigin attribute?

A browser will only verify the integrity of a cross-origin resource if it was fetched with CORS. You must add crossorigin="anonymous" and the remote server must return an Access-Control-Allow-Origin header. Without CORS, the browser treats the response as opaque and refuses to load the resource rather than silently skipping the check.

Can I use SRI with dynamic or per-user content?

No. SRI verifies a fixed cryptographic hash, so any resource whose bytes change between requests — per-user config, template variables, query-driven APIs — will fail verification. Use CSP nonces or hashes for dynamic content instead.

What happens when SRI verification fails?

The browser blocks the resource with a network error and does not execute or apply it. There is no automatic fallback: a failed script simply does not run, so later code that depends on it throws errors unless you check for it and load a backup manually.

Does SRI work with inline scripts?

No. The integrity attribute is ignored on inline <script> blocks because there is no fetched resource to hash. SRI only validates externally loaded files referenced by src or href.

Which hash algorithms does SRI support?

SRI supports SHA-256, SHA-384, and SHA-512, encoded in base64 (not hexadecimal). SHA-256 is the common recommendation. MD5 and SHA-1 are not supported because they are cryptographically weak.

Does SRI break when a CDN updates a library?

Yes, by design. SRI pins you to an exact version by its hash, so if the CDN changes the file the hash no longer matches and the browser blocks it. Pin to versioned, immutable URLs and update the hash deliberately when you upgrade.

srisubresource-integritybrowser-supportweb-securitycompatibility