Skip to content
Reporting on the technology of the open webThe Allow Copy tool

05Web & Browsers

Content Security Policy From Scratch, Without Breaking Your Own Site

Roll out a content security policy (CSP) and immediately block vital inline scripts, and you deserve every broken site you break. Take the proper step of deploying in…

Published 8 September 2026

Content Security Policy From Scratch, Without Breaking Your Own Site
Photo: Mehranshargi · CC BY-SA 4.0 · Wikimedia Commons

Roll out a content security policy (CSP) and immediately block vital inline scripts, and you deserve every broken site you break. Take the proper step of deploying in "report-only" mode first and monitoring data, then tighten the policy based on that evidence – and you have a fighting chance of winning this hard-won security gain.

TO VERIFY: Facts go here. The editor's furnished material.

There should be no doubt about this: The Content-Security-Policy-Report-Only header is for monitoring CSP's effects, not for enforcement. When a policy with Content-Security-Policy-Report-Only causes a violation, it won't block the violation but will generate a violation report instead.1,2,4[/REF]

But don’t assume reports will arrive automatically; they won’t unless the report-only header specifies where to send those reports. In browsers that support it, you use the report-to directive, not the deprecated report-uri directive, to set the reporting destination.4,7,11[/REF] The key point is that reports will only flow when this reporting plumbing is correctly wired; the base Content-Security-Policy-Report-Only header alone does nothing if reporting is not configured.4,7[/REF]

Once the reporting destination is set and the policy is deployed, the browser will attempt to send violation reports to the specified destination whenever a directive is violated.7[/REF] These reports take the form of CSPViolationReport objects, and they clearly distinguish which policy was violated. The reports that come in during a violation will be marked with "reporting", as they are coming from a report-only (non-enforcing) Content-Security-Policy-Report-Only.2[/REF] Only once enforcement is turned on with the Content-Security-Policy header will you see violation reports marked "enforce". For now, it’s just monitoring.2,4[/REF]

Now comes the hard part: There are situations where content must be loaded inline, and the default CSP policy blocks those, no exceptions.7[/REF] To allow specific inline content, you must either refactor the inline code into an external source (the safest bet), include a nonce, or include a hash. Both nonces and hashes must exactly match between the CSP header and the inline source.5,15[/REF] To include a nonce, you generate a cryptographically secure random nonce value per response, include it in the CSP Content-Security-Policy-Report-Only header, and then include it in the HTML nonce attribute of the element being allowed, like a script or a style.5,15[/REF] The inline may be a full script, or it could be a style. The CSP directive to configure is style-src, which has exactly the same rule about allowing inline sources: only when included with its own hash, nonce, or the unsafe-inline exception.5,7,9,14[/REF]

TO VERIFY: Which CSP directives are “standard” versus optional, and therefore which directives should be prioritised in this roll-out: can we get a statement from a primary source, either a standards document or a browser vendor’s production-enablement guidance?

That’s where the policy tweaking typically starts. Every inline script and inline style you allow – whether you choose a nonce, a hash, or the unsafe-inline exception – is a concession CSP will have to evaluate relative to the risk of XSS on your particular site.5,7,9,14,15[/REF] That’s why report-only is so crucial: You use it to discover, understand, and alter the worst offenders, and carefully tighten up the policy, before a misconfiguration of script-src or style-src could block the site’s inline scripts on deployment.

TO VERIFY: Is there a documented recommendation in a primary source, possibly from a browser vendor, about whether to start a CSP roll-out in production with report-to or the legacy report-uri directive?