reporting-api
v1.0.5
Published
Roll your own Reporting API collector. Supports CSP, COEP, COOP, Document-Policy, Crash reports, Deprecation reports, Intervention reports and Network Error Logging
Downloads
599
Maintainers
Readme
reporting-api
Express.js middleware for the Reporting API. Automatically wires up report-to / report-uri on your existing policy headers and gives you a ready-made endpoint to collect violation, deprecation, crash, and network error reports.
Supported headers and report types
| Header | Shorthand |
|--------|-----------|
| Content-Security-Policy | CSP |
| Content-Security-Policy-Report-Only | |
| Cross-Origin-Opener-Policy | COOP |
| Cross-Origin-Opener-Policy-Report-Only | |
| Cross-Origin-Embedder-Policy | COEP |
| Cross-Origin-Embedder-Policy-Report-Only | |
| Permissions-Policy | |
| Permissions-Policy-Report-Only | |
| NEL (Network Error Logging) | NEL |
Plus Deprecation, Intervention, and Crash reports.
Backwards-compatible with CSP Level 2 report-uri for browsers that don't yet support the Reporting API.
Install
npm install reporting-apiPeer dependencies: express, zod, debug.
Quick start
import express from 'express';
import { reportingEndpoint, setupReportingHeaders } from 'reporting-api';
const app = express();
// 1. Mount the reporting endpoint
app.use('/reporting-endpoint', reportingEndpoint({
allowedOrigins: '*',
onReport(report) {
console.log(report.type, report.body);
},
}));
// 2. Set your policy headers, then let the middleware attach reporters
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "script-src 'self'");
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
next();
});
app.use(setupReportingHeaders('/reporting-endpoint'));
app.listen(8080);[!NOTE] Policy headers must be set before
setupReportingHeadersruns so the middleware can appendreport-toandreport-uridirectives to them.
The resulting response headers will look like this:
Reporting-Endpoints: reporter="/reporting-endpoint"
Content-Security-Policy: script-src 'self';report-uri /reporting-endpoint?disposition=enforce;report-to reporter
Cross-Origin-Opener-Policy: same-origin;report-to="reporter"
Cross-Origin-Embedder-Policy: require-corp;report-to="reporter"API
reportingEndpoint(config)
Returns Express middleware that accepts incoming reports.
| Option | Type | Description |
|--------|------|-------------|
| onReport | (report, req) => void | Called for every valid report. |
| onValidationError | (error, body, req) => void | Called when a report fails Zod validation. |
| allowedOrigins | string \| RegExp \| Array | Enable CORS for cross-origin reports. Use '*' to allow any origin. |
| ignoreBrowserExtensions | boolean | Drop CSP violations originating from browser extensions. |
| ignoredDeprecationIds | string[] | Deprecation report IDs to ignore (e.g. ['AttributionReporting', 'Topics']). |
| maxAge | number | Maximum report age in seconds. Older buffered reports are dropped. |
| debug | boolean | Enable debug logging for the reporting-api:* namespace. |
setupReportingHeaders(url, config?)
Returns Express middleware that appends report-to / report-uri to every policy header already set on the response and adds the Reporting-Endpoints header.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| reportingGroup | string | "reporter" | Reporting group name. |
| enableDefaultReporters | boolean | false | Use the default group so you also receive Deprecation, Crash, and Intervention reports. |
| enableNetworkErrorLogging | boolean \| object | false | Add Report-To + NEL headers (Reporting API v0, required for NEL). Accepts { success_fraction, failure_fraction, include_subdomains }. |
| version | string \| number | — | Appended as a ?version= query param so you can correlate reports with policy revisions. |
Report schema
Every report delivered to onReport is validated with Zod and has the shape:
{
type: 'csp-violation' | 'coop' | 'coep' | 'deprecation' | 'crash'
| 'intervention' | 'network-error' | 'permissions-policy-violation'
| 'potential-permissions-policy-violation';
body: { /* type-specific fields */ };
url: string;
age: number;
user_agent: string;
report_format: 'report-uri' | 'report-to' | 'report-to-safari';
version?: string;
}Full type definitions are exported as Report and the individual body types (ContentSecurityPolicyReport, CrossOriginOpenerPolicyReport, etc.).
Client-side observing
Reports can also be observed in the browser via ReportingObserver:
if (typeof ReportingObserver !== 'undefined') {
new ReportingObserver((reports) => {
reports.forEach(r => console.log(r.body));
}).observe();
}Resources
- Reporting API v1 spec (Reporting-Endpoints)
- Reporting API v0 spec (Report-To)
- Migrating from v0 to v1
- v0 vs v1 differences (Chromium)
- Permissions-Policy reporting
Notes
Permissions-Policyreports to thedefaultgroup whenreport-tois not set.- COOP and COEP require
report-tovalues wrapped in double quotes (e.g.report-to="group"). - Safari sends reports as
{ body: { ... } }instead of an array and omitsage.
