Content Security Policy Deployment Guide
Copy-paste CSP examples for every major platform — Apache, Nginx, WordPress, Node.js, Cloudflare and Vercel. Every snippet on this page uses a generic starter policy; to generate one tailored to your actual website, run a free scan.
Content-Security-Policy-Report-Only first. The browser logs violations to the console without blocking anything. Monitor for 1–2 weeks, fix the warnings, then switch to the enforcing Content-Security-Policy header. This prevents breaking your site the moment you roll out.
Platforms
Jump to the platform you're using:
- Apache (
.htaccess) — detailed guide → - Nginx — detailed guide →
- WordPress (
functions.php) — detailed guide → - Node.js / Express
- Cloudflare Transform Rule
- Vercel (
vercel.json)
Apache (.htaccess)
The most common deployment target. Drop this in the .htaccess file at your document root. Make sure mod_headers is enabled.
<IfModule mod_headers.c>
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'"
</IfModule>
Once you're confident the policy doesn't break anything, switch Content-Security-Policy-Report-Only to Content-Security-Policy to start enforcing.
Nginx
Add this inside your server { } block (typically in /etc/nginx/sites-enabled/your-site):
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'" always;
The always flag ensures the header is set on error responses too (404, 500), not just successful ones.
WordPress (functions.php)
Add this to your theme's functions.php (or better: a custom plugin, so a theme update doesn't wipe it out):
add_action('send_headers', function() {
header("Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'");
});
WordPress almost always needs 'unsafe-inline' in script-src and style-src because core, themes and many plugins rely on inline scripts and styles.
Read the full WordPress guide →
Node.js / Express
Set the header via Express middleware. For anything beyond a trivial app, use the Helmet package which handles edge cases for you.
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy-Report-Only',
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'"
);
next();
});
Cloudflare Transform Rule
In the Cloudflare dashboard: Rules → Transform Rules → Modify Response Header → Create rule. Add a "Set static" action:
Header name: Content-Security-Policy-Report-Only
Value: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'
Transform Rules are available on the Free plan (limited quota). For higher volume use a Cloudflare Worker instead. → Full guide: CSP on Cloudflare — covers Set vs. Add, Email Obfuscation and Rocket Loader caveats, and the Worker pattern for nonces.
vercel.json
Add a headers entry to your project's vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy-Report-Only",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'"
}
]
}
]
}
Redeploy after committing — headers are applied at the edge.
Get a CSP tailored to your site → Free scan · covers every resource your site actually loads · copy-paste snippets for all platforms aboveWhy the generic example isn't enough
The policy above uses default-src 'self', which blocks everything that doesn't come from your own origin. Real websites load Google Fonts, analytics, embedded videos, maps, chat widgets and so on — each of which needs to be whitelisted explicitly. Guessing wrong breaks the site, and a too-permissive policy defeats the whole point of CSP.
That's why a one-size-fits-all CSP doesn't work. Our scanner crawls your site, finds every external resource it actually loads, and generates the tightest possible policy that still keeps everything working — plus the copy-paste deployment snippet for your stack.