CSP violation
The csp-violation report, what the browser sends when a Content Security Policy is violated, in both the modern and legacy formats.
Last update:
A csp-violation report tells you that something on the page broke a Content Security Policy (CSP) rule: a blocked script, style, image, frame, or connection.
It is the most useful report type for tightening a policy, because each one names
the directive that fired and the resource that was blocked. There are two payload
formats for the same event, the modern Reporting API form and the legacy
report-uri form.
When the browser sends it
The browser sends one report each time the policy blocks (or, in Report-Only mode,
would block) a resource or an inline violation. It fires in both modes; the
disposition field tells them apart (enforce for a blocking policy, report for
Report-Only). Reports are de-duplicated, so a resource blocked many times does not
produce one report per attempt.
Payload
The same violation is delivered in two shapes depending on which directive routed it. Switch between them here:
The report-uri directive posts a single object wrapped in csp-report with kebab-case fields and Content-Type: application/csp-report, not the application/reports+json array. The two are not interchangeable; an endpoint that accepts both must branch on the Content-Type.
{
"type": "csp-violation",
"age": 53,
"url": "https://api-next.centralcsp.com/",
"user_agent": "Mozilla/5.0 ...",
"body": {
"documentURL": "https://api-next.centralcsp.com/",
"referrer": "https://www.google.com/",
"blockedURL": "https://apis.google.com/js/platform.js",
"effectiveDirective": "script-src-elem",
"originalPolicy": "default-src 'self'; report-to csp-endpoint",
"sourceFile": "https://api-next.centralcsp.com/",
"sample": "",
"disposition": "enforce",
"statusCode": 200,
"lineNumber": 1441,
"columnNumber": 59
}
}Field reference
The modern body uses camelCase; the legacy form uses the kebab-case name in parentheses.
| Field (legacy name) | Meaning |
|---|---|
documentURL (document-uri) | The page where the violation happened. |
referrer | The document referrer, if any. |
blockedURL (blocked-uri) | The resource that was blocked. Truncated to scheme, host, and port when cross-origin. |
effectiveDirective (effective-directive) | The directive that actually fired (for example script-src-elem). |
originalPolicy (original-policy) | The full policy text the browser enforced. |
sourceFile | Where the violation originated, for inline cases. |
sample (script-sample) | First ~40 characters of the offending inline content, only when the directive carries 'report-sample'. |
disposition | enforce or report. |
statusCode (status-code) | HTTP status of the document response. |
lineNumber / columnNumber | Location for inline violations. |
The legacy violated-directive is a historic alias for effective-directive. Treat
every field as attacker-influenced input, and never render one into a page unescaped.
How to receive it
Declare an endpoint and point the policy at it with the
report-to
directive. For the widest browser coverage, send the deprecated
report-uri
alongside it; browsers that support report-to ignore report-uri, so the two
never double-report.
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-endpointCentralCSP ingests both formats and normalizes them, which is the basis of the CSP violation dashboard.
What it tells you about security
Read effectiveDirective and blockedURL together. A script-src violation
pointing at a host you recognize usually means the policy is too strict. One pointing
at a host you do not recognize, or an inline sample you did not write, is worth
investigating as a possible injection. A sudden spike in a directive is the signal
to look. The CSP evaluator helps tighten the policy that
produced the reports.
Gotchas
The body field names are camelCase in the modern form and kebab-case in the legacy
form. The disposition value per the spec WebIDL is enforce or report, though
some MDN prose writes reporting; expect report. And blockedURL is deliberately
redacted to scheme, host, and port for cross-origin resources, so you see the origin
rather than the exact path.
Browser support
The legacy report-uri delivery has the broadest support, including Firefox and
Safari. The modern report-to delivery is Chromium-led, which is why sending both
is the widest-coverage setup today.
See also
- Content Security Policy
- report-uri directive
- CSP violation report fields explained
- The report delivery format
- Reporting-Endpoints header
- CSP monitoring in CentralCSP