Content Security Policy (CSP) Header Not Set: Meaning, Risk and Fix
CSP Header Not Set: Meaning, Risk and How to Fix It
HTTP Security Headers

Content Security Policy (CSP) Header Not Set: Meaning, Risk and Fix

A scanner finding that says “Content Security Policy (CSP) Header Not Set” means the response does not deliver an enforcing CSP. The fix is not to paste a generic policy blindly: inventory the page’s resource requirements, deploy a restrictive policy deliberately, test it, and use Report-Only during rollout where appropriate.

Scanner signalZAP 10038-1
ZAP alert10038-1 · Passive
RiskMedium
Core concernXSS / injection containment
Best rolloutReport → tighten → enforce

A Content Security Policy (CSP) Header Not Set finding means the application response does not contain an enforcing Content-Security-Policy header. CSP is a browser-enforced defense-in-depth control that restricts which scripts, styles, frames, images, connections, and other resources a document may use. Its absence does not prove that an XSS vulnerability exists, but it removes an important containment layer if injection occurs.

Treat this alert as two separate questions: first, is an enforcing policy actually absent from the final HTML response; second, what policy would be safe and useful for this application? Those are not the same problem. A header can be present and still be dangerously permissive, while an aggressive policy copied from another site can break authentication, payments, analytics, editors, or other production flows.

What Does “Content Security Policy Header Not Set” Mean?

Scanner meaning

OWASP ZAP alert 10038-1 is a passive, release-status, medium-risk finding. It reports that an enforcing Content-Security-Policy header is missing from the tested response.

Security meaning

CSP is defense in depth against XSS and content injection. Its absence does not prove XSS exists, but it removes a browser-enforced containment layer that can limit script execution and outbound connections.

Important: Content-Security-Policy-Report-Only is useful for tuning, but it does not enforce blocking. ZAP separately reports Report-Only-only deployments, so remediation should end with an enforcing policy once testing is complete.

How Scanners Detect This Finding

Most CSP “header not set” checks are passive: the scanner requests a page, inspects the response headers, and reports that an enforcing CSP is absent. That is intentionally simpler than evaluating whether the application is exploitable. A scanner cannot infer all script-generation patterns, trust relationships, nonce handling, or third-party dependencies from one response.

Validate the exact URL that triggered the alert. A login page, admin console, marketing page, API documentation UI, and JSON endpoint may all sit behind the same hostname but require different CSP treatment. Also inspect the final response after CDN and reverse-proxy processing; it is common for an origin to set a policy that is overwritten or stripped at another layer.

Practical Security Scenario

Consider an authenticated application that contains a separate HTML-injection defect. Without CSP, an injected script may be able to execute directly, call same-origin APIs with the victim’s session, read data available to the page, and send that data elsewhere. A strong CSP does not make the injection safe, but it can block unapproved script execution or outbound destinations and materially reduce the attacker’s options.

The opposite is also important: a permissive policy such as script-src * or widespread 'unsafe-inline' can create the appearance of remediation while providing little containment. The security outcome depends on policy quality, not merely header presence.

Where This Control Should Be Applied

Prioritize CSP on browser-rendered HTML documents and application shells. JSON APIs do not execute scripts themselves, so a CSP header on a pure JSON response is usually less meaningful than correct content types, authorization, CORS, and data minimization. If the same endpoint can return HTML error content or content negotiation changes the representation, test those paths separately.

Applications with many third-party scripts should treat CSP as a managed allowlist. Build an inventory, remove unnecessary dependencies, prefer nonces or hashes for trusted inline code, and keep a process for reviewing newly requested origins instead of continuously widening the policy.

Why a Missing CSP Header Matters

CSP changes the browser from “load whatever the page asks for” to “load only resources allowed by policy.” A well-designed policy can make many injected scripts fail because the attacker’s source, inline code, eval-like behavior, object content, or framing target is not permitted.

The strongest CSP deployments focus especially on script execution. Nonces or hashes can allow known inline scripts without enabling all inline JavaScript, while directives such as object-src 'none' and base-uri 'self' close classes of secondary injection techniques. CSP can also restrict framing through frame-ancestors.

Because CSP is defense in depth, severity should be judged in context. A static page with no sensitive state has a different risk profile from an authenticated application that renders user-controlled content, uses many third-party scripts, or handles privileged workflows.

How Content Security Policy Works

  • default-src: Provides a fallback source list for many resource types when a more specific directive is absent.
  • script-src: Controls JavaScript sources and is central to XSS containment. Prefer nonces or hashes over broad unsafe-inline allowances.
  • connect-src: Limits destinations used by fetch, XHR, WebSocket and related script interfaces.
  • frame-ancestors: Controls which origins may embed the page and is the modern control for clickjacking protection.
  • object-src and base-uri: Common hardening directives that reduce legacy plugin and base-URL abuse.
  • Reporting: Content-Security-Policy-Report-Only lets teams observe violations before enforcing a policy.

Related Ammune guides: HTTP security header not detected, cross-site scripting (XSS), and X-Frame-Options / clickjacking protection.

A Safer CSP Starting Pattern

There is no universal production CSP. A useful starting pattern for a conventional application may look like this, but it must be adapted to the page’s actual resource graph:

Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; script-src 'self' 'nonce-{RANDOM_PER_RESPONSE}'; style-src 'self'; img-src 'self' data:; connect-src 'self' https://api.example.com
Deployment note: Generate a new unpredictable nonce per response and apply the same nonce only to scripts that are intentionally trusted. Do not literally deploy the placeholder above.

Common Remediation Mistakes

  • Adding default-src * and assuming a header is automatically useful.
  • Using script-src 'unsafe-inline' everywhere, which weakens one of CSP’s most valuable protections.
  • Copying a policy from another application without inventorying CDNs, analytics, APIs, fonts, workers, payment frames, or identity flows.
  • Enabling enforcement in one step and breaking production because required resources were never observed.
  • Confusing Content-Security-Policy-Report-Only with enforcement. Report-Only records violations but does not block them.
  • Treating CSP as a substitute for fixing XSS, unsafe DOM sinks, template injection, or vulnerable third-party code.

How to Fix CSP Header Not Set Safely

1. Confirm the affected documents. Identify the exact HTML routes, status codes, virtual hosts, and response-producing layers that are missing CSP. Do not use a JSON API response or a different hostname as proof that the reported page is fixed.

2. Inventory real resource dependencies. Use browser developer tools and existing telemetry to list scripts, styles, fonts, images, frames, workers, WebSocket/fetch destinations, payment providers, identity providers, and other third-party origins the page genuinely needs.

3. Build the policy around script execution first. Start from restrictive defaults such as default-src 'self', object-src 'none', and base-uri 'self'. Prefer nonces or hashes for trusted inline scripts instead of permanently allowing 'unsafe-inline'.

4. Observe before broad enforcement. Deploy Content-Security-Policy-Report-Only where appropriate, exercise representative user journeys, and investigate violations. Separate necessary resources from stale integrations and unexpected third-party dependencies.

5. Enforce and keep tightening. Move the validated policy into Content-Security-Policy, re-run the original scan, and separately review policy-quality issues such as wildcards, unsafe-eval, missing fallback directives, and overly broad connect-src values.

Configuration Examples

CSP is often safest when the application owns the policy because dynamic nonces and route-specific dependencies require application context. Static policies can also be set at NGINX, Apache, an ingress, gateway, or CDN when the same policy is correct for every affected document. Ensure only the intended final policy reaches the browser.

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'"

Application

Set the header at the application or gateway only if that layer can generate the correct policy for each route. Dynamic nonces generally need application-aware generation.
Important: syntax can vary by software version and deployment model. Validate the generated response after every change rather than relying only on configuration-file appearance.

How to Test the Fix

  1. Inspect the final browser-visible response, not only the origin server. A CDN, reverse proxy, WAF, or load balancer may add or remove headers.
  2. Use browser developer tools to confirm the enforcing Content-Security-Policy header is present on the HTML document.
  3. Exercise login, logout, payments, uploads, editors, dashboards, third-party widgets, and error pages while monitoring CSP violations.
  4. Check that intended JavaScript still runs while an intentionally injected or unapproved test script source is blocked.
  5. Run the same scanner again and review separate CSP quality findings such as wildcards, unsafe-inline, unsafe-eval, malformed policy, or missing fallback directives.

For a production-equivalent check, capture response headers with curl -sD - -o /dev/null https://example.com/, then use the browser console to inspect CSP violations. Confirm there is one effective enforcing policy and that required flows work without silently adding broad exceptions.

How to Think About Severity

ZAP rates alert 10038-1 as Medium, but business risk depends heavily on context. Missing CSP is more consequential on authenticated applications, pages that render user-controlled content, administrative consoles, and applications with a large third-party script surface. A static informational page with no sensitive state has a different exposure profile.

Prioritize confirmed injection vulnerabilities ahead of CSP hardening, but do not dismiss a systemic CSP gap. A strong policy can materially reduce the blast radius of future XSS and supply-chain failures, especially when it is maintained as part of deployment rather than added once for a scanner.

How Ammune Fits

CSP controls what a browser document may execute, load, frame, or connect to. Ammune addresses the server/API side of the same application: discovering active APIs, observing request and response behavior, identifying sensitive data, and detecting runtime abuse that CSP cannot evaluate.

For example, connect-src can restrict where browser JavaScript sends requests, but it does not decide whether an API call is authorized, whether an object belongs to the caller, or whether a business workflow is being automated maliciously. Browser policy and runtime API protection therefore solve different parts of the attack path.

Production Remediation Checklist

  • Confirm the finding is on a browser-rendered HTML document, not only a JSON endpoint.
  • Capture the final client-visible headers through the real CDN, proxy, or gateway path.
  • Inventory scripts, styles, images, frames, fonts, workers, and API connection destinations.
  • Use nonces or hashes where inline scripts are genuinely required.
  • Avoid broad *, unsafe-inline, and unsafe-eval exceptions unless a documented requirement exists.
  • Use Report-Only during rollout when blocking risk is significant.
  • Exercise authentication, payments, uploads, editors, dashboards, and third-party widgets.
  • Enforce the final policy and review CSP quality findings separately from header presence.
  • Add automated response-header checks to deployment or synthetic tests.
  • Assign ownership for future CSP changes so new dependencies do not expand the policy without review.

Frequently Asked Questions

Is “CSP Header Not Set” a vulnerability?

It is a security-hardening finding and often a scanner-reported misconfiguration. The absence of CSP does not itself create XSS, but it removes a browser-enforced mitigation that can significantly reduce the impact of many injection attacks.

Is Content-Security-Policy-Report-Only enough?

No. Report-Only is useful for deployment and tuning, but it does not block disallowed content. The objective is usually to move a tested policy into the enforcing Content-Security-Policy header.

Should every API response have CSP?

CSP primarily protects browser-rendered documents. Applying it to JSON API responses is usually not the central control. Prioritize HTML documents and any response that can execute or embed active browser content.

Is frame-ancestors better than X-Frame-Options?

CSP frame-ancestors provides more flexible framing policy. Many organizations still send X-Frame-Options for compatibility while using frame-ancestors as the primary modern control.

What ZAP alert ID is used for this finding?

OWASP ZAP uses alert 10038-1 for Content Security Policy (CSP) Header Not Set.

Primary References

Pair Browser Policy with Runtime API Protection

CSP can contain browser-side injection impact. Ammune complements that control with runtime API discovery, behavioral analysis, sensitive-data visibility, and protection for the application workflows behind the page.

© Ammune.ai — API security guidance for modern application environments.