Browser Security Best Practices

Chapter 2 · Practice 3 of 3

Roll out CSP in report-only mode and watch the reports

From Content Security Policy

Why it matters

Switching on a strict CSP in one go usually breaks something: an inline event handler, an analytics snippet, a browser extension's injected script showing up in reports. OWASP's rollout approach:

  1. Send the strict policy as Content-Security-Policy-Report-Only. It blocks nothing and reports every violation.
  2. Optionally keep a looser policy enforced at the same time.
  3. Fix your code: move inline handlers (onclick=) to addEventListener, add nonces, remove eval.
  4. When reports are only noise (extensions, old browsers), switch the header to enforcing.
  5. Keep reporting on, so regressions show up.

Reporting directives. report-to is current: it names an endpoint defined in the Reporting-Endpoints header. report-uri is deprecated but still used by older browsers, so OWASP recommends sending both.

Expect some noise. Group reports by blocked-uri and violated-directive, ignore known extension schemes, and alert on new patterns rather than volume.

Avoid

  • Adding 'unsafe-inline' or 'unsafe-eval' to silence reports
  • Enforcing a new policy without a report-only period

Example

HTTP
Reporting-Endpoints: csp="https://example.com/csp-reports"
Content-Security-Policy-Report-Only: script-src 'nonce-r4nd0m' 'strict-dynamic';
  object-src 'none'; base-uri 'none'; require-trusted-types-for 'script';
  report-to csp; report-uri https://example.com/csp-reports