Third-party scripts without Subresource Integrity

Scripts or stylesheets are loaded from third-party hosts without an integrity attribute. If that host is compromised or changes hands, the modified file runs on your page unchallenged.

Do this: Add integrity and crossorigin attributes to third-party scripts. If the CDN is compromised or hijacked, the altered script runs with full access to your page. Open the page you need
PassThird-party scripts and stylesheets carry Subresource Integrity hashes.
LowThird-party scripts or stylesheets are loaded without Subresource Integrity.

The fix, in one snippet

Example to adapt Pin the exact file you reviewed
<script src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"></script>

Illustrative values. Change the paths, hostnames and options to match your own site before using it.

The sections below explain what is tested, why it matters and the alternatives.

What we test

Scan.now parses the homepage for <script src> and <link rel="stylesheet" href> elements whose host is outside the page's registrable domain. For each one it checks for an integrity attribute, validates its format (sha256-, sha384- or sha512- followed by base64), and checks for crossorigin="anonymous", without which browsers cannot verify a cross-origin file and refuse to load it. Elements lacking integrity fail the check at low severity. Scan.now does not fetch the files to recompute hashes. It also recognises scripts that are designed to change without notice, such as Google Tag Manager, gtag.js and most analytics loaders, and notes that SRI cannot be applied to them; for those, a strict Content-Security-Policy and vendor trust are the controls. A full list of third-party hosts is in external-scripts-inventory.

Why it matters

Loading a script from a CDN means trusting the CDN operator, its DNS, its TLS certificate and every future owner of the domain, permanently. In June 2024 the domain polyfill.io, whose script was embedded on more than a hundred thousand sites, was sold and began serving code that redirected visitors to scam pages, as reported by Sansec. In 2018 the British Airways payment page was skimmed through a modified copy of a script the site loaded from a third party. Subresource Integrity binds the tag to a specific hash: if the delivered bytes differ, the browser refuses to execute them and the page degrades rather than the attacker succeeding. It costs nothing at runtime and is supported by every current browser. The SRI guide covers generating hashes and the limits of the technique.

How to fix it

Compute the hash of the exact file you reference and add it to the tag:

curl -s https://cdn.example.com/lib/1.2.3/lib.min.js | openssl dgst -sha384 -binary | openssl base64 -A
<script src="https://cdn.example.com/lib/1.2.3/lib.min.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Pin the URL to a version, never to latest, or the hash will stop matching at the next release. Most CDNs (cdnjs, jsDelivr) display the SRI hash next to each file. In a build pipeline, webpack's webpack-subresource-integrity plugin and Vite's equivalents emit hashes automatically:

// webpack.config.js
const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity');
module.exports = {
  output: { crossOriginLoading: 'anonymous' },
  plugins: [new SubresourceIntegrityPlugin()],
};

Where a vendor script cannot be pinned, self-host a vetted copy and update it deliberately, or isolate the vendor in an iframe. Combine SRI with a CSP script-src that lists only the hosts you expect, so an unpinned tag cannot simply be added elsewhere.

Where this fits

Third-party scripts without Subresource Integrity is check 7 of 10 that the website vulnerability scanner runs under page content and javascript, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.

Fix this one first

Above it in the same category sits Sensitive information in HTML comments (low), where hTML comments in the page source contain material that looks internal: Credentials, TODO notes, internal hostnames or IP addresses, file paths, or links to unpublished areas of the site. An attacker who has that does not need this, so it is the better use of the same hour.

What fixing this still leaves open

Third-party scripts without Subresource Integrity closes one route in. Immediately below it: Inline event handlers and scripts, where the page relies on inline scripts, on* event-handler attributes or javascript: URLs; Password field autocomplete, where password fields on the page either try to disable autocomplete, which browsers ignore and password managers dislike, or lack the autocomplete tokens that let password managers fill and generate credentials safely; Third-party script inventory, where an inventory of every script the page loads from other domains.

Found in the same scan

The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and Exposed .env configuration file, where a .env configuration file is served from the web root. A single run of website vulnerability scanner answers all of them at once.

Prompt for an AI Hand this check to an assistant Sign in to copy it
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.

Finding: Third-party scripts without Subresource Integrity (low severity)
Scanner check id: subresource-integrity
19 more lines, including the evidence and the exact fix

The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.

Sign in with Google

Signing in is free and takes one click. We store your email address and nothing else.

References

  1. MDN: Subresource Integrity
  2. W3C: Subresource Integrity
  3. Sansec: Polyfill supply chain attack
  4. SRI Hash Generator

Related guides