Crawlsonar
Security & HTTPS2 min readUpdated 2026-07-09

Content-Security-Policy explained (with a safe rollout)

CSP is the strongest defence against XSS — and the easiest header to get wrong. Here's how it works, a safe starting policy, and how to reach a strict nonce-based CSP.

Content-Security-Policy (CSP) tells the browser exactly which sources of scripts, styles, images and other resources are allowed to load — so even if an attacker injects a <script>, the browser refuses to run it. It's the most effective mitigation for cross-site scripting (XSS), and the header most likely to block your own site if you rush it.

The key directives#

DirectiveControls
default-srcFallback for anything not otherwise specified
script-srcWhere scripts may load/run (the XSS-critical one)
style-srcStylesheets and inline styles
img-srcImages (allow https: for remote images)
connect-srcfetch/XHR/WebSocket destinations
frame-ancestorsWho may iframe you (replaces X-Frame-Options)
object-src / base-uriSet both to 'none' / 'self' to close injection vectors

A safe starting policy#

Deploy in report-only first — it reports violations without blocking anything:

Content-Security-Policy-Report-Only:
  default-src 'self';
  base-uri 'self';
  object-src 'none';
  frame-ancestors 'none';
  img-src 'self' data: https:;
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  connect-src 'self'

Watch the reports for a week, add the legitimate sources it flags, then switch the header name to Content-Security-Policy to enforce.

Reaching a strict CSP#

Allowing 'unsafe-inline' in script-src weakens the whole policy. The modern, strict approach is a per-request nonce plus 'strict-dynamic':

script-src 'nonce-RANDOM' 'strict-dynamic';
  • Your server generates a fresh random nonce per response and stamps it on every trusted <script nonce="…">.
  • 'strict-dynamic' lets those trusted scripts load others, so you don't have to allowlist every CDN.
  • Trade-off: a per-request nonce means pages can't be statically cached with a fixed nonce — weigh it against your performance needs.

Frequently asked questions

How do I add CSP without breaking my site?

Deploy it as Content-Security-Policy-Report-Only first. That reports violations to you but blocks nothing. Fix the legitimate sources it flags, then rename the header to Content-Security-Policy to start enforcing.

Is 'unsafe-inline' bad?

It defeats much of CSP's XSS protection because it allows any inline script to run. It's a pragmatic starting point, but the strict goal is a nonce (or hash) based script-src with 'strict-dynamic' and no 'unsafe-inline'.

Does CSP replace X-Frame-Options?

The frame-ancestors directive supersedes X-Frame-Options in modern browsers. Sending both is fine for older-browser coverage.

Do it with a free tool

Related guides

Published 2026-07-09 · Updated 2026-07-09 · By Crawlsonar.