If you’ve ever run a security scan on your WordPress site, you’ve probably seen a warning about a missing Content Security Policy. It sounds intimidating. It is also one of the few security headers that can completely break your site if you implement it wrong.
Here’s what CSP actually is, why it matters, and how to add one that works — without taking your site down in the process.
What is a Content Security Policy?
A Content Security Policy is an HTTP response header that tells browsers which sources of content are allowed to load on your page. Think of it as a whitelist. If a script, stylesheet, image, or font tries to load from a domain you haven’t approved, the browser blocks it.
The main threat it protects against is Cross-Site Scripting (XSS) — where an attacker injects malicious code into your page. Even if the injection happens, a properly configured CSP can prevent that code from doing anything.
Why WordPress Makes This Tricky
WordPress loads resources from a lot of places — your theme, plugins, Google Fonts, embedded videos, payment widgets. A strict CSP will block all of it unless you explicitly allow each source.
Page builders like Elementor make this worse because they inject inline scripts and styles that CSP blocks by default. This is one of the reasons we moved away from page builders entirely on our custom builds.
Start With Report-Only Mode
Never enforce a CSP on a live site without testing first. Add this to your functions.php:
add_action( 'send_headers', function() {
header( "Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src * data:;" );
} );
Report-Only mode logs violations to your browser console without blocking anything. Open DevTools, load your site, and note every CSP violation that appears. Each one is a domain you need to whitelist.
Build Your Whitelist
Once you know what your site actually loads, build your enforced header. A typical WordPress site without a page builder looks something like this:
$csp = implode( '; ', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline'",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com data:",
"img-src * data:",
"connect-src 'self'",
"frame-src https://www.youtube.com https://www.google.com",
"object-src 'none'",
] );
header( "Content-Security-Policy: {$csp}" );
If you use Google Tag Manager, add https://www.googletagmanager.com to script-src. If you embed Vimeo, add https://player.vimeo.com to frame-src. Every third-party service needs its own entry.
The Honest Tradeoff
unsafe-inline is technically a weaker CSP because it allows inline scripts. A stricter approach uses nonces, but that requires server-side work on every request and breaks most WordPress plugins. For most small business WordPress sites, unsafe-inline with a solid domain whitelist is a meaningful improvement over having no CSP at all.
Start with Report-Only. Build your whitelist. Enforce it. Then run your security scan again — you’ll see the difference.
If you’ve ever run a security scan on your WordPress site, you’ve probably seen a warning about a missing Content Security Policy. It sounds intimidating. It is also one of the few security headers that can completely break your site if you implement it wrong.
Here’s what CSP actually is, why it matters, and how to add one that works — without taking your site down in the process.
What is a Content Security Policy?
A Content Security Policy is an HTTP response header that tells browsers which sources of content are allowed to load on your page. Think of it as a whitelist. If a script, stylesheet, image, or font tries to load from a domain you haven’t approved, the browser blocks it.
The main threat it protects against is Cross-Site Scripting (XSS) — where an attacker injects malicious code into your page. Even if the injection happens, a properly configured CSP can prevent that code from doing anything.
Why WordPress Makes This Tricky
WordPress loads resources from a lot of places — your theme, plugins, Google Fonts, embedded videos, payment widgets. A strict CSP will block all of it unless you explicitly allow each source.
Page builders like Elementor make this worse because they inject inline scripts and styles that CSP blocks by default. This is one of the reasons we moved away from page builders entirely on our custom builds.
Start With Report-Only Mode
Never enforce a CSP on a live site without testing first. Add this to your functions.php:
add_action( 'send_headers', function() {
header( "Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src * data:;" );
} );
Report-Only mode logs violations to your browser console without blocking anything. Open DevTools, load your site, and note every CSP violation that appears. Each one is a domain you need to whitelist.
Build Your Whitelist
Once you know what your site actually loads, build your enforced header. A typical WordPress site without a page builder looks something like this:
$csp = implode( '; ', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline'",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com data:",
"img-src * data:",
"connect-src 'self'",
"frame-src https://www.youtube.com https://www.google.com",
"object-src 'none'",
] );
header( "Content-Security-Policy: {$csp}" );
If you use Google Tag Manager, add https://www.googletagmanager.com to script-src. If you embed Vimeo, add https://player.vimeo.com to frame-src. Every third-party service needs its own entry.
The Honest Tradeoff
unsafe-inline is technically a weaker CSP because it allows inline scripts. A stricter approach uses nonces, but that requires server-side work on every request and breaks most WordPress plugins. For most small business WordPress sites, unsafe-inline with a solid domain whitelist is a meaningful improvement over having no CSP at all.
Start with Report-Only. Build your whitelist. Enforce it. Then run your security scan again — you’ll see the difference.