CentralCSP
PoliciesContent-Security-PolicyIntroduction

Headers

The HTTP headers that deliver a Content Security Policy, enforce vs report-only, report-to vs report-uri, meta delivery limits, and how policies combine.

Last update:

A Content Security Policy (CSP) reaches the browser as an HTTP response header. You send the policy on the response, the browser reads it, and from that point it applies the rules to the page. This page covers the two delivery headers, how the policy reports violations, the limits of <meta> delivery, and what happens when a response carries more than one policy.

For the policy contents themselves, see the directives and the values they accept.

The enforcing header in its simplest form:

Content-Security-Policy: default-src 'self'

Enforce vs report-only

There are two headers that deliver a policy. They take the exact same syntax; the only difference is what the browser does with a violation.

HeaderStatusWhat the browser does
Content-Security-Policy✅ GoodEnforces the policy: blocks the violation and reports it.
Content-Security-Policy-Report-Only✅ GoodReports the violation but does not block it.

Report-only mode lets you watch what a policy would break before you turn it on. You deploy the policy on the report-only header, collect the reports, fix what the policy would have blocked, then move the same string to the enforcing header. A report-only policy needs a reporting endpoint to be useful, since reporting is all it does.

Content-Security-Policy-Report-Only:
  default-src 'self';
  report-to csp-endpoint

A response can carry both an enforcing policy and a report-only policy at once, which lets you enforce a known-good baseline while testing a stricter policy in parallel.

How the policy reports

A policy points the browser at an endpoint with one of two directives.

  • report-to names a reporting group. The group's URL lives in a separate Reporting-Endpoints header, part of the Reporting API. This is the current mechanism. See the CSP report-to page.
  • report-uri posts reports straight to a URL. It is the legacy mechanism and is ignored where report-to is supported, which is now every current browser (Chrome, Edge, Safari, and Firefox).

report-to is the primary mechanism; keep report-uri alongside it only to cover old, unupdated browser versions. The modern Reporting-Endpoints header pairs with report-to; the older Report-To header is a separate, deprecated mechanism that CSP no longer needs (it remains required only for NEL).

Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
Content-Security-Policy:
  default-src 'self';
  report-uri https://<Endpoint-ID>.report.centralcsp.com;
  report-to csp-endpoint

The two delivery paths produce different report shapes: hyphenated field names for report-uri and camelCase for report-to. Both land as a CSP violation report, which CentralCSP collects and normalizes. To confirm your endpoint is wired correctly, run the Reporting API checker.

Delivery through a meta tag

You can also deliver a policy in HTML with a <meta> tag in the document <head>, which is useful when you cannot set response headers.

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'">

A <meta> policy is more limited than a header. It cannot do report-only. It cannot use report-uri, report-to, frame-ancestors, or sandbox. It must appear in the <head>, and it only governs content that comes after it in the document. Prefer the HTTP header where you can set one.

How multiple policies combine

When a response carries more than one enforcing policy, the browser applies all of them, and a resource must satisfy every one to load. Policies combine by intersection, so the effective rule is the most restrictive across all of them.

This means adding a policy can only ever tighten the result, never loosen it. A second policy of script-src 'self' will not re-allow a host that a first policy of script-src 'none' already blocked. Each policy is also evaluated independently for reporting, so one violation can produce reports to several endpoints.

Recommendation

Run both headers together: enforce the policy you trust today, and test each tightening step in a report-only policy before promoting it. Wire reporting through report-to and Reporting-Endpoints, which every current browser now supports.

Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
Content-Security-Policy:
    script-src 'nonce-{RANDOM}' 'strict-dynamic';
    object-src 'none';
    base-uri 'none';
    report-to csp-endpoint
Content-Security-Policy-Report-Only:
    script-src 'nonce-{RANDOM}' 'strict-dynamic';
    connect-src 'self';
    report-to csp-endpoint

Staged tightening with a report-only shadow policy is how the web.dev strict CSP guide recommends rolling a policy out, and it keeps a production incident out of every change.

FAQ

What is the difference between enforce and report-only CSP?

Content-Security-Policy blocks a violation and reports it; Content-Security-Policy-Report-Only only reports it, so you can test a policy before enforcing. See enforce vs report-only for the full rollout workflow.

Can I set a CSP in a meta tag?

Yes for most directives, but a <meta http-equiv="Content-Security-Policy"> tag cannot do report-only and ignores report-uri, report-to, frame-ancestors, and sandbox. See meta tags vs headers for when to use each.

See also

Sources

On this page