All guides · Security

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"
/>
  • integrity holds the algorithm (sha256, sha384 or sha512) and the base64 hash. sha384 is 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.

Last updated October 28, 2026