Overview
Content-Security-Policy (CSP) is an HTTP response header standardised by the W3C that instructs browsers to restrict which sources of scripts, styles, images, frames, and other resources a document is permitted to load and execute. When the header is absent, the browser falls back to the permissive same-origin policy with no additional restrictions, leaving the application without a second layer of defence against content injection attacks such as cross-site scripting (XSS).
A missing CSP header does not directly introduce a vulnerability, but it eliminates a critical mitigation control. In environments where an XSS or HTML injection flaw exists, the absence of CSP allows injected scripts to execute without any browser-level interference. Sensagraph detects missing and misconfigured CSP headers as part of its continuous HTTP security-header checks.
How it works
Without a Content-Security-Policy header (or a <meta http-equiv> equivalent), browsers apply only default same-origin rules. An attacker who can inject content into the page — through reflected, stored, or DOM-based XSS — can execute arbitrary JavaScript because no policy declares script-src restrictions or blocks inline scripts.
- Inline script execution: Browsers execute
<script>...</script>blocks and event-handler attributes (onclick,onerror, etc.) freely when no CSP disallows'unsafe-inline'. - Arbitrary external script loading: Without a
script-srcdirective, pages can load scripts from any origin, enabling attackers to import payloads from attacker-controlled CDNs or domains. - Data exfiltration via
connect-srcabsence: Without aconnect-srcdirective, injected code can freely beacon stolen session tokens or credentials to external endpoints. - Plugin and object loading: Without
object-src 'none', legacy plugin content (Flash, Java applets) could be injected, though this is less relevant in modern browsers. - Clickjacking facilitation: While
X-Frame-Optionsaddresses framing specifically, CSP'sframe-ancestorsdirective is the modern equivalent; its absence (along with a missingX-Frame-Optionsheader) enables clickjacking.
Business impact
The practical risk of a missing CSP scales with the sensitivity of the application and whether other injection vulnerabilities are present:
- Session hijacking: Injected scripts can steal session cookies (where
HttpOnlyis absent) and authentication tokens, leading to account takeover. - Credential theft: DOM manipulation can overlay fake login forms or redirect users to phishing pages without any visible URL change.
- Data exfiltration: Sensitive PII, financial data, or internal API responses can be silently transmitted to attacker infrastructure.
- Malware distribution: Compromised pages can serve drive-by downloads to site visitors, creating legal and reputational liability.
- Regulatory exposure: Failure to implement available technical controls may constitute a violation of GDPR Article 32 (appropriate technical measures), PCI DSS Requirement 6.4, and similar frameworks.
How to fix it
- Start with a report-only policy: Deploy
Content-Security-Policy-Report-Onlywith a permissive base and areport-uriorreport-toendpoint to collect violations without breaking functionality. Analyse reports to identify all legitimate resource origins before enforcing. - Define a strict base policy: Use a policy that includes at minimum:
default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self';. Expand directives only as needed for verified third-party resources. - Eliminate inline scripts and styles: Move all inline JavaScript to external files. If inline scripts are unavoidable, use
'nonce-{random}'or'sha256-{hash}'instead of'unsafe-inline'. Generate a cryptographically random nonce per response. - Avoid
'unsafe-eval': Refactor code that relies oneval(),Function(), or similar dynamic code execution to eliminate the need for this directive. - Lock down fetch directives: Explicitly specify
script-src,style-src,img-src,font-src,connect-src,media-src,frame-src, andworker-srcfor all origins your application legitimately uses. - Set
upgrade-insecure-requests: Add this directive to ensure mixed-content resources are loaded over HTTPS automatically. - Transition to enforcement: Switch from
Content-Security-Policy-Report-OnlytoContent-Security-Policyonce the policy is validated and violations have stabilised. - Serve the header at the web server or CDN layer: Configure the header in Nginx (
add_header), Apache (Header always set), or your CDN's response-header rules to ensure it is present on all responses, not just application-generated ones. - Review and iterate regularly: CSP policies require maintenance as dependencies and third-party integrations change. Incorporate CSP review into your deployment pipeline.
References
- W3C – Content Security Policy Level 3 Specification
- MDN Web Docs – Content Security Policy (CSP)
- OWASP – Secure Headers Project
- OWASP – Content Security Policy
- MITRE CWE-693 – Protection Mechanism Failure
- Google – Strict CSP
- MDN Web Docs – Content-Security-Policy Header Reference
- OWASP Top 10 – A05:2021 Security Misconfiguration