CentralCSP
PoliciesContent-Security-PolicyIntroduction

What it is

A Content Security Policy is an HTTP-header allowlist the browser enforces to block XSS, clickjacking, mixed content, and data exfiltration.

Last update:

A Content Security Policy (CSP) is an allowlist you send as an HTTP response header to tell the browser which resources a page may load and run. The browser reads the policy and refuses anything outside it: a script from an unapproved host, an inline <script> an attacker injected, a form that posts to a foreign domain. You declare the rules; the browser enforces them on the client.

CentralCSP does not enforce the policy. The browser is the enforcer. CentralCSP collects the violation reports the browser sends, builds a script inventory from them, and turns that stream into monitoring, alerting, and evidence. It is observability and policy management on top of what the browser already does, not a proxy or a web application firewall.

What a policy looks like

A policy is a string of directives separated by semicolons. Each directive is a name followed by a space-separated list of sources or keywords that the directive allows. Directive names are case-insensitive, and only the first occurrence of a given directive in one policy is used.

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-r4nd0m';
  object-src 'none';
  base-uri 'none'

That policy says scripts may come from the same origin or carry the nonce r4nd0m, plugins are blocked, the <base> tag is locked down, and everything else falls back to the same origin. The pieces are covered on their own pages: the directives that name what to control, the values each directive accepts, and the headers that deliver the policy to the browser.

What it protects against

CSP is a defense-in-depth control. It does not fix the bug that lets an attacker inject content; it limits what that injection can do once it lands.

ThreatHow the policy helps
Cross-site scripting (XSS) and injectionBlock inline and unapproved external script so injected code cannot run. Use script-src.
ClickjackingControl which sites may frame the page with frame-ancestors.
Mixed contentRewrite insecure subresource URLs to HTTPS with upgrade-insecure-requests.
Data exfiltrationRestrict where the page can send data and post forms with connect-src, form-action, and base-uri.

The XSS case is the reason most teams adopt a policy. If an attacker injects a <script> tag into a page, a well-built policy stops that script from executing, because it has no nonce, no matching hash, and no allowed host. The injection still happens; the payload never runs.

CSP is not a replacement for encoding

A policy reduces the impact of an injection. It does not prevent the injection. You still need contextual output encoding, input validation, and the other server-side controls that keep untrusted data out of the page in the first place. Treat the policy as the second layer that contains a mistake in the first.

The strict CSP recommendation

Host allowlists are hard to get right. They tend to grow long, they often allow domains that themselves host attacker-controllable content, and a single permissive entry can defeat the whole policy. The current recommendation, set out in the web.dev strict CSP guide, is to stop allowlisting hosts for script and trust individual scripts instead.

A strict policy rests on four parts:

  • A nonce or hash on script-src so only scripts you marked can run.
  • strict-dynamic, so a trusted script can load the scripts it needs without you listing every host. With it present, host and scheme entries are ignored.
  • object-src 'none' to remove plugin-based script execution.
  • base-uri 'none' to block <base> tag injection, which can otherwise redirect every relative script URL on the page.

A complete base policy sets those parts and then the remaining directives explicitly, including the fetch directives that would otherwise fall back to default-src, so nothing is left implicit and the browser reports violations to your endpoint:

Content-Security-Policy:
    default-src 'self';
    script-src 'nonce-{RANDOM}' 'strict-dynamic';
    style-src 'self';
    img-src 'self';
    font-src 'self';
    connect-src 'self';
    media-src 'self';
    manifest-src 'self';
    frame-src 'none';
    worker-src 'self';
    object-src 'none';
    base-uri 'none';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
    report-to csp-endpoint
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"

Generate a fresh {RANDOM} nonce per response and put the same value on each <script> you trust. Loosen a single directive only when the site needs it (an image CDN in img-src, a frame you embed in frame-src); keep the rest.

You can check a draft policy against these rules with the CSP evaluator, and scan a live site for its current headers with the CSP scanner. For a step-by-step build, the blog walks through it in Get started with CSP and How to build a strong CSP.

How CentralCSP fits

A strict policy is easiest to deploy in stages, starting in report-only mode so you watch what would break before you enforce anything. The browser sends a CSP violation report for each block, and CentralCSP collects that stream, deduplicates it, and surfaces what to fix. The same reports feed a script inventory, so you can see every script running on a page and roll the policy out without flying blind. See the CSP suite for the full feature set.

FAQ

What is a Content Security Policy?

A Content Security Policy is an allowlist you send as an HTTP response header telling the browser which resources a page may load and run. The browser reads the policy and refuses anything outside it: an unapproved script host, an injected inline script, a form posting to a foreign domain. You declare the rules; the browser enforces them.

Does CSP stop all XSS?

No. CSP is the strongest in-browser control against XSS, but it limits what an injection can do rather than preventing the injection itself. A strong policy stops an injected script from running because it has no nonce, hash, or allowed host, yet you still need contextual output encoding and Trusted Types to keep untrusted data out of the page.

Is CSP hard to set up?

Not if you stage it. Host allowlists are hard to get right, so the current recommendation is a strict policy built on a nonce or hash plus strict-dynamic. Deploy it in report-only mode first to watch what would break, then move the same string to the enforcing header. The strong CSP guide walks through the build.

See also

Sources

On this page