secure_headers icon indicating copy to clipboard operation
secure_headers copied to clipboard

Add support for W3C Reporting API

Open tmaier opened this issue 2 months ago • 1 comments

Fixes #512

Implements support for the W3C Reporting API (https://w3c.github.io/reporting/) to enable standardized browser reporting for security violations and other issues.

Changes include:

  1. New Reporting-Endpoints Header:

    • Added ReportingEndpoints header class to configure named reporting endpoints
    • Accepts hash configuration: { default: "https://example.com/reports" }
    • Generates header: Reporting-Endpoints: default="https://example.com/reports"
  2. CSP report-to Directive:

    • Added report_to directive to Content Security Policy
    • New :string directive type for single token values
    • Positioned before legacy report-uri directive for clarity
  3. Configuration Updates:

    • Registered reporting_endpoints in CONFIG_ATTRIBUTES_TO_HEADER_CLASSES
    • Added report_to to DIRECTIVES_3_0 (CSP Level 3)
    • Updated NON_FETCH_SOURCES to include report_to
  4. Tests:

    • Complete test coverage for ReportingEndpoints header
    • CSP tests for report-to directive
    • Integration tests for both headers working together
  5. Documentation:

    • Added W3C Reporting API section to README
    • Usage examples for both modern and legacy browser support
    • Configuration examples showing endpoint definition and CSP integration

Addresses issue #512

🤖 Generated with Claude Code

All PRs:

  • [x] Has tests
    • spec/lib/secure_headers/headers/reporting_endpoints_spec.rb - Tests for Reporting-Endpoints header
    • spec/lib/secure_headers/headers/content_security_policy_spec.rb - Tests for CSP report-to directive
  • [x] Documentation updated
    • README.md updated with W3C Reporting API section including usage examples and browser compatibility information

Adding a new header: Reporting-Endpoints

Is the header supported by any user agent? If so, which?

  • Chrome/Edge: Supported since Chrome 96
  • Firefox: not supported
  • Safari: Supported since Safari 16.4
  • Opera: Supported since Opera 82

Browser compatibility: https://caniuse.com/wf-reporting

What does it do?

The Reporting-Endpoints header defines named endpoints where browsers can send various types of reports using the W3C Reporting API. These reports include:

  • Content Security Policy violations
  • Deprecated API usage warnings
  • Network errors
  • Interventions and crashes

It replaces the deprecated Report-To header with a simpler, more efficient format.

What are the valid values for the header?

A comma-separated list of endpoint definitions in the format: name="url"

Examples:

  • Single endpoint: default="https://example.com/reports"
  • Multiple endpoints: default="https://example.com/reports", csp="https://example.com/csp"

Each endpoint must have:

  • name: A token (alphanumeric, hyphens, underscores) that can be referenced by reporting features
  • url: A fully qualified HTTPS URL where reports will be sent via POST requests

Where does the specification live?

  • https://w3c.github.io/reporting/
  • Specifically: https://w3c.github.io/reporting/#header

Adding a new CSP directive: report-to

Is the directive supported by any user agent? If so, which?

  • Chrome/Edge: Supported since Chrome 70/79
  • Firefox: not supported
  • Safari: Supported since Safari 16.4
  • Opera: Supported since Opera 57

Browser compatibility: https://caniuse.com/mdn-http_headers_content-security-policy_report-to

What does it do?

The report-to directive specifies the name of a reporting endpoint (defined in the Reporting-Endpoints header) where the browser should send CSP violation reports. This is the modern replacement for the report-uri directive.

Key differences from report-uri:

  • References an endpoint name rather than a URL directly
  • Uses the structured Reporting API format (JSON with more metadata)
  • Supports batching and retry logic
  • Can be used for more than just CSP violations

What are the valid values for the directive?

A single token (string) representing the endpoint name defined in the Reporting-Endpoints header.

Examples:

  • report-to default - References the "default" endpoint
  • report-to csp-endpoint - References the "csp-endpoint" endpoint

Unlike report-uri (which accepts an array of URLs), report-to accepts only a single endpoint name.

Where does the specification live?

  • CSP Level 3: https://w3c.github.io/webappsec-csp/#directive-report-to
  • W3C Reporting API: https://w3c.github.io/reporting/

Additional Notes:

For maximum browser compatibility, both report-to (modern) and report-uri (legacy) can be used simultaneously:

config.reporting_endpoints = { default: "https://example.com/reports" }
config.csp = {
  default_src: %w('self'),
  report_to: 'default',                           # Modern browsers
  report_uri: %w(https://example.com/reports)     # Legacy browsers
}

Modern browsers will use report-to and ignore report-uri, while older browsers will fall back to report-uri.

tmaier avatar Oct 23 '25 14:10 tmaier

I rebased this on #558 , since the rubocop issues reported are independent of this PR.

tmaier avatar Nov 19 '25 23:11 tmaier