All posts

May 9, 2026 · 5 min read

What a Missing Content Security Policy Actually Fails to Stop

Content Security Policy, usually just called CSP, is a response header I've mentioned in passing on this blog without ever giving it a full teardown. Worth doing properly, because what it actually protects against is more concrete and more common than the technical-sounding name suggests.

The vulnerability CSP exists to contain: cross-site scripting

Cross-site scripting, XSS, happens when your app takes text that came from a user, a comment, a profile bio, a search term, and displays it back on a page without properly neutralizing anything in it that looks like executable code. If a visitor submits something crafted to look like a script tag instead of plain text, and your app renders it back without escaping it, that script can actually run, in the browser, of anyone else who views that page.

What a script running this way can actually do

Once a malicious script executes on your page, in a real visitor's browser, it runs with roughly the same access to that page as your own legitimate code. It can read anything visible on the page, including other content loaded for that user. Depending on how your session is structured, and whether you've applied the cookie protections I've written about before, it can potentially access the session token itself. It can redirect the visitor elsewhere, or quietly perform actions on their behalf using their own logged-in session.

Why this is often only a secondary layer, and why that layer still matters

The actual first line of defense against XSS is properly escaping user input before displaying it, which most modern frameworks handle reasonably well by default. CSP is the layer that exists specifically for when that first line fails anyway, whether through a bug, an overlooked edge case, or a place where raw HTML rendering was deliberately used for a legitimate feature and something slipped through. A Content Security Policy tells the browser, explicitly, which sources of scripts, styles, and other content are allowed to run on your page at all, so that even if a malicious script gets injected into the page's content, the browser refuses to execute it because it didn't come from an approved source.

What a missing CSP actually means in practice

Without one, if an XSS bug ever slips through your input handling, anywhere in your app, an injected script runs with no additional obstacle at all. With a properly configured CSP, that same injected script gets blocked by the browser itself, even though the underlying input-handling bug still technically exists. It's not a substitute for fixing the actual bug. It's a real, meaningful backstop for the moment one gets missed.

How to actually check and fix this

  • Check your app's response headers for a Content-Security-Policy header at all. A lot of fast-built apps simply don't have one.
  • If one exists, check whether it's meaningfully restrictive or effectively wide open, since a CSP that allows scripts from anywhere provides very little real protection.
  • Start with a reasonably strict policy and loosen only the specific sources you actually need, rather than starting broad and never tightening it.
  • Test the policy after adding it. An overly strict CSP can break legitimate functionality, so this is worth verifying rather than just deploying and hoping.

A missing CSP isn't the vulnerability itself. It's the missing backstop for a vulnerability that's genuinely common in fast-built apps, and it's one of the cheaper, more mechanical fixes on this entire blog once you know to add it.

Related reading

Harbova is a security service for apps built with AI tools. Start with a free scan, and if it finds something serious, we can fix it and prove it is closed.