Move from Report-Only to Enforced Content Security Policy

fix now page

Content-Security-Policy-Report-Only sends violation reports without blocking resources. The header allows observation of policy impact before enforcement. Moving to enforced mode replaces the report-only header with Content-Security-Policy, causing browsers to block violations rather than report them. Report-only mode is a staging mechanism, not a permanent configuration.

What's wrong

The Content-Security-Policy-Report-Only header is active but no enforced Content-Security-Policy header exists. Browsers observe violations and send reports but do not block resources. The policy identifies problems without preventing them. Report-only mode remains active past its observation window, creating the appearance of protection without actual enforcement.

Why it matters

Report-only policies do not prevent attacks. Browsers log violations to the console and send reports to configured endpoints but load blocked resources normally. Inline scripts execute. Unsafe domains connect. XSS payloads run without interference. The policy documents violations but provides no runtime protection. Extended report-only deployment creates false confidence in security posture.

The correct change

Replace Content-Security-Policy-Report-Only with Content-Security-Policy using the same directive values. The policy transitions from observation to enforcement. Browsers block resources that violate the policy instead of reporting them. Retain the report-uri or report-to directive to continue receiving violation reports in enforced mode. The end state is an enforced policy with no report-only header remaining.

Scope

This condition applies at the page level. Each response controls its own CSP mode through HTTP headers. Global configuration typically enforces policy across all pages simultaneously. Gradual rollout can enforce policy on subsets of pages while others remain in report-only mode. Mixed deployment increases operational complexity.

How to verify

  • · Validation confirms the condition is resolved:
  • · • Content-Security-Policy header present in responses
  • · • Content-Security-Policy-Report-Only header removed
  • · • Browser blocks resources violating the policy
  • · • Console shows blocked resource messages, not just violation reports
  • · • Functionality remains intact with no legitimate resources blocked
  • · • Violation reports continue arriving at configured endpoints
  • · • Security scanners confirm enforced CSP is active

Takeaway

  • · Report-only mode observes violations without blocking resources
  • · Enforced mode blocks violations at runtime, providing actual protection
  • · The transition requires only changing the header name with identical directives
  • · Violation reporting continues in enforced mode when report-uri or report-to is configured
  • · Report-only should be temporary staging, not permanent deployment

FAQ

How long should report-only mode run before enforcement?

Long enough to observe all legitimate resource patterns. Most sites need one to four weeks to capture variation in user behavior, A/B tests, and seasonal features. Monitor violation reports for patterns that stabilize. When no new violation types appear for several days, the policy likely covers all legitimate cases. Extended report-only beyond observation needs provides no additional security value.

Can both report-only and enforced policies coexist?

Yes. Browsers process both headers independently. The enforced policy blocks violations while the report-only policy observes additional restrictions without blocking. This configuration allows testing stricter policies while maintaining current enforcement. Most deployments should not need both long term. Use dual mode temporarily when preparing policy tightening.

What happens to existing violation reports after enforcement?

Reports continue when report-uri or report-to remains in the enforced policy. Report format and content remain identical. The disposition field changes from 'report' to 'enforce' indicating actual blocking occurred. Report volume typically drops after enforcement because blocked resources stop attempting to load repeatedly.

Should enforcement happen globally or gradually?

Depends on confidence in the policy and risk tolerance. Global enforcement provides immediate protection but risks breaking functionality if the policy has gaps. Gradual rollout by page type or traffic percentage allows validation while limiting blast radius. Sensitive pages benefit from immediate enforcement. Public content pages can roll out more gradually.

What breaks when switching from report-only to enforced?

Any resource that violates the policy stops loading. Inline scripts that previously ran now fail. Third-party resources from undeclared domains do not connect. Dynamic style injection breaks if unsafe-inline is removed. Functionality appears to work in report-only mode but fails after enforcement. Violation reports in report-only mode predict exactly what breaks.

Does removing report-only improve performance?

Minimally. The browser still evaluates resources against policy directives in both modes. Report-only adds the overhead of console logging and report transmission. Enforced mode blocks resources earlier in the loading process, potentially preventing wasted bandwidth on blocked resources. The performance difference is negligible compared to the security benefit.

The fix

Intent: Activate runtime protection by moving from observation to enforcement mode

End state: Content-Security-Policy header enforces the policy with no report-only header remaining

  • Do not leave report-only mode active indefinitely as a permanent configuration
  • Do not enforce policy without first validating violation reports from report-only mode
  • Do not remove violation reporting when moving to enforced mode
  • Do not assume report-only provides any security protection