Browser security boundaries
Add a Content Security Policy
Use CSP to restrict script and resource execution while keeping output handling and application design as the primary XSS defenses.
A Content Security Policy limits what a page is allowed to load and execute. It is a strong second layer. Treat it as defense in depth behind correct output handling, not as permission to render unsafe HTML.
The mistake is to enable enforcement on day one and break the site. Start in report-only mode instead, so violations are reported but nothing is blocked while you learn what the page really needs.
Content-Security-Policy-Report-Only:
default-src 'self'; script-src 'self'; report-uri /csp-report
Point report-uri at an endpoint and read what arrives. Each report names the blocked resource and the directive that would have stopped it, so you build the real policy from evidence rather than guessing.
Move toward nonces, not exceptions
Once you understand the page, switch to enforcement and let inline scripts run through a per-response nonce rather than opening unsafe-inline.
const nonce = crypto.randomBytes(16).toString('base64')
res.set('Content-Security-Policy',
`default-src 'self'; script-src 'self' 'nonce-${nonce}'`)
<script nonce="RANDOM_PER_RESPONSE">/* only this inline script runs */</script>
A new analytics script requires unsafe-inline, so the team adds it to script-src. That exception also lets an injected inline script run across the site.
A strict policy can break checkout or sign-in if required sources are missed. Start in report-only mode, then replace broad exceptions with nonces, hashes, or removed scripts.
Deploy a report-only policy and exercise the home, sign-in, and checkout paths. Record required violations, remove one unnecessary source, then test that an injected inline script is blocked under enforcement.
Lesson completed