The short version
Content Security Policy (CSP) is an HTTP header that tells the browser: "Only load scripts, styles, images, and other resources from these specific sources." If something tries to load from a source you didn't approve, the browser kills it.
Think of it like a bouncer at a club with a guest list. No list, no entry.
Why should you care?
Let's say someone finds a way to inject a <script> tag into your page. Without CSP, the browser happily runs it. It doesn't know the difference between your legitimate code and something an attacker slipped in.
With CSP, the browser checks the script's source against your policy. If it's not on the approved list, it gets blocked. This is why CSP is one of the most effective mitigations against cross-site scripting (XSS) attacks.
Note: CSP does not prevent XSS vulnerabilities from existing in your code. It limits the damage an attacker can do if they find one. It's defense-in-depth, not a fix for sloppy code.
How it works
You set CSP via an HTTP response header. Here's a basic example:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
This says:
- default-src 'self': By default, only load resources from your own domain.
- script-src 'self' https://cdn.example.com: Scripts can come from your domain or
cdn.example.com. Nothing else.
The MDN CSP reference lists all the directives you can use: style-src, img-src, font-src, connect-src, and more.
The most common mistakes
Using unsafe-inline and unsafe-eval. These directives basically tell the browser "ignore the policy for inline scripts and eval." They exist for backward compatibility, but they gut the protection CSP provides. The OWASP CSP Cheat Sheet warns against both.
Setting a policy that's too loose. A CSP of default-src * allows everything. That's not a policy, that's a suggestion.
Not using report-uri or report-to. CSP can send reports when it blocks something, so you know what's happening. Without reporting, you're flying blind.
How to get started
- Add the
Content-Security-Policy-Report-Onlyheader first. This logs violations without blocking anything. - Check your browser's console for CSP reports. You'll see what would be blocked.
- Tighten the policy gradually until only your legitimate resources are allowed.
- Switch from
Report-Onlyto the enforcingContent-Security-Policyheader.
Most hosting platforms (Vercel, Netlify, Cloudflare) let you set custom headers in their config files. If you're using a framework like Next.js or Astro, you can set them in your middleware or server config.
Quick reference
| Directive | Controls |
|---|---|
default-src | Fallback for all resource types |
script-src | JavaScript |
style-src | CSS |
img-src | Images |
connect-src | Fetch, XHR, WebSocket |
frame-src | Iframes |
Check your site
Want to know if your site has this issue? Scan it now and find out in 60 seconds.
Frequently Asked Questions
- What does Content Security Policy do?
- CSP tells the browser which sources of scripts, styles, images, and other resources are allowed to load on your page. If something tries to load from an unapproved source, the browser blocks it.
- Is CSP enough to prevent XSS?
- CSP is a strong layer of defense, but it's not a silver bullet. You still need to sanitize inputs and escape outputs. CSP acts as a safety net if something slips through.
- Does CSP break my site?
- It can, if configured incorrectly. Start with Content-Security-Policy-Report-Only to see what would be blocked without actually breaking anything.
Your AI writes the code. We find what it missed.
Paste your URL. Security audit in 60 seconds.
Scan my app