fastmon Docs
Guides

Report Content Security Policy violations

Two response headers make the browser report every violation of your Content Security Policy to fastmon.

Naming fastmon as your policy's report endpoint makes the browser send every violation to fastmon. A new or tightened policy can run as Content-Security-Policy-Report-Only first, so you see what it would break before it blocks anything. What the reports show is on Content Security Policy.

Set it up

  1. Enter the application's collector_hash in the panel below, or open this page with ?collector_hash=. Every snippet on the page then uses it.
  2. Send the two headers on every HTML response of the site.
  3. Make sure every host that sends them is a site of that application, or a subdomain of one.
  4. Verify that a report arrives.

Your snippet

Opened from the app, these are filled in with your application's real values. Otherwise, paste them here and every snippet on this page updates.

Find both hashes in the app under Applications → ··· → IDs & hashes.

A report whose host is no site of the application is dropped, and a report never creates a site. www.shop.example counts for shop.example, notshop.example does not.

The headers

Reporting-Endpoints: fastmon-csp="https://fastmon.site/c/v/{collector_hash}"Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://js.payments.example; report-to fastmon-csp; report-uri https://fastmon.site/c/v/{collector_hash}

The policy is an example. Keep your own directives and add report-to and report-uri. An application with a custom collector endpoint uses its own host instead of fastmon.site.

  • On every HTML response. A policy covers the document that carries it, not the images or scripts it loads.
  • Reporting-Endpoints beside the policy. It defines the group fastmon-csp that report-to names. Report-To, which NEL needs, is not required.
  • Both report-to and report-uri. Newer browsers use report-to and ignore report-uri, older ones send only report-uri. Each violation arrives once.
  • The enforcing policy can report too. Add the same two directives to Content-Security-Policy. Every report says whether it was blocked or only reported.
  • Leave out 'report-sample'. fastmon drops the code sample unread, see Privacy → CSP reports.

Examples

server {  listen 443 ssl;  server_name shop.example;  add_header Reporting-Endpoints 'fastmon-csp="https://fastmon.site/c/v/{collector_hash}"' always;  add_header Content-Security-Policy-Report-Only "default-src 'self'; report-to fastmon-csp; report-uri https://fastmon.site/c/v/{collector_hash}" always;}

A location block with its own add_header inherits none from server, so repeat both lines there.

Verify

  1. The headers arrive. In the browser's network tab, check the document request for Reporting-Endpoints and the policy header.
  2. A violation shows. With a report-only policy that forbids something the page loads, the console prints a [Report Only] message per violation. Chrome uploads report-to reports within about a minute, a report-uri report goes out at once.
  3. The endpoint answers. Test both formats without a browser, with a registered site in place of shop.example:
curl -i https://fastmon.site/c/v/{collector_hash} \-H 'Content-Type: application/reports+json' \--data '[{"age":0,"type":"csp-violation","url":"https://shop.example/","body":{"documentURL":"https://shop.example/","blockedURL":"https://cdn.example/x.js","effectiveDirective":"script-src-elem","disposition":"report","statusCode":200}}]'curl -i https://fastmon.site/c/v/{collector_hash} \-H 'Content-Type: application/csp-report' \--data '{"csp-report":{"document-uri":"https://shop.example/","blocked-uri":"inline","effective-directive":"script-src-elem","disposition":"report","status-code":200}}'

The endpoint answers 204 whether it kept the report or dropped it. The Sites card on the Content Security Policy page shows each site's last report.

Traps

  • A long policy fills the upload. One upload is capped at 128 KiB and every report carries the whole policy. A page that breaks a policy of several kilobytes dozens of times per load can exceed it, and the browser drops that upload.
  • Shopify storefronts allow no custom response headers, so a Shopify shop cannot send a policy that reports to fastmon.
  • Each application has its own hash. A report for a site of another application drops, even in the same organization.
  • A hash rotation stops the reports silently. Put the new collector_hash into both directives.
  • A first-party proxy has to forward /c/v/ and the OPTIONS preflight before a report-to upload. A location /c/ block covers both.

On this page