LEARNING OBJECTIVES ⌵
- Implement a strict Content Security Policy (CSP Level 3) utilizing cryptographically random per-request nonces (
'nonce-...') and'strict-dynamic'. - Protect the application from Clickjacking attacks using the
frame-ancestors 'none'CSP directive and legacyX-Frame-Options: DENYheaders. - Guard against CDN tampering and supply-chain compromises using Subresource Integrity (SRI) (
integrity="sha384-..."withcrossorigin="anonymous"). - Implement browser defense-in-depth headers including
X-Content-Type-Options: nosniff,Referrer-Policy, and Permissions Policy.
📖 The Mental Model & Story (Intuitive Foundation)
Imagine a high-security sovereign embassy or military intelligence compound.
- The Guest Badge Verification System (CSP Nonces): Visitors cannot enter just because they claim to be a contractor. Every morning, the security officer issues a brand-new cryptographic single-use badge (a
nonce). Anyone found walking through the halls without that day's verified badge is immediately arrested and removed from the facility. Even if a spy leaves a USB stick with malicious code on a hallway desk, the computer system rejects it because it lacks the valid daily cryptographic badge. - The Tamper-Evident Cargo Seal (Subresource Integrity / SRI): When third-party medical supplies arrive from an external distributor, guards check the unbroken wax seal with a cryptographic hash. If a single pill has been modified in transit, the seal is broken and the shipment is incinerated before entering the building.
- The One-Way Soundproof Enclosure (
frame-ancestors 'none'/ Anti-Clickjacking): The ambassador's briefing room is enclosed in soundproof, opaque Faraday walls so nobody from the outside street can aim a laser microphone or drop a hidden transparent window over the conference table.
A production multi-tenant SaaS dashboard handles private server credentials, API tokens, and customer telemetry. If your HTML permits unvetted inline scripts, iframe framing, or compromised external CDNs, attackers can execute Cross-Site Scripting (XSS) and siphon tenant secrets.
In this lesson, we transform our HTML into a hardened fortress using CSP Level 3, SRI, and strict browser headers.
Technical Deep Dive & Specifications
1. CSP Level 3 Nonce Execution Flow & Top Layer Defense
+----------------------------------------------------------------------------------------------------+
| HTTP RESPONSE HEADERS |
| Content-Security-Policy: |
| default-src 'self'; |
| script-src 'self' 'nonce-rAnd0m123==' 'strict-dynamic'; |
| style-src 'self' 'nonce-rAnd0m123=='; |
| img-src 'self' data: https://assets.cloudmetrics.io; |
| connect-src 'self' wss://telemetry.cloudmetrics.io; |
| frame-ancestors 'none'; |
| base-uri 'none'; |
| form-action 'self'; |
+----------------------------------------------------------------------------------------------------+
|
v
+----------------------------------------------------------------------------------------------------+
| HTML DOCUMENT PARSER |
| ├── <script nonce="rAnd0m123=="> ... </script> ======> [MATCHES HEADER NONCE] ===> [EXECUTED] |
| ├── <script> alert(document.cookie) </script> ======> [NO NONCE] ============> [BLOCKED (XSS)] |
| ├── <script src="http://evil.com/xss.js"></script> ===> [UNAUTHORIZED HOST] ====> [BLOCKED] |
| └── <iframe src="https://cloudmetrics.io"> ======> [frame-ancestors 'none']=> [BLOCKED] |
+----------------------------------------------------------------------------------------------------+
2. Defense-in-Depth Security Headers Matrix
| HTTP Header / Tag | Recommended Value | Security Threat Neutralized |
|---|---|---|
Content-Security-Policy |
default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; frame-ancestors 'none'; |
Stored/Reflected XSS, unauthorized external resource injection, data exfiltration. |
X-Frame-Options |
DENY |
Clickjacking attacks in legacy browsers. |
X-Content-Type-Options |
nosniff |
MIME-type confusion attacks and executable polyglots. |
Referrer-Policy |
strict-origin-when-cross-origin |
Leaking sensitive URL query parameters and tenant IDs to third-party domains. |
Permissions-Policy |
camera=(), microphone=(), geolocation=(), payment=() |
Disables browser hardware APIs not required by the SaaS application. |
<meta http-equiv="..."> |
<meta http-equiv="Content-Security-Policy" content="..."> |
Fallback CSP enforcement when backend HTTP headers cannot be modified directly. |
3. Subresource Integrity (SRI) Mechanics
When importing external vendor libraries from public CDNs (e.g. charts or icons), compute the Base64 SHA-384 hash of the file content:
<!-- Cryptographically Verified External Asset -->
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"
integrity="sha384-9548486f0284d720b080f4f95430882e3b2b93081e3a479ff73714b72ef78484"
crossorigin="anonymous">
</script>
If an attacker compromises the CDN and modifies even 1 byte in the script file:
- The browser computes
SHA384(downloaded_file). - The hash does not match the
integrityattribute. - The browser immediately rejects and destroys the script before execution.
💻 Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 8–18 (
<meta http-equiv="Content-Security-Policy" content="...">): Configures the CSP policy directly within the HTML header, locking down script origins, WebSocket endpoints, and framing permissions. - Line 10 (
script-src 'self' 'nonce-...' 'strict-dynamic'): Activates modern CSP Level 3. Any script with the cryptographic nonce is executed, and'strict-dynamic'permits that trusted script to load trusted child dependencies dynamically. - Line 14 (
frame-ancestors 'none'): Prevents any third-party website from rendering this dashboard inside an<iframe>, eliminating Clickjacking attacks. - Line 15 (
base-uri 'none'): Prevents attackers from injecting<base href="https://evil.com">to rewrite relative URLs across the application. - Lines 49–54 (
<script integrity="sha384-..." crossorigin="anonymous" nonce="...">): Applies Subresource Integrity. The browser verifies the SHA-384 hash before executing the CDN bundle. - Line 87 (
<script nonce="EDN40JY8m2SL8840A6gU3m6w==">): Matches the CSP nonce specified in the header; the browser authorizes execution.
Expected Browser Render Output
+----------------------------------------------------------------------------------------------------+
| APPLICATION SECURITY HEALTH & CSP AUDITS [Hardened (A+)] |
| |
| This document enforces strict per-request nonces, preventing inline XSS injection. |
| |
| • CSP Level 3 Nonce: Active (nonce-EDN40...) |
| • Subresource Integrity: SHA-384 Verified on external CDNs |
| • Clickjacking Defense: frame-ancestors 'none' enforced |
| • Referrer Policy: strict-origin-when-cross-origin |
| |
| ✓ Nonce-authorized JavaScript executed successfully. |
+----------------------------------------------------------------------------------------------------+🏋️ Hands-On Exercise
🎯 The Challenge: Subresource Integrity (SRI) Hash Verification
You are loading an external CSS framework from a CDN. Your task is to calculate the proper HTML markup with SRI hash attributes to protect your users against supply-chain tampering.
Instructions:
- Given a stylesheet at
https://cdn.example.com/theme.csswith known SHA-384 hashdGVzdC1oYXNoLTEyMzQ1Njc4OWFiY2RlZg==. - Write the secure
<link>tag includingintegrityandcrossoriginattributes. - Configure a CSP
style-srcpolicy that authorizes this stylesheet while rejecting untrusted styles.
🏁 Starter Code Sandbox
⚠️ Common Pitfalls
- Using Static Hardcoded Nonces: A nonce must be a cryptographically random Base64 string generated freshly on every single HTTP request. Reusing a static nonce completely nullifies CSP protection.
- Forgetting
crossorigin="anonymous"withintegrity: Omittingcrossorigin="anonymous"when applying SRI to cross-origin CDN links causes the browser to block the asset due to CORS security checks. - Using
'unsafe-inline'inscript-src: Including'unsafe-inline'without a nonce disables CSP's ability to protect against inline Cross-Site Scripting.
💡 Pro Tips
- CSP Reporting via
report-to: Configurereport-uri /api/csp-violationsor the newerReporting-Endpointsheader to stream real-time JSON reports to your security telemetry backend when an XSS attempt is blocked. - Permissions-Policy Lockdown: Explicitly disable unused hardware sensors (
camera=(), microphone=(), usb=()) in headers to prevent compromised third-party scripts from activating device hardware.
📌 Key Takeaways
- CSP Level 3 with per-request nonces (
'nonce-...') and'strict-dynamic'is the gold standard for XSS defense. - Subresource Integrity (SRI) with
integrity="sha384-..."protects applications against compromised third-party CDNs. - Clickjacking must be prevented using
frame-ancestors 'none'in CSP andX-Frame-Options: DENY. base-uri 'none'prevents attackers from manipulating relative link resolution.- All cross-origin assets verified with SRI require
crossorigin="anonymous". - --