Subresource Integrity: Pin Your CDN Scripts
Many sites load libraries such as jQuery, Bootstrap or Font Awesome from a public CDN. That code runs with the same power as your own: it can read form fields, change the page and send data anywhere. If the CDN, or the account that publishes the package, is ever compromised, every site that loads the file runs the attacker’s version.
Subresource Integrity (SRI) closes that gap. You add a cryptographic hash of the expected file to the tag, and the browser refuses to run or apply the file if its content does not match.
What it looks like
<script
src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js"
integrity="sha384-...base64 hash..."
crossorigin="anonymous"
></script>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
integrity="sha384-...base64 hash..."
crossorigin="anonymous"
/>
integrityholds the algorithm (sha256,sha384orsha512) and the base64 hash.sha384is the usual choice. You can list several hashes separated by spaces.crossorigin="anonymous"is required for cross-origin files; without it the browser cannot check the hash and blocks the file.
How to get the hash
From the CDN. cdnjs and jsDelivr show a “copy tag with SRI” option next to each file, and code.jquery.com prints the full tag including the hash.
Yourself, from the exact file you will load:
curl -s https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js \
| openssl dgst -sha384 -binary | openssl base64 -A
Prefix the result with sha384-.
Pin exact versions
SRI only works for files that never change. A URL such as .../npm/alpinejs@3/dist/cdn.min.js or
@latest resolves to a new file whenever the package is updated, the hash stops matching, and the
script stops loading. Always use a full version number in the URL, and update the hash together
with the version.
When SRI does not fit
Analytics, tag managers, chat widgets, payment SDKs and ad scripts are deliberately updated by the vendor at the same URL, so they cannot carry a fixed hash. For those, the options are to trust the vendor, limit what they can do with a Content Security Policy, or remove scripts you do not need. This is why our check only expects SRI on static CDN files.
The alternative to SRI is to self-host the library: copy the file into your own build and serve it from your domain. That removes the third party entirely and often loads faster too, since it avoids a connection to another host.
WordPress
Themes and plugins that load CDN files usually do it through wp_enqueue_script or
wp_enqueue_style, which do not add an integrity attribute. You can add one with the
script_loader_tag and style_loader_tag filters, but self-hosting the file (many plugins offer a
“load locally” option) is often simpler.
How PerfoMetrix checks this
We look at the script src and link rel="stylesheet" elements in the HTML we already downloaded.
We send no extra requests to your site and never download the scripts themselves.
Files on your own site are skipped. Files from these static public CDNs need an integrity
attribute: cdnjs, jsDelivr, unpkg, code.jquery.com, BootstrapCDN, Google Hosted Libraries,
Microsoft’s Ajax CDN, the DataTables CDN, Font Awesome’s CDN, RawGit and Statically. If any of them
lacks one, the check needs attention and lists up to five files.
Other third-party scripts and styles (analytics, tag managers, widgets) are counted and shown, but do not affect the result. We do not verify that a hash is correct; a wrong hash shows up as a blocked file in the browser console.
Further reading: MDN: Subresource Integrity and OWASP: Third-Party JavaScript Management.