CentralCSP
FeaturesCSP builder

Builder decision rules

The rules the CSP builder follows to turn violation reports into sources, flag noise, detect the policy you serve, and fill in the CentralCSP baseline.

Last update:

The Content Security Policy (CSP) builder suggests every value from rules you can check. Knowing them tells you when to trust a default and when to overrule it.

From a report to a source

Each CSP violation report names a directive and what the browser blocked. The builder turns that into the value that would allow it:

Browser reportedSuggested value
A URL on another siteThe origin of the URL (scheme, host, and port), such as https://cdn.example.com
A URL on your own website'self'
A data:, blob:, mediastream:, or filesystem: URLThe scheme, such as data:
Inline code in a script or style directive'unsafe-inline'
eval() or new Function() in a script directive'unsafe-eval'
WebAssembly compilation in a script directive'wasm-unsafe-eval'

The builder suggests origins, not full paths. One entry per origin keeps the policy short, and it stays valid when a vendor renames a file.

Reports caused by a browser extension, such as a chrome-extension:// URL, never become a source. Your site does not load those, and a policy cannot allow them. To drop them before they are stored, refer to Drop reports from browser extensions.

Reports that name nothing a policy can allow, such as a Trusted Types violation, are also left out. The review table counts them in a note.

Noise

Noise is a reported source that your pages do not need. The typical cause is software on the visitor's machine, such as an antivirus or an ad injector, that adds scripts to every page. Allowing it widens the policy for nothing.

The builder flags a source as noise in any of these cases:

  • The host belongs to a tool known to inject content into pages, such as an antivirus, a browser extension like Grammarly or Honey, or an adware network.
  • The source has very few reports, and they are a tiny share of the reports for its directive.
  • The source appears on only a few days of the period, and a single browser reported it while your site sees several.

The Detected as noise, rejected by default callout in the details panel says which of these applies, with the numbers behind it.

Noise starts rejected, but it is only a default. A rarely used page, such as a yearly campaign, can look bursty and still be real. Check the Noise filter before you deploy.

Detected policies

Every CSP report carries the policy that produced it. The builder groups the reports by policy and ranks the policies by how likely your site serves each one now. A policy reported often and recently ranks first, so a policy you deployed yesterday outranks one that ran for a year before you replaced it.

Each detected policy gets one of three labels:

LabelMeaning
Live policyVery likely the policy you serve today
Partial policyStill reported for part of the traffic, such as one section of the site, a staging copy, or a second header
Old policyNo report for two days, or a newer policy replaced it

After a deploy, your previous policy can stay labeled live for a few hours. Visitors keep cached pages that still send the old header.

The builder shows up to six detected policies. When one of them is live, it is the default starting policy. Otherwise, the default is the CentralCSP baseline.

The CentralCSP baseline

The baseline is the policy CentralCSP recommends as a secure starting point for every website. It allows only your own origin, and it reports every script that loads:

DirectiveValueWhy
default-src'self'The fallback for every resource type without its own directive
script-src'self' 'report-sample' 'report-sha256'Scripts from your own origin, with reporting keywords
style-src'self' 'report-sample'Styles from your own origin, with a sample of each blocked style
object-src'none'Blocks plugins entirely
base-uri'self'Stops an injected <base> tag from redirecting every relative URL
form-action'self'Forms submit only to your own origin
frame-ancestors'none'No other site can frame your pages, which blocks clickjacking
upgrade-insecure-requestsNoneRewrites every http:// resource request to https://

The two reporting keywords allow nothing. 'report-sample' adds the start of blocked inline code to its report. 'report-sha256' reports the hash of every script that loads, which feeds the script inventory. Both are safe in an enforced policy.

If you frame your own pages, set frame-ancestors to 'self' instead of 'none'.

When you start from your own policy

The builder keeps every value of the detected policy and completes it with the baseline:

  • A baseline directive your policy lacks is added. A missing resource directive starts with the values of its fallback, such as default-src, so it never narrows what already loads.
  • A baseline keyword your policy lacks, such as 'report-sample', is added to the directive.
  • A script-src that uses a nonce gains 'strict-dynamic'. Scripts your nonced scripts load are then trusted too.

These additions show as Recommended in the review table. Each one can be rejected like any other value.

A nonce in your policy comes back as the placeholder 'nonce-{RANDOM}'. Your server must replace it with a new random value on every response. A fixed nonce protects nothing. Refer to Nonces and unsafe-inline.

Risk flags

The builder grades the policy with the same analysis as the CSP evaluator. Every row carries its risk chip before you decide, including values you have not added.

Risk flags never change a decision on their own. A risky value your pages load stays added. Removing it first takes a change in your code, and the details panel describes that change.

If the analysis is unavailable, the builder still works. The risk chips are missing and the deploy step shows Analysis unavailable until you try again.

Periods and limits

The builder reads up to the last 30 days of reports. A website that sends a very large volume of reports is limited to 7 days at a time.

The API applies the same limits. The Build a recommended CSP endpoint defaults to the last 7 days, and each user can call it 10 times per minute. Refer to the API reference.

Next steps

On this page