Content-Security-Policy (CSP) header configured
Issue No: 137
Category: HTTP Security Headers
Issue type: Issue
Priority: IMPORTANT
Description
Verifies that the website transmits a Content-Security-Policy (CSP) HTTP response header to mitigate cross-site scripting (XSS) attacks and control resource loading. A properly configured CSP header restricts the sources from which content can be loaded, reducing attack surface.
How do we capture it
- Perform an HTTP GET request to the site's homepage URL (or canonical URL if provided).
- Follow all HTTP redirects (3xx status codes) up to a maximum of 5 redirects; record the final HTTP status code and response headers.
- Inspect the HTTP response headers for the
Content-Security-Policyheader (case-insensitive header name per RFC 7230). - If the header is present, extract and record the full header value as a string.
- If the header is absent, record
nullor an empty string for the header value. - If the HTTP request fails, times out, or returns a 5xx error, record the HTTP status code and note that the CSP header could not be verified.
- Record the HTTP status code of the final response after all redirects.
- Return the CSP header value, presence/absence flag, and HTTP status code for storage.
What to store
| Field | Type | Comment |
|---|---|---|
csp_header_present | BOOLEAN | Whether the Content-Security-Policy header is present in the HTTP response. |
csp_header_value | TEXT | The full value of the Content-Security-Policy header if present; null if absent. |
response_status_code | INTEGER | The final HTTP status code after following redirects. |
capture_timestamp | TIMESTAMP | The date and time when the header was captured. |
capture_success | BOOLEAN | Whether the HTTP request succeeded and headers were captured without error. |
Condition for trigger
The audit triggers when a site does not transmit a valid Content-Security-Policy header or transmits an incomplete/insufficient policy. Rules below:
-
Trigger Rule 1: CSP Header Missing
- Target Field:
csp_header_present - Evaluation Logic:
csp_header_present = false - Severity: IMPORTANT
- Diagnostic Message: "Missing Content-Security-Policy (CSP) header. Configure a CSP header to prevent XSS attacks and unauthorized resource loading."
- Target Field:
-
Trigger Rule 2: Empty CSP Header Value
- Target Field:
csp_header_value - Evaluation Logic:
csp_header_value IS NULL OR csp_header_value = '' - Severity: IMPORTANT
- Diagnostic Message: "Content-Security-Policy header is empty or malformed. Provide a valid CSP policy with directives."
- Target Field:
-
Trigger Rule 3: Permissive CSP Policy (unsafe-inline or unsafe-eval)
- Target Field:
csp_header_value - Evaluation Logic:
csp_header_value LIKE '%unsafe-inline%' AND csp_header_value LIKE '%script-src%'ORcsp_header_value LIKE '%unsafe-eval%' AND csp_header_value LIKE '%script-src%' - Severity: WARNING
- Diagnostic Message: "Content-Security-Policy contains 'unsafe-inline' or 'unsafe-eval' in script-src directive, which undermines XSS protection. Remove or restrict these keywords."
- Target Field:
-
Trigger Rule 4: Capture Failed
- Target Field:
capture_success - Evaluation Logic:
capture_success = false - Severity: CRITICAL
- Diagnostic Message: "Unable to capture CSP header due to HTTP error or timeout. Verify that the site is accessible and returning valid HTTP responses."
- Target Field:
Sources
- OWASP Content Security Policy: https://owasp.org/www-community/attacks/xss/
- MDN Web Docs - Content-Security-Policy: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
- W3C Content Security Policy Level 3: https://w3c.github.io/webappsec-csp/
- Google Search Central - Web Security: https://developers.google.com/search/docs/beginner/security-best-practices
- RFC 7230 - HTTP/1.1 Message Syntax and Routing: https://tools.ietf.org/html/rfc7230
Long description
Content-Security-Policy (CSP) is a W3C standard HTTP response header that allows website operators to declare which dynamic resources are permitted to load in a user's browser. CSP mitigates cross-site scripting (XSS) attacks by preventing inline script execution and restricting script sources to whitelisted domains.
Why CSP matters:
- XSS Prevention: CSP blocks unauthorized script execution, a primary vector for account compromise and data theft.
- Search Ranking: Google factors site security into search rankings. A strong CSP signals that the site follows security best practices.
- Attack Surface Reduction: By restricting resource sources (scripts, styles, images, fonts), CSP limits an attacker's ability to inject malicious content.
- Compliance: Many security frameworks and compliance standards (e.g., PCI DSS, HIPAA) recommend or require CSP headers.
Common failure scenarios checked by the crawler:
- CSP header completely missing: The site does not transmit a CSP header, leaving it vulnerable to inline script injection.
- Empty or malformed CSP header: The CSP header value is empty, blank, or syntactically invalid.
- Overly permissive CSP: The policy uses
unsafe-inlineorunsafe-evalin thescript-srcdirective, which allows inline scripts and defeats the purpose of CSP. - CSP header only on certain pages: The header is present on the homepage but missing from subpages or API endpoints.
- Default-src only: The policy only uses a permissive
default-srcdirective without specificscript-srcrestrictions.
How to Fix
-
Identify your site's resource requirements: Audit all scripts, stylesheets, images, fonts, and other resources to determine which domains and types are necessary.
-
Define a strict CSP policy: Create a policy that lists only the required resource sources. Start with a restrictive baseline such as
default-src 'self'and add specific directives for each resource type. -
Restrict script execution: Use
script-src 'self'to allow scripts only from your own domain. Avoidunsafe-inlineandunsafe-evalunless absolutely necessary; refactor inline scripts into external files instead. -
Use nonces or hashes for dynamic content: If inline scripts are unavoidable, use Content Security Policy nonces (unique per request) or hashes to allow specific inline scripts while blocking others.
-
Configure the CSP header on your server: Add the
Content-Security-Policyheader to all HTTP responses from your web server or application framework. Ensure it is sent alongside all content types (HTML, API responses, etc.). -
Test and iterate: Use the
Content-Security-Policy-Report-Onlyheader first to log violations without blocking resources. Monitor violation reports, adjust the policy, and then deploy the enforcingContent-Security-Policyheader. -
Monitor for violations: Configure a report-uri or report-to endpoint to collect CSP violation reports, enabling you to detect attacks or policy misconfigurations in production.
-
Document your policy: Include comments in your policy configuration explaining why each directive is necessary, making future maintenance easier.