

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Cross-Site Scripting (XSS)
incomplete
2: Fix Cross-Site Scripting
incomplete
3: Cross-Site Request Forgery (CSRF)
incomplete
4: CSRF Tokens
incomplete
5: Content Security Policy
incomplete
6: Legitimate Inline Scripts
incomplete
7: Sandboxing 'iframe' Elements
incomplete
8: Clickjacking
incomplete
9: Same-Origin and Referrer Policies
incomplete
10: Cross-Origin Resource Sharing
incomplete
11: CORS in Express
incomplete
12: Helmet
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Moving all your own JavaScript into same-origin external files is usually the simplest way to keep a strict CSP. When a trusted inline script really has to stay inline, authorize just that one script with a per-response nonce.
Generate a fresh, unpredictable value for every HTML response:
import { randomBytes } from "node:crypto";
const nonce = randomBytes(16).toString("base64");
res.locals.cspNonce = nonce;
Include the value in script-src:
Content-Security-Policy: script-src 'self' 'nonce-z7G4mN2qL8vP1sR5'
Then place the matching value on the trusted script element:
<script nonce="z7G4mN2qL8vP1sR5">
window.location.assign("/receipts/42");
</script>
The browser only executes inline scripts that carry the nonce from that response's policy. An attacker who can inject markup can't predict the next nonce, and an old nonce doesn't authorize a script in a new response.
Never reuse a fixed nonce or accept one provided from the client's request.
Bearly Secure already creates a fresh CSP nonce for every response and renders it on PawPal's trusted redirect script, but its policy ignores it. Allow only that nonce in script-src.
With Bearly Secure still running, run and submit the CLI tests from the project root.