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
| Symptom | Cause / fix |
|---|---|
| No reports at all | report-uri is inside the wrong header, or the browser only supports report-to |
401 in the browser console | sentry_key missing or wrong in the query string |
| Flood of reports | Usually one bad directive; fix the policy rather than filtering — that is what report-only mode is for |
| Reports from extensions | Already filtered; if you still see them, they came through a page-injected script, not the extension protocol |