Content Security Policy (CSP) is an HTTP response header that tells browsers which sources may load scripts, styles, images, frames, and other assets. Used carefully, it limits what injected code can do. Used carelessly, it breaks Analytics, fonts, embeds, and the WordPress admin.
Security Ninja Pro can set related headers from Security Ninja → Fixes. Prefer report-only mode while you tune a policy. See also Security headers.
Why WordPress sites use CSP
A typical WordPress page loads assets from the theme, plugins, CDNs, fonts, and analytics. Without CSP, the browser will run injected JavaScript the same way it runs legitimate scripts. CSP cannot fix every plugin hole, but it raises the bar after injection.
How CSP works
A basic policy:
Content-Security-Policy: script-src 'self'
That allows scripts only from your own origin. External or injected scripts are blocked (or reported, in report-only mode).
Useful directives
default-src- Fallback for resource types you did not list
script-src- Allowed JavaScript sources
style-src- Allowed CSS sources
img-src- Allowed image sources
font-src- Allowed font sources
connect-src- AJAX, fetch, WebSocket, EventSource
frame-src- Embedded frames (YouTube, maps, payment widgets)
object-src- Plugins such as Flash; usually
'none' form-action- Allowed form submission targets
frame-ancestors- Who may embed your pages (clickjacking related)
report-uri/ reporting APIs- Where browsers send violation reports
Example policies
HTTPS-only baseline (weak XSS control):
Content-Security-Policy: default-src https:
Common CDN allowlist (still often needs tuning):
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;
Strict starting point (will break many WordPress sites until you add sources):
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';
Keywords
'none'- Block all of that type
'self'- Same origin (not every subdomain)
'unsafe-inline'- Allows inline script/style; weakens CSP
'unsafe-eval'- Allows
eval()-style APIs; weakens CSP
Prefer nonces or hashes over 'unsafe-inline' when you can. Many WordPress plugins still need temporary exceptions.
Test before you enforce
Use report-only mode first:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri https://yoursite.com/csp-report
You can send an enforcing header and a report-only header at the same time while you trial a stricter policy. Do not trust violation report payloads blindly; rate-limit any endpoint that accepts them.
WordPress-specific issues
- Inline scripts and styles in themes and plugins often need
'unsafe-inline', nonces, or refactoring. - Third-party services (Analytics, fonts, chat, ads) each need explicit allowlist entries.
- wp-admin uses many inline scripts. Consider a looser policy for admin URLs than for the public site.
- YouTube / maps embeds need
frame-src(and sometimes Referrer-Policy adjustments). See YouTube Error 153.
Example allowlist fragments:
script-src https://www.google-analytics.com
font-src https://fonts.gstatic.com
style-src https://fonts.googleapis.com
frame-src https://www.youtube.com
How to add the header
Apache (.htaccess):
Header set Content-Security-Policy "default-src 'self';"
Theme or small plugin:
add_action(
'send_headers',
function () {
header( "Content-Security-Policy: default-src 'self';" );
}
);
Security Ninja Pro: enable and tune CSP-related options under Security Ninja → Fixes.
Practical checklist
- Start in report-only mode.
- Watch the browser console and violation reports.
- Add only the sources you need.
- Avoid broad wildcards such as
https://*. - Include
data:inimg-srcif your theme uses data URIs. - Retest after installing or updating plugins.
- Keep CSP as one layer. Updates, strong auth, and the firewall still matter.