A Content Security Policy is one of the most effective protections you can add to a website, and it's usually just a single response header. Here's what it does, why it matters, and how to roll one out without breaking your site.
The problem it solves
Cross-site scripting (XSS) is one of the oldest and most damaging web vulnerabilities. If an attacker can get their JavaScript to run on your page — through a comment field, a URL parameter, or a compromised third-party script — that code runs with full access to your visitors' session: it can steal login cookies, capture what they type into a checkout, or quietly redirect them. A Content Security Policy is the browser-level backstop against this.
How a CSP works
A CSP is an allow-list. You tell the browser, via the Content-Security-Policy header, exactly which origins are permitted to provide scripts, styles, images, fonts and so on. The browser then refuses to load or execute anything from anywhere else — including inline scripts an attacker might inject. A simple starting policy looks like this:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://js.stripe.com;
style-src 'self' https://fonts.googleapis.com;
img-src 'self' data:;
object-src 'none';
base-uri 'self'
This says: load everything from my own domain by default; allow scripts only from my domain and Stripe; allow styles from my domain and Google Fonts; block plugins entirely; and lock down the page's base URL. Anything an attacker injects from elsewhere simply won't run.
Roll it out safely with report-only mode
The one risk with a CSP is being too strict and accidentally blocking something your own site needs. That's what report-only mode is for. Send the policy as Content-Security-Policy-Report-Only instead, and the browser will report what it would have blocked without actually blocking anything. Watch those reports, add the legitimate sources you missed, and once it's clean, switch the header to the enforcing version.
Common gotchas
- Inline scripts and styles. A strict policy blocks inline
<script>blocks andonclick=handlers. The best fix is to move JavaScript into external files; if you can't, use nonces or hashes rather than falling back to'unsafe-inline'. - Third-party widgets. Analytics, chat and embed scripts each need their origins added. This is also a useful audit of what you're actually loading.
- Forgetting to test. Always trial in report-only mode first, especially on a site you didn't build yourself.
Where to add it
A CSP is set as an HTTP response header, so it's configured wherever your responses are served: your web server (Nginx, Apache), your CDN or platform (Cloudflare, Netlify, Vercel), or your application framework. A <meta> tag version exists but is more limited — the header is preferred.
People also ask
What does a Content-Security-Policy header do?
It tells the browser which sources of scripts, styles and other content are allowed on your pages. Anything not on the list is blocked, which stops injected or malicious scripts running.
How do I add a CSP to my website?
Send a Content-Security-Policy response header from your server, CDN or platform. Begin in report-only mode, refine until it's clean, then enforce it.
What is CSP report-only mode?
Content-Security-Policy-Report-Only applies the policy without blocking anything and reports what would have been blocked — a safe way to test before enforcing.
Does a CSP stop all cross-site scripting?
No single control is complete. A strong CSP greatly reduces XSS impact but works best alongside proper input handling, output encoding and up-to-date software.
Not sure whether your site has a CSP?
Our audit checks your security headers and shows you exactly what to add — in plain English.
Get my security audit · $300