Skip to content

Repository files navigation

reporting-api

npmlicense

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

HeaderShorthand
Content-Security-PolicyCSP
Content-Security-Policy-Report-Only
Cross-Origin-Opener-PolicyCOOP
Cross-Origin-Opener-Policy-Report-Only
Cross-Origin-Embedder-PolicyCOEP
Cross-Origin-Embedder-Policy-Report-Only
Permissions-Policy
Permissions-Policy-Report-Only
NEL (Network Error Logging)NEL

Plus Document-Policy violation, 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-api

Peer dependencies: express, zod, debug.

Quick start

importexpressfrom'express';import{reportingEndpoint,setupReportingHeaders}from'reporting-api';constapp=express();// 1. Mount the reporting endpointapp.use('/reporting-endpoint',reportingEndpoint({allowedOrigins: '*',onReport(report){console.log(report.type,report.body);},}));// 2. Set your policy headers, then let the middleware attach reportersapp.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 beforesetupReportingHeaders runs so the middleware can append report-to and report-uri directives 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.

OptionTypeDescription
onReport(report, req) => voidCalled for every valid report.
onValidationError(error, body, req) => voidCalled when a report fails Zod validation.
allowedOriginsstring | RegExp | ArrayEnable CORS for cross-origin reports. Use '*' to allow any origin.
ignoreBrowserExtensionsbooleanDrop CSP violations originating from browser extensions.
ignoredDeprecationIdsstring[]Deprecation report IDs to ignore (e.g. ['AttributionReporting', 'Topics']).
maxAgenumberMaximum report age in seconds. Older buffered reports are dropped.
debugbooleanEnable 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.

OptionTypeDefaultDescription
reportingGroupstring"reporter"Reporting group name.
enableDefaultReportersbooleanfalseUse the default group so you also receive Deprecation, Crash, and Intervention reports.
enableNetworkErrorLoggingboolean | objectfalseAdd Report-To + NEL headers (Reporting API v0, required for NEL). Accepts { success_fraction, failure_fraction, include_subdomains }.
versionstring | numberAppended 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'|'feature-policy-violation'|'document-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(typeofReportingObserver!=='undefined'){newReportingObserver((reports)=>{reports.forEach(r=>console.log(r.body));}).observe();}

Resources

Notes

  • Permissions-Policy reports to the default group when report-to is not set.
  • COOP and COEP require report-to values wrapped in double quotes (e.g. report-to="group").
  • Safari sends reports as { body: { ... } } instead of an array and omits age.

About

Express middleware to collect Reporting API reports - CSP, COOP, COEP, Permissions-Policy, Document-Policy, NEL, crash, deprecation and intervention reports

Topics

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages