Skip to main content

Security policy reports

Browsers can report policy violations back to a URL. Point that URL at Errora and violations become issues, grouped by directive and blocked host.

Supported report types: CSP, Expect-CT, Expect-Staple, HPKP, including the batched Reporting API format.

Setup​

The endpoint is per project and authenticated by the DSN public key:

https://<your-errora-host>/api/<project_id>/security/?sentry_key=<public_key>

Add it to your policy header:

Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline';
connect-src 'self' https://<your-errora-host>;
report-uri https://<your-errora-host>/api/<project_id>/security/?sentry_key=<public_key>

Modern browsers prefer the Reporting API:

Reporting-Endpoints: csp-endpoint="https://<your-errora-host>/api/<project_id>/security/?sentry_key=<public_key>"
Content-Security-Policy: default-src 'self'; report-to csp-endpoint

Send both headers during a migration — support is uneven across browsers.

Nginx​

add_header Content-Security-Policy "default-src 'self'; report-uri https://errora.example.com/api/$PROJECT_ID/security/?sentry_key=$KEY" always;

Django​

CSP_REPORT_URI = "https://errora.example.com/api/<project_id>/security/?sentry_key=<key>"

Laravel​

Set the header in middleware, or with spatie/laravel-csp's reportUri option.

Rolling out a policy safely​

Start in report-only mode so nothing breaks while you learn what your pages actually load:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri https://…/security/?sentry_key=…

Watch the issues for a week, fix the legitimate ones, then switch the header to the enforcing form.

What you get​

Violations are grouped as issues by directive + blocked host, so script-src violations from one CDN are one issue, not ten thousand. Each event carries the document URI, the violated directive, the blocked URI, the effective policy and the browser.

Extension noise is filtered — chrome-extension://, moz-extension:// and friends — because your users' extensions are not your bug.

Verify​

curl -X POST "https://<host>/api/<project_id>/security/?sentry_key=<key>" \
-H 'Content-Type: application/csp-report' \
-d '{"csp-report":{"document-uri":"https://example.com/","violated-directive":"script-src",
"blocked-uri":"https://evil.example.net/x.js","effective-directive":"script-src"}}'

Then look in Issues.

Troubleshooting​

SymptomCause / fix
No reports at allreport-uri is inside the wrong header, or the browser only supports report-to
401 in the browser consolesentry_key missing or wrong in the query string
Flood of reportsUsually one bad directive; fix the policy rather than filtering — that is what report-only mode is for
Reports from extensionsAlready filtered; if you still see them, they came through a page-injected script, not the extension protocol