Missing Browser Security Policy Leaves Site Without a Content Filter
Your website is missing a security instruction called a Content Security Policy (CSP). Think of it like a guest list for your website — it tells visitors' browsers which scripts and resources are allowed to run, and blocks everything else. Without it, your site is missing one layer of protection that could help limit the damage if another vulnerability were ever found.
Business Impact And Actions
medium urgencyBusiness Impact
On its own, a missing CSP does not mean your site has been compromised. It is a defence-in-depth control — its absence won't directly cause a breach, but it does mean your site lacks a safety net that could contain the impact of other issues (like a code injection bug). For compliance-conscious customers or enterprise buyers, missing security headers can flag during vendor security reviews and slow down sales cycles.
What To Do
- Ask your developer to add a Content Security Policy header to your web server — for a simple site, this is typically a 30–60 minute task.
- Ask them to start in 'report-only' mode first, so the policy can be tested without breaking anything on your site before it is enforced.
- Once the policy is confirmed working, switch it to enforcement mode and verify it appears using a free tool like securityheaders.com.
- If your site uses a third-party platform (WordPress, Shopify, etc.), ask your developer whether a plugin or platform setting can handle this automatically.
Missing Content-Security-Policy HTTP Response Header
medium severity CVSS N/A (defence-in-depth control; not independently exploitable)Vulnerability Explanation
The server does not emit a Content-Security-Policy (CSP) response header on any of its HTTP responses. CSP is a browser-enforced allowlist that controls which origins may supply scripts, styles, images, fonts, frames, and other resource types to a page. Without it, the browser applies no origin restrictions on resource loading, meaning any script that executes in the page context — whether injected via an XSS vulnerability, a compromised third-party dependency, or a supply-chain attack — runs without any browser-level containment.
Root Cause
CSP is an opt-in browser mechanism; servers must explicitly send the header. Its absence typically reflects that security headers were never configured at the web server or application framework layer, rather than any flaw in application code itself.
Technical Impact
Without CSP, a successful XSS or script-injection attack faces no browser-side containment. An attacker who can inject script can exfiltrate session tokens, perform actions on behalf of the user, redirect to phishing pages, or load additional payloads. CSP is a defence-in-depth control — its absence does not create a vulnerability on its own, but it removes a meaningful mitigation layer that limits the blast radius of other vulnerabilities.
Severity Justification
Missing CSP is a defence-in-depth gap, not a directly exploitable vulnerability. CVSS base score is not applicable in isolation; scanners typically rate this medium (CVSS ~5.0) because exploitation requires a separate injection vulnerability to be present. The finding is important but not independently exploitable.
Affected Components
Web server HTTP response headers — all versions without CSP configured
Remediation Steps
- Start in report-only mode to avoid breaking the site. Deploy `Content-Security-Policy-Report-Only` with a permissive baseline policy and a `report-uri` or `report-to` endpoint. Monitor violations for 1–2 days before enforcing.
- Audit your page's actual resource origins: note all CDNs, analytics, font providers, and API endpoints your pages load. These must be explicitly allowed in your policy.
- Build an enforced policy scoped to your real dependencies. A safe starting point for most apps: `Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; form-action 'self'; object-src 'none';` — expand each directive only as needed.
- Add the header at the web server or reverse-proxy layer so it applies to all responses (not just the index page). See code examples below for Nginx, Apache, and Express.
- If your app uses inline scripts or `eval()`, refactor to external script files or adopt nonce-based CSP (`'nonce-{random}'` per request) rather than using `'unsafe-inline'` or `'unsafe-eval'`, which negate most XSS protection.
- Validate your final policy with Google's CSP Evaluator (https://csp-evaluator.withgoogle.com/) before switching off report-only mode.
Verification Steps
- Run: `curl -s -I https://yourdomain.com | grep -i content-security-policy` — the header should appear in the output.
- Open Chrome DevTools → Network tab → click any page request → check the Response Headers section for `content-security-policy`.
- Paste your domain into https://securityheaders.com to get a graded report including CSP presence and quality.
- Validate the policy value at https://csp-evaluator.withgoogle.com/ to catch common misconfigurations (e.g., overly broad wildcards, `unsafe-inline`).
Code Examples (nginx / apache / javascript)
# No Content-Security-Policy header present in server response
# Nginx — add inside server {} or location {} block:
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; form-action 'self'; object-src 'none';" always;
# Apache — add inside <VirtualHost> block (requires mod_headers):
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; form-action 'self'; object-src 'none';"
# Express / Node.js — using the helmet package:
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"],
imgSrc: ["'self'", 'data:'],
fontSrc: ["'self'"],
connectSrc: ["'self'"],
frameAncestors: ["'self'"],
formAction: ["'self'"],
objectSrc: ["'none'"]
}
}));
# IIS — web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self'; object-src 'none';" />
</customHeaders>
</httpProtocol>
</system.webServer>
Best Practices
- Always deploy CSP in `Content-Security-Policy-Report-Only` mode first and monitor violations before switching to enforcement — this prevents accidental site breakage.
- Prefer nonce-based or hash-based CSP over `'unsafe-inline'`; inline script allowances significantly weaken XSS protection.
- Apply the CSP header to all HTTP responses, not just the HTML document — subresource responses can also benefit from policy coverage.
- Regularly review and tighten your CSP as your application's third-party dependencies change; an overly permissive policy provides little protection.
References
- developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
- cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
- csp-evaluator.withgoogle.com/
- owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/12-Test_for_Content_Security_Policy
Found this in your infrastructure?
VulWall scans for this and dozens of other issues automatically.
Scan Your Domain Free