Content Security Policy for WordPress — Without Breaking Plugins
WordPress is one of the hardest platforms for CSP because plugins and themes add inline scripts that you do not control. The practical approach: start with report-only, collect violations for a week, then enforce.
Step 1 — Start with report-only mode
Never deploy an enforcing CSP on WordPress without testing first. Use report-only to collect violations without breaking anything:
# Nginx — add to your WordPress server block add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; report-uri /csp-violations;" always;
Open your browser console. Visit several pages of your site — home, shop, checkout, blog. Every CSP violation will appear in the console as an error message. Note down every blocked domain.
Step 2 — Add CSP via WordPress hook
// functions.php
add_filter('wp_headers', function($headers) {
$headers['Content-Security-Policy-Report-Only'] =
"default-src 'self'; " .
"script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; " .
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " .
"font-src 'self' https://fonts.gstatic.com; " .
"img-src 'self' data: https:; " .
"connect-src 'self' https://www.google-analytics.com;";
return $headers;
});
Common WordPress plugin domains to allowlist
| Plugin | Domains to add |
|---|---|
| WooCommerce | script-src + 'unsafe-inline'; connect-src + your store domain |
| Elementor | script-src + 'unsafe-inline'; style-src + 'unsafe-inline' |
| Yoast SEO | script-src + 'unsafe-inline' |
| Contact Form 7 | script-src + 'unsafe-inline' |
| Jetpack | script-src + https://stats.wp.com; connect-src + https://jetpack.wordpress.com |
Reality check on WordPress CSP
Most WordPress sites end up needing 'unsafe-inline' in script-src and style-src because plugins inject inline content without nonces. This is not ideal — but a CSP that allows only known external domains is still better than no CSP at all. It blocks external script injection even if it cannot block inline attacks.
If you need a strict CSP, consider a headless WordPress setup where the frontend is a separate Next.js or Nuxt app — you control all the inline scripts there.
Scan your WordPress site → CSPFixer