
Content Security Policy: what does CSP do?
7 min read below · WebYes knowledge base
Content Security Policy (CSP) limits which scripts and resources your site may load. How CSP fights XSS, report-only vs enforce, and what WebYes checks.
Content Security Policy (CSP) is an HTTP header that tells the browser which scripts, styles, images and frames may load. That limits the damage from cross-site scripting: even if an attacker injects code, it often may not run. Start in report-only, tighten, then enforce. The WebYes scan checks CSP within the security pillar, alongside HSTS and the other security headers.
What does Content Security Policy actually do?
A Content Security Policy is a set of rules your server sends with every page. Per resource type (scripts, stylesheets, images, fonts, frames, connections) you define an allowlist: only these domains, or only your own origin. Per the MDN guide to CSP, the browser refuses anything outside that list. The core idea: do not trust whatever appears in the HTML; trust only what the policy allows.
That mainly targets cross-site scripting (XSS). With XSS, an attacker gets script into your page: via a comment field, an open redirect, an outdated plugin. Without CSP, the browser runs that script. With a strict CSP, the script may not come from a foreign source, and inline script often may not start at all. The injection can still sit in the markup, but the browser blocks execution.
OWASP stresses the same point: CSP makes vulnerabilities harder to exploit, but it does not replace secure code. Input filtering, output encoding and updates remain necessary. CSP is a safety net, not a lock on the front door. See the OWASP CSP Cheat Sheet for that nuance and for recommended directives.
CSP does not stand alone. Without HTTPS and HSTS, traffic can still be intercepted or a first unencrypted hit remains possible. That foundation is covered in our pages on SSL certificates and security headers. CSP governs what may run in the browser; TLS protects what travels on the wire.
Report-only versus enforce
Two headers speak the same policy language. Content-Security-Policy enforces: violations are blocked. Content-Security-Policy-Report-Only does the same inventory work, but still lets everything through. The browser only reports which resources would have violated the policy.
Report-only is the safe start. You inventory scripts from analytics, chat, payment providers, fonts and CDNs, write a first policy, and run it report-only for a week (or longer). In the console or via a report-URI/report-to endpoint you see what you still miss. Only when that list goes quiet do you switch to the enforcing header.
Anyone who ships enforce immediately usually finds out via complaints: the chat widget vanishes, the payment button does nothing, or Google Tag Manager stops. That is not a reason to skip CSP. It is a reason to take the report-only phase seriously. You can temporarily run both headers side by side: report-only for a stricter draft, enforce for a milder policy that is already safe.
A quick reference for directives and keywords is the CSP Header Quick Reference. Use it as a checklist when writing default-src, script-src, style-src and frame-ancestors; always base the final choice on what your own site actually loads.
Pitfalls: unsafe-inline, wildcards and half measures
The most common weakness is 'unsafe-inline' in script-src or style-src. That keyword says: any inline script or style may run. That undercuts much of the XSS protection, because injected inline code is exactly what XSS often uses. The same applies to 'unsafe-eval' when you allow eval or similar constructs.
Better: nonces or hashes. A nonce is a random per-response value you put in the header and on legitimate script tags. Only tags with that nonce may run. Hashes work for fixed inline blocks whose content you know. Frameworks such as Next.js can generate nonces per request; that is the modern path to a stricter policy without breaking every widget.
Wildcards (https:) or overly broad host lists are the second classic. Allowing everything on HTTPS sounds generous, but still lets scripts from arbitrary sites through. Limit to the domains you truly need. Do not forget frame-ancestors either: without that directive (or without X-Frame-Options), clickjacking via iframes remains possible. CSP and the other headers belong together, not as optional extras.
Finally: policy only on the homepage. A CDN or reverse proxy that sets headers only on / leaves deep URLs unprotected. After every change, check a product page, a blog post and an account route, not just the root.
What the WebYes security pillar measures
The free WebYes scan checks security headers within the security pillar. CSP is part of that explicitly: if the header is missing, you see it in the report (for example as missing-csp). If a policy exists but with broad exceptions such as unsafe-inline or a wildcard, a weak-csp finding can follow. Nonces/hashes and frame-ancestors also appear when the engine runs those checks.
For the WebYes keurmerk the average across all pillars must be at least 80, and each pillar (including security) at least 60. A missing or too-loose CSP is a fast way to drop below that floor, especially together with missing HSTS or a weak TLS setup. The report links findings to fix guidance, so you see not only a score but what to change.
The scan is labeled beta and covers at most six pages per run, with a sixty-minute dedupe window per domain. That is enough to see headers on representative URLs, not to prove every edge case in your CDN. Use the scan for diagnosis; use report-only in production while you tighten the policy.
Besides CSP, the same pillar looks at HTTPS, HSTS and the other headers we explain under security headers. Adding only CSP while leaving HTTP open solves the wrong problem. Having solid TLS but no CSP misses the XSS layer.
A practical order to roll out CSP
Inventory first: open the network tab, note every external script, stylesheet, font and iframe. Include third-party tags that load via a tag manager; those change more often than your own code. Without that list you write a policy that breaks again tomorrow.
Then write a minimal policy: default-src 'self', script-src and style-src with the known hosts, frame-ancestors 'self' (or tighter), and object-src 'none' if you need no plugins. Ship that first as Content-Security-Policy-Report-Only. Review reports, fill gaps, repeat.
Replace unsafe-inline step by step with nonces or hashes. That is often the hardest part, especially with older themes or page builders that inject a lot of inline script. Plan it as separate work, not an evening job next to a release.
Only then switch to enforce, and keep HSTS and HTTPS in sync. A valid SSL certificate with redirect, plus the headers from our security-headers guide, plus a tightened CSP: that is the combination that carries the security pillar in practice. After every change, retest with the WebYes scan.
Read more
Frequently asked questions
Does CSP prevent all XSS attacks?
No. CSP makes XSS much harder to exploit by blocking scripts from disallowed sources, but it is not a substitute for secure development. OWASP explicitly calls CSP a complementary defence. Combine it with input validation, updates and the other security headers.
What is the difference between report-only and a normal CSP?
Content-Security-Policy-Report-Only reports violations without blocking anything. Content-Security-Policy enforces the rules. Use report-only to build your allowlist; switch to enforce only when legitimate sources pass the policy stably.
Why is 'unsafe-inline' a problem?
With 'unsafe-inline', any inline script or style may run. That undercuts the XSS protection CSP is meant to provide. Use nonces or hashes for legitimate inline code, and limit script-src to known hosts.
Does WebYes also check whether my CSP is strict enough?
Yes, within the security pillar. The scan flags a missing CSP and policies that are too loose (such as unsafe-inline or wildcards), alongside HSTS and other headers. For the keurmerk, security must score at least 60 and the overall average at least 80.
The WebYes scan measures this too
Scan your website for free on speed, security, mobile and accessibility and see where you stand.
Start free scan
