# Subresource Integrity hashes for third-party CDN scripts

- **Pattern:** `ab-002410` (`security-hardening.dependency-security.sri-hashes`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002410
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002410)

## Why it matters

Third-party scripts loaded from CDNs without Subresource Integrity (SRI) hashes execute in your users' browsers with full page access — if the CDN is compromised or the script URL is hijacked, attackers can inject arbitrary JavaScript. CWE-829 (Inclusion of Functionality from Untrusted Control Sphere) and OWASP A08 (Software and Data Integrity Failures) both flag this. NIST 800-53 SA-9 requires controls on external services. A CDN supply chain attack targeting jQuery, Bootstrap, or Font Awesome affects every user of every site loading that URL — SRI hashes prevent the browser from executing a tampered file.

## Severity rationale

Low because SRI failure only matters when the CDN is actively compromised, but when that occurs, every site loading the resource is immediately affected.

## Remediation

Generate SHA-384 hashes for each CDN resource and add `integrity` and `crossorigin` attributes:

```bash
curl -s https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js | \
  openssl dgst -sha384 -binary | openssl base64 -A
```

```html
<script
  src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
  integrity="sha384-<hash-here>"
  crossorigin="anonymous"
></script>
```

Prefer bundling CDN dependencies into your npm build (`npm install jquery`) and serving them self-hosted — this eliminates the CDN dependency entirely and makes SRI unnecessary. Most CDN providers list official SRI hashes on their documentation pages.

## Detection

- **ID:** `sri-hashes`
- **Severity:** `low`
- **What to look for:** Count all third-party scripts loaded from CDNs. For each, check for `<script>` and `<link>` tags that load resources from external CDNs (cdnjs, jsdelivr, unpkg, googleapis, bootstrapcdn). Verify these tags include `integrity` attributes with SHA-384 or SHA-256 hashes, and `crossorigin="anonymous"`.
- **Pass criteria:** All externally hosted scripts and stylesheets include `integrity` hashes. Hashes use SHA-384 or SHA-256 — 100% of CDN-loaded scripts must include integrity attributes. Report: "X CDN scripts found, all Y have SRI integrity hashes."
- **Fail criteria:** Any external CDN resource lacks an `integrity` attribute. Scripts loaded from CDNs without SRI.
- **Skip (N/A) when:** The application loads no third-party scripts or styles from CDNs — all assets are self-hosted or bundled.
- **Detail on fail:** `"Google Fonts stylesheet link lacks integrity attribute"` or `"3 CDN scripts in index.html have no SRI hashes: jQuery, Bootstrap, Font Awesome"`
- **Remediation:** Add integrity hashes to all CDN resources. Generate the hash:

  ```bash
  curl -s https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js | \
    openssl dgst -sha384 -binary | openssl base64 -A
  ```

  ```html
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
    integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs"
    crossorigin="anonymous"
  ></script>
  ```

  Consider migrating CDN dependencies into your npm bundle to eliminate CDN reliance entirely.

## External references

- cwe CWE-829
- owasp A08
- nist SA-9

Taxons: supply-chain

HTML version: https://auditbuffet.com/patterns/ab-002410
