Skip to content

Test your website now

Free, no card. We read only public pages.

Run free audit →

Security

What is a Content Security Policy, and how do you add one?

A Content Security Policy tells the browser which scripts and resources may run on your page. How to roll one out safely, and which directives matter.

A Content Security Policy, CSP, is a response header that tells the browser which sources of scripts, styles, images and frames your page may load, and blocks everything else. Its main job is limiting cross-site scripting. Roll it out safely by starting in report-only mode, fixing what it reports, then enforcing it with nonces for inline scripts.

Published · Last updated

By Michal Měřínský. Audit methodology.

What a CSP does

Without a policy, a browser runs any script that ends up in your page, including one an attacker injected. A CSP is an allowlist. With it, an injected script from an unknown source, or an inline script without the right nonce, is blocked and reported in the console instead of running.

A starting policy

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-{random-per-request}' 'strict-dynamic';
  object-src 'none';
  base-uri 'self';
  frame-ancestors 'self'
  • default-src is the fallback for every resource type you do not list.
  • script-src with a per-request nonce lets your own inline scripts run while injected ones fail. strict-dynamic lets trusted scripts load what they need.
  • object-src 'none' removes old plugin content.
  • base-uri stops an injected base tag from redirecting relative URLs.
  • frame-ancestors controls who may embed your site, replacing X-Frame-Options.

Rolling it out without breaking the site

  • Start with Content-Security-Policy-Report-Only. The browser reports violations and blocks nothing.
  • Run it for a week of real traffic and read the reports. That is where you find the analytics, chat widget and payment script nobody listed.
  • Add what is legitimate, remove what is not, then switch to the enforcing header.
  • Keep a report endpoint, so new violations after releases are visible.

A policy containing 'unsafe-inline' for scripts, without a nonce or hash, allows exactly the injected scripts CSP exists to stop.

Common problems

  • Tag managers that load arbitrary scripts, which effectively require a very loose policy.
  • Frameworks that add inline scripts for hydration, which need nonce support configured.
  • 'unsafe-eval', required by some older libraries, which weakens the policy.
  • A Report-Only header left in place forever, which protects nothing.

What a scan can and cannot tell you

WebAuditOS fails pages without an enforcing CSP, warns when a policy does not restrict scripts or allows unsafe inline scripts without a nonce or hash, and checks unsafe-eval, default-src, object-src, base-uri, and a Report-Only header used without an enforcing one.

It reads the policy, not its effect. It cannot tell whether an allowed domain hosts content an attacker could use, or whether your site still works under the policy.

A strict policy on paper and a broken checkout in practice is a real risk. Test key journeys before enforcing.

Short answers

Does CSP prevent XSS? It limits what an XSS bug can do. It does not fix the bug.

Is a CSP required? Not by law, but it is the strongest browser-side defence against script injection.

Can CSP break my site? Yes, if enforced before testing. Start in report-only mode.

CSP in a meta tag or header? Prefer the header. Some directives, such as frame-ancestors, do not work in meta tags.

In the product

The checks this maps to

Every check named here runs on every scan, on every plan - what a plan changes is how many pages are crawled, how long the history is kept and what you can do with the result. These are the ids the findings carry, so you can match a line in a report to the explanation above.