Subresource Integrity (SRI) is a W3C security standard that lets you specify a cryptographic hash on <script> and <link> tags so the browser can verify the loaded file matches what you expect. If the file at the URL has been modified, intercepted or replaced (whether by an attacker, a compromised CDN, or even an accidental update), the browser blocks execution entirely. SRI was standardized in 2016 and is supported by every major browser. It is one of the cheapest mitigations against supply-chain attacks on third-party JavaScript, which is the dominant source of breach incidents on WordPress sites in 2026.
What does an SRI hash look like, and how do I add it?
An SRI-enabled script tag has two extra attributes: integrity and crossorigin:
<script
src="https://cdn.example.com/jquery-3.7.1.min.js"
integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
crossorigin="anonymous">
</script>The integrity value is a base64-encoded cryptographic hash of the file contents, prefixed with the algorithm used (sha256-, sha384-, or sha512-). SHA-384 is the recommended choice in 2026: a good balance between security and hash length. SHA-512 is also acceptable. SHA-256 still works but is considered the weakest of the three; it is fine for non-critical assets but not for anything security-sensitive.
When the browser loads the file, it computes its hash and compares it to the integrity value. If the hashes match, the script runs. If they differ even by one byte, the browser refuses to execute it and logs an error in the console.
What attacks does Subresource Integrity prevent?
SRI specifically protects against the case where a third-party file is modified between the time you decided to trust it and the time a user's browser actually loads it. The three most relevant scenarios for WordPress sites:
- CDN compromise. If an attacker breaks into a CDN (or the third-party service whose CDN you use) and modifies a JavaScript file, every site embedding that file via
<script src>would suddenly run the attacker's code. SRI catches this immediately: the modified file does not match the hash, the browser blocks it. - Account takeover at the third-party provider. Someone compromises an analytics, chat widget, or font hosting account and pushes a malicious update to the script you have embedded. Without SRI, your site runs the malicious update on every page load. With SRI, the script silently fails until you update the hash, which means until you have personally re-vetted the new version.
- Network-level tampering. A man-in-the-middle attacker on a corporate network or hostile WiFi rewrites a JavaScript file as it transits to the user. HTTPS prevents this for direct connections to your origin, but a third-party script served from an attacker-controlled DNS poisoning attempt could bypass that. SRI provides an end-to-end integrity check independent of TLS.
The 2018 British Airways breach where 380,000 customers had their payment details stolen happened because the attacker modified a third-party Modernizr script that BA loaded on their checkout page. SRI on that script tag would have stopped the attack the moment the modified file loaded. Similar incidents continue to happen, with Magecart-style attacks on e-commerce sites being the most documented category.
Which files should I add SRI to?
SRI is for third-party files loaded over the network. Three categories matter, in priority order:
- Payment, checkout, and login flows. Any JavaScript that runs on a page where users enter credit cards, passwords or other sensitive data is the highest-priority target. A compromised script on a checkout page is the worst-case scenario. If your WooCommerce checkout loads anything from a CDN, every one of those scripts should have SRI.
- Globally embedded scripts. Anything in
<head>or near the top of<body>that runs on every page: analytics tags, fonts, polyfills, jQuery from a public CDN. These run before the user has a chance to notice anything wrong. - Plugin-injected CDN scripts. Many WordPress plugins (chat widgets, A/B testing, marketing pixels) load remote JavaScript. These are written by third parties you have implicitly trusted, and they typically do not include SRI by default.
Conversely, do not add SRI to files served from your own domain. If an attacker has access to modify files on your origin server, they can also modify the HTML that declares the hash, so SRI provides no real protection. SRI shines only for cross-origin resources.
How do I generate an SRI hash for a third-party script?
Three practical methods:
- Use srihash.org. Web-based tool. Paste the script URL, get back the full
<script>tag with integrity and crossorigin attributes. Fastest path for one-off additions. - OpenSSL on the command line.
curl -s https://cdn.example.com/file.js | openssl dgst -sha384 -binary | openssl base64 -Aoutputs the base64 hash you prepend withsha384-. Useful when scripting or working with files locally before deployment. - Check the provider's docs. Major CDNs (cdnjs.com, jsDelivr) publish the SRI hash next to every version of every library they host. Bootstrap, jQuery, Vue, React, etc. all publish the recommended integrity value on their official getting-started pages. Copy-paste from there.
One caveat: the hash is tied to the exact byte content of the file. If the CDN serves a different version (because you used a URL like jquery@3 instead of jquery@3.7.1), the hash will not match and the script blocks. Always pin to specific versions when using SRI.
Why is the crossorigin="anonymous" attribute required?
The crossorigin="anonymous" attribute tells the browser to fetch the third-party file using CORS, without sending cookies or authentication. Without it, the browser cannot read the file's response body to compute its hash (a same-origin policy quirk), and SRI verification silently fails open: the script runs without being checked.
This is the most common SRI mistake. People add integrity but forget crossorigin, then assume their setup works because the script keeps loading. Without both attributes, you have no actual protection. To verify: open DevTools, Network tab, click the script, look at the response. If the CDN supports CORS (essentially all modern public CDNs do), you will see Access-Control-Allow-Origin: * in the response headers. Without that header, SRI cannot work on that resource at all.
How do I add SRI to WordPress?
Three scenarios depending on how scripts get into your pages:
Scenario 1: scripts enqueued by WordPress (theme or plugin)
WordPress core supports SRI via the script_loader_tag filter. Add to your child theme's functions.php or a small mu-plugin:
add_filter('script_loader_tag', function ($tag, $handle, $src) {
$sri_hashes = [
'jquery' => 'sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs',
'bootstrap' => 'sha384-...your-hash-here...',
];
if (isset($sri_hashes[$handle]) && strpos($src, '://') !== false && strpos($src, home_url()) === false) {
$tag = str_replace(
' src=',
' integrity="' . $sri_hashes[$handle] . '" crossorigin="anonymous" src=',
$tag
);
}
return $tag;
}, 10, 3);Adjust the handle names and hashes to match your scripts. The strpos guards ensure SRI is only applied to scripts loaded from external domains, not your own.
Scenario 2: scripts hardcoded into theme templates
If a theme directly outputs <script src="https://..."> tags in header.php or elsewhere, edit those tags directly to add the integrity and crossorigin attributes. Mirror this in your child theme to survive parent theme updates.
Scenario 3: scripts injected by JavaScript or third-party plugins at runtime
Chat widgets, A/B testing tools, and tag managers often inject script tags dynamically. SRI still works in this case: the dynamically created <script> element must set the integrity and crossOrigin properties before the script gets appended to the DOM. Most enterprise versions of these tools support this via configuration; the free tiers typically do not. For unmanaged third-party injections, the practical fallback is a Content Security Policy with require-sri-for script (still in draft) or just careful auditing.
What is the maintenance burden of SRI?
This is the honest tradeoff. SRI is a tradeoff between security and convenience. Every time the upstream library updates, the hash changes, your script breaks, and you have to update the hash. For a stable site that pins versions and rarely updates them, this is a once-a-quarter task. For a site that uses jquery@latest or relies on auto-updating CDNs, SRI is a constant source of breakage.
Three patterns that make SRI maintenance manageable:
- Pin to specific versions, not "latest". URL like
https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js, notjquery@latest. The hash is then stable until you deliberately upgrade. - Use a CDN that publishes hashes. cdnjs and jsDelivr both publish the SRI hash for every file. Updating the hash when you upgrade is a 30-second task.
- Self-host critical libraries. Once you self-host (which you should consider for GDPR reasons anyway, see the Google Fonts discussion), SRI becomes irrelevant for that script. SRI is for cases where you cannot self-host. For analytics, fonts, libraries used on one page, self-hosting often is the better answer.
Common mistakes
- Forgetting
crossorigin="anonymous". The script keeps loading but is no longer integrity-checked. The most common silent SRI failure. - Using SRI on same-origin resources. An attacker who can modify your
/wp-includes/js/jquery.jscan also modify the HTML that declares the hash. Use SRI only on cross-origin resources. - Computing the hash on the wrong file version. The hash must match the exact bytes that the browser will receive, including any CDN-side minification or transformation. Always fetch from the actual production URL when computing.
- Not updating the hash on library upgrade. Upgrade the library version in the URL, forget to update
integrity, the script silently stops working. Symptoms: a feature breaks, the console shows "Failed to find a valid digest in the integrity attribute". - Using SHA-1. SHA-1 is collision-vulnerable and has been deprecated for SRI. Use SHA-384 or SHA-512.
- Trying to use SRI on a CDN without CORS. The browser cannot compute the hash, so SRI is impossible. Either the CDN must enable CORS, or you must self-host the file.
SRI and Content Security Policy (CSP)
SRI and CSP are complementary, not redundant. CSP says "only scripts from this list of origins are allowed to run". SRI says "and that script must match this exact hash". Together they form a defense-in-depth approach: CSP blocks unknown origins; SRI blocks tampering with known origins. A CSP with script-src 'self' https://trusted-cdn.com says "we trust trusted-cdn.com"; adding SRI hashes to your scripts on trusted-cdn.com narrows that trust to specific file versions.
The draft require-sri-for script CSP directive would enforce that every cross-origin script must have an integrity attribute, browser-level. As of 2026 it has limited support but is the direction the standard is heading.
What InspectWP checks
The Security section of every InspectWP report inspects external script and stylesheet tags and reports which ones include integrity attributes and which do not. Missing SRI on a script from a third-party CDN is flagged as a low-to-medium severity finding, depending on context. A login or checkout page loading external JavaScript without SRI is a higher-priority warning. The report also flags malformed integrity values (wrong algorithm prefix, invalid base64) which can give a false sense of protection while actually being ignored by the browser. SRI is one of those measures where the existence of the attribute matters less than its correctness; a wrong hash is functionally equivalent to no hash because the browser still rejects mismatches, but a missing crossorigin attribute makes the whole check silent.