Reference Guide

Content-Security-Policy-Report-Only Guide

Set up the report-only HTTP header to test a generated CSP, collect violation reports, and avoid production breakage before enforcement.

Generate a CSP
Reference

What a report-only CSP header does

Content-Security-Policy-Report-Only asks the browser to evaluate a policy and report violations without blocking the page. It is a non-blocking way to learn what could break before switching to an enforced Content-Security-Policy header.

Compare

Report-only versus enforced CSP

Report-only policies observe behavior and surface CSP violation reports. Enforced policies block disallowed behavior. Use report-only for discovery and validation, then enforce when the policy is stable and reviewed.

Explainer

How do I test CSP before enforcement?

Deploy the generated policy with the Content-Security-Policy-Report-Only header, collect violation reports, compare blocked sources to expected user flows, then update the policy before moving it to the enforced header.

Review

What should I look for in CSP reports?

Prioritize violations from required scripts, API calls, frames, form submissions, and inline code. Noise from extensions or unexpected browser behavior should be separated from real application requirements.

Example

Example Content-Security-Policy-Report-Only header

This report-only CSP header tests a policy without blocking scripts, images, frames, or API connections that violate it.

Modern Violation Report

Modern Reporting API payload (application/reports+json)

The report-to directive uses the Reporting API. The browser sends a JSON array and can batch multiple reports in one request. CSP entries use type: "csp-violation" and camelCase body fields.

Legacy Violation Report

Legacy report-uri payload (application/csp-report)

The deprecated report-uri directive sends one JSON object with a top-level csp-report envelope and kebab-case field names. Collectors may still need this format for older browser behavior.

blockedURL / blocked-uri The source the browser would have blocked under the tested policy.
effectiveDirective / effective-directive The directive that controlled the resource after CSP fallback behavior.
documentURL / document-uri The document where the violation was observed.
sourceFile / source-file The page, script, or stylesheet that triggered the blocked load when the browser can identify it.
lineNumber / line-number The reported line for the attempted load, useful when tracking inline scripts or injected code.
disposition report means report-only. enforce means the browser blocked the resource.
Reporting Endpoints

Reporting-Endpoints, report-to, and report-uri example

For a compatibility period, define a named Reporting API endpoint with Reporting-Endpoints, use report-to, and include deprecated report-uri in the same policy for older reporting behavior.

Compatibility

Why send both report-to and report-uri?

report-to is the modern mechanism and is intended to replace report-uri, but older browser versions may only use the legacy directive. When both appear, browsers that use report-to ignore report-uri; legacy implementations can still post to the fallback URL.

Test the browser versions you support. Reporting can be delayed, batched, disabled, or dropped, so the absence of reports is not proof that a policy is ready to enforce.

Collector Input

Accept both report media types

  • application/reports+json contains an array that may hold several report types; process each supported csp-violation entry independently.
  • application/csp-report contains one legacy csp-report envelope.
  • Route parsing by the request Content-Type, reject malformed or oversized bodies, and return a small success response after bounded processing.
Collector Security

Treat every CSP report as attacker-controlled input

Warning: Every field can be forged, oversized, or crafted to attack logs, storage, and dashboards. Never render report values as trusted HTML or use them directly in queries, filenames, alerts, or log formats.

This is design guidance for a collector you operate. Script Sentinel does not currently provide a hosted public CSP violation collector.

Validation

Sanitize before storage or display

  • Allow only expected methods and media types, cap request bytes and batch length, and bound nesting, field counts, and string lengths.
  • Parse into a narrow schema, ignore unsupported report types and unknown fields, and reject malformed JSON without echoing it.
  • Normalize permitted URL and directive fields, encode values for their output context, and keep raw payloads out of application logs.
  • Treat sample, script-sample, URLs, referrers, user-agent text, and policy text as untrusted content.
Abuse and Noise

Rate-limit and deduplicate reports

  • Use bounded per-client and global request budgets, plus backpressure or dropping rules for traffic spikes.
  • Apply limits to both HTTP requests and the number of reports inside a modern batch.
  • Deduplicate with a server-computed fingerprint over sanitized fields such as document origin or path, effective directive, blocked origin, disposition, and a time bucket.
  • Store aggregate counts with first-seen and last-seen timestamps instead of creating an unlimited row or alert for every duplicate.
Data Governance

Privacy and retention

Report URLs, referrers, source locations, policy text, and code samples can expose account paths, query tokens, personal data, or application details. Collect only what the review workflow needs.

  • Strip URL user information, query strings, and fragments unless a documented use case requires a safer derived value.
  • Redact or omit code samples and other high-risk fields before storage, logging, analytics, or alert delivery.
  • Restrict access to stored reports, define a short retention window, aggregate older data when useful, and delete expired raw records.
  • Document the collector, processors, retention period, and deletion path in the applicable privacy notice.

For protocol details, consult the W3C Content Security Policy reporting specification and Reporting API specification.

Limit

What report-only CSP cannot protect against

  • It does not block malicious or unexpected scripts.
  • It does not replace real enforcement after validation.
  • It depends on useful CSP violation report collection and review.
  • It can be noisy if the candidate policy is too far from real behavior.
Rollout

Suggested CSP rollout sequence

  1. Scan the site and generate a candidate CSP.
  2. Deploy the policy as report-only.
  3. Review violations and expected third-party resources.
  4. Update the policy and retest.
  5. Enforce when violations are understood and acceptable.
  6. Monitor CSP drift after deployment.
Directive Glossary

Compact CSP directive glossary

These are the directives most often involved when you create a CSP, validate a generated policy, or read browser violation reports.

default-src Fallback policy for resource types that do not have a more specific directive.
script-src Controls JavaScript sources, inline script hashes, nonces, and risky values like 'unsafe-eval'.
style-src Controls stylesheets and inline style allowances, including hashes or nonces when used.
img-src Controls image sources, including common allowances such as same-origin CDNs or carefully reviewed data: images.
connect-src Controls fetch, XHR, WebSocket, EventSource, and API endpoints.
font-src Controls web font sources such as local assets, Google Fonts, or a private asset CDN.
frame-src Controls iframes and embedded content loaded by your page.
frame-ancestors Controls which parent pages may embed your page and helps prevent clickjacking.
object-src Controls legacy plugin content. Most modern policies set this to 'none'.
base-uri Restricts which URLs can be used in a document <base> element.
form-action Controls where forms can submit data.
report-to Names a Reporting API endpoint for CSP violation reports.
Premium Workflow

Use the CSP Rollout Assistant for monitored sites

Script Sentinel Premium turns report-only testing into a guided CSP rollout workflow for verified sites. It uses stored scan history to generate report-only headers, compare drift, and show enforcement readiness before you ship a blocking policy.

Compare Premium Plans

Report-Only CSP FAQ

Does report-only CSP block anything?

No. Report-only CSP evaluates the policy and reports violations, but the browser continues loading the page.

When should I move from report-only to enforcement?

Move to enforcement when violations are reviewed, required sources are accounted for, and the policy no longer blocks expected user flows.

Should report-only and enforced headers be identical?

They are often close, but some enforce-only directives are not useful in report-only mode. Review differences deliberately before deployment.

Why use both report-to and report-uri?

report-to uses the modern Reporting API and application/reports+json, while deprecated report-uri uses application/csp-report and supports older reporting behavior. During a compatibility transition, send Reporting-Endpoints, include both directives, and make the collector accept both payload formats.

Can I trust CSP violation report data?

No. Treat every field as attacker-controlled. Enforce request and field limits, sanitize before storage, escape before display, rate-limit and deduplicate submissions, redact sensitive URL and sample data, and apply a documented retention period.

Next Step

Generate a policy before report-only rollout

Run a Chrome-based CSP scanner first so your report-only header starts from observed resource behavior instead of a blank policy.

Run CSP Scanner