Content-Security-Policy (CSP): Setup and Common Mistakes
Learn what Content-Security-Policy does, how to set up CSP safely, common CSP directives, report-only testing and mistakes that can break websites.
Introduction
Content-Security-Policy, or CSP, is an HTTP security header that tells browsers which resources are allowed to load on a website. It can control scripts, styles, images, fonts, frames, connections, media and other resource types.
A good CSP can reduce the impact of cross-site scripting, unwanted script injection and untrusted third-party resources. But CSP must be configured carefully. A policy that is too strict can break analytics, fonts, payment widgets, maps, videos, page builders, forms or other legitimate website features.
Quick answer
CSP controls which sources a browser may load resources from. Start with Content-Security-Policy-Report-Only, review blocked resources, allow only trusted sources, then move gradually to enforcement. Avoid broad wildcards and test scripts, styles, fonts, images, frames, forms and third-party tools before going live.
Content-Security-Policy
Content-Security-Policy is a browser security policy delivered through an HTTP response header.
It can restrict:
- JavaScript sources
- CSS/style sources
- image sources
- font sources
- iframe/frame sources
- API/connect sources
- form submission targets
- media sources
- object/embed sources
- base URL behavior
- who can embed your site
CSP does not remove vulnerabilities from code, but it can reduce what injected or unwanted code is allowed to do in the browser.
What CSP protects
CSP can help reduce risk from browser-side attacks and unsafe resource loading.
- cross-site scripting impact
- injected malicious scripts
- unauthorized third-party JavaScript
- clickjacking when using frame-ancestors
- mixed content loading
- unsafe plugin/object embeds
- data exfiltration through unexpected connections
- loading assets from untrusted domains
CSP is a defense-in-depth control. It should be used together with secure coding, input validation, updates and server hardening.
Important directives
default-src
Fallback rule for resource types that are not defined separately.
script-src
Controls where JavaScript can load from.
style-src
Controls CSS and style sources.
img-src
Controls image sources.
font-src
Controls font sources.
connect-src
Controls fetch, XHR, WebSocket and API connections.
frame-src
Controls what can be loaded inside frames.
frame-ancestors
Controls who can embed your site in an iframe.
form-action
Controls where forms can submit.
object-src
Controls legacy object/embed/plugin content.
base-uri
Restricts the base URL used by the document.
upgrade-insecure-requests
Asks browsers to upgrade HTTP resource requests to HTTPS.
Report-only mode
The safest way to introduce CSP is to start in report-only mode.
Content-Security-Policy-Report-Only
Report-only mode lets you see what the policy would block without actually breaking the website.
Use report-only to:
- discover required script sources
- discover required style sources
- identify third-party tools
- catch blocked fonts/images
- find broken embeds
- detect unexpected resources
- test policy changes safely
Do not start with a strict enforced CSP on a complex production website unless you already know every required resource.
Basic example
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' https:;
font-src 'self' https:;
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
form-action 'self';
This example allows resources mostly from the same site and HTTPS image/font sources, blocks legacy object embeds and prevents the site from being framed by unrelated domains.
This is only an illustrative starting point. It may break analytics, external fonts, embedded videos, payment widgets, maps or chat tools until those trusted sources are added.
CSP keywords
'self'
Allows resources from the same origin.
'none'
Allows nothing for that directive.
'unsafe-inline'
Allows inline scripts or styles. Often weakens CSP.
'unsafe-eval'
Allows eval-like JavaScript execution. Usually avoid when possible.
https:
Allows resources from HTTPS sources.
data:
Allows data URLs. Sometimes needed for images, but should be limited.
nonce
Allows specific inline scripts/styles with a server-generated nonce.
hash
Allows specific inline scripts/styles matching a hash.
Avoid adding unsafe-inline or unsafe-eval unless you understand why the site needs them.
Why this matters
CSP matters because modern websites often load scripts, styles, fonts, images and tools from many places. Without a policy, the browser has fewer rules for deciding which resources are trusted. If an attacker injects script into a page, a strong CSP can reduce what that script can load or execute.
CSP is especially useful for login pages, dashboards, checkout flows, SaaS apps, WordPress sites, admin panels and pages with user-generated content.
How to check CSP
Use HTTP Header Checker to inspect whether your site sends a Content-Security-Policy header.
Check:
- Header presence — Look for Content-Security-Policy or Content-Security-Policy-Report-Only.
- Final response — Check the final HTTPS page after redirects.
- Important pages — Test homepage, login, checkout, dashboard, forms and embedded pages.
- Browser console — Look for CSP violation messages.
- Third-party tools — Verify analytics, fonts, maps, videos, payments and chat widgets.
- Report-only logs — Review violation reports before enforcement.
- CDN/origin behavior — Confirm the header is not duplicated or overwritten.
Check your CSP
Use HTTP Header Checker to inspect whether your site sends a Content-Security-Policy header.
Common problems
CSP missing
MediumThe browser receives no resource-loading policy.
Next step: Start with a report-only policy and build from observed resources.
CSP too strict
HighLegitimate scripts, styles, fonts, images or embeds are blocked.
Next step: Review browser console violations and allow only trusted required sources.
unsafe-inline used broadly
MediumInline scripts/styles are allowed, reducing CSP protection.
Next step: Use nonces, hashes or refactor inline code where practical.
unsafe-eval required
MediumSome JavaScript relies on eval-like behavior, weakening protection.
Next step: Identify the dependency and remove or isolate it if possible.
Third-party scripts blocked
MediumAnalytics, chat, payment or tracking scripts do not load.
Next step: Add only the specific trusted domains needed.
Fonts or images missing
Lowfont-src or img-src does not include required asset sources.
Next step: Add trusted font/image CDNs or host assets locally.
Forms stop submitting
Highform-action blocks legitimate form targets.
Next step: Allow only trusted form endpoints.
Embeds stop working
Mediumframe-src or frame-ancestors blocks videos, maps or embedded tools.
Next step: Allow specific trusted embed domains.
Duplicate CSP headers
MediumCDN and origin send conflicting policies.
Next step: Manage CSP in one place or ensure policies are compatible.
Enforced too early
HighA strict policy was deployed before testing.
Next step: Switch to report-only, fix violations, then enforce gradually.
How to set up CSP
-
Step 1: Inventory resources
List scripts, styles, fonts, images, APIs, frames and form destinations your site uses.
-
Step 2: Start with report-only
Deploy Content-Security-Policy-Report-Only so violations are visible without breaking the site.
-
Step 3: Review violations
Use browser console and reports to identify required trusted sources.
-
Step 4: Allow specific sources
Prefer exact trusted domains instead of broad wildcards.
-
Step 5: Avoid unsafe patterns
Reduce unsafe-inline and unsafe-eval where practical.
-
Step 6: Test important flows
Check login, checkout, forms, dashboards, analytics, payment widgets and embeds.
-
Step 7: Enforce gradually
Move from report-only to enforcement after testing.
-
Step 8: Monitor after deployment
Watch console errors, user reports, analytics drops and CSP reports.
Before enforcement
Confirm these items before switching from report-only to enforced CSP.
Policy tested in report-only mode
Violations reviewed and understood.
Homepage works
Main page loads without CSP blocks.
Login works
Authentication flows are not blocked.
Forms submit
form-action allows trusted endpoints.
Checkout/payment works
Payment widgets and gateways load correctly.
Analytics works
Tracking scripts and beacons are allowed.
Fonts load
font-src and style-src include required sources.
Images load
img-src includes required asset hosts.
Videos/maps/chats work
frame-src and connect-src allow embeds.
No important console violations
Critical resources are not blocked.
CSP is not duplicated
CDN and origin do not send conflicting policies.
CDN/origin rules are consistent
One primary place manages the policy.
Report endpoint is monitored if used
Violation reports are reviewed.
fallback/default-src is defined
Default rule covers unspecified resource types.
object-src is restricted
Legacy embeds and plugins are limited.
frame-ancestors is configured
Clickjacking protection is in place.
Report-only example:
Content-Security-Policy-Report-Only:
default-src 'self';
script-src 'self' https://www.googletagmanager.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' https: data:;
connect-src 'self' https://www.google-analytics.com;
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
Stricter enforced example:
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' https:;
font-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
form-action 'self';
These examples are illustrative. Do not copy them blindly. Your required sources depend on your website, plugins, CDN, analytics and third-party integrations.
Nginx:
add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self';" always;
Apache:
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self';"
Report-only:
Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; report-uri /csp-report
CSP can be configured in the web server, CDN, application framework or hosting panel. Choose one primary place to avoid conflicts.
Syntax and support vary by server, CDN and framework. Test in staging where possible.
WordPress CSP
WordPress sites often need extra care because themes, plugins and page builders may load external resources.
- page builders
- caching plugins
- security plugins
- Google Fonts
- Google Analytics
- Tag Manager
- YouTube embeds
- Google Maps
- payment widgets
- contact forms
- chat widgets
- CDN-hosted assets
- inline scripts added by plugins
For WordPress, report-only mode is strongly recommended before enforcement because plugins can change resource loading after updates.
Third-party tools
Third-party tools often require multiple directives.
Analytics scripts
May need script-src, img-src and connect-src.
Video embeds
May need frame-src, img-src and script-src.
Payment tools
May need script-src, frame-src, connect-src and form-action.
Fonts
May need font-src and style-src.
Only allow the domains required by the provider’s documentation. Avoid adding unrelated domains just to silence errors.
Frequently asked questions
What does CSP do?
CSP tells browsers which resources are allowed to load on a page.
Can CSP break my website?
Yes. A strict policy can block legitimate scripts, styles, fonts, images, forms or embeds.
Should I use report-only first?
Yes, especially for complex sites, WordPress sites, e-commerce or sites using many third-party tools.
Is unsafe-inline bad?
It weakens CSP because inline code is allowed. Use nonces, hashes or code changes where practical.
Does CSP replace secure coding?
No. CSP is an extra protection layer, not a replacement for fixing vulnerabilities.
Where should CSP be configured?
Usually at the server, CDN, application or hosting level. Avoid conflicting duplicate policies.
What is a good first CSP?
Start with report-only, restrict object-src and base-uri, define default-src, then refine script/style/image/font/connect/frame rules.
Related tools
Use these free tools to verify your configuration after applying changes.
Related guides
Browse all Website Health guides →Need help applying this fix?
Send us your domain, report link or issue details. CheckDomainHealth will review the request and route it to the right technical team if hands-on support is needed.
Was this guide helpful?
Your feedback helps us improve our guides for everyone.
Thanks for your feedback!