Content Security Policy
A Content Security Policy tells the browser which scripts, styles and connections a page is allowed to use. Anything else is refused — which is what stops an injected script from running even after an attacker gets it onto the page. We build the policy in the dashboard and apply it at the edge, so your templates never change.
Start in Report-Only
A policy that is too strict breaks your site; one that is too loose protects nothing. Rather than guess, run it in Report-Only first. The browser evaluates the policy and reports everything that would have been blocked, while blocking nothing.
Leave it there for a few days of real traffic. Real visitors exercise paths you will not think to test — a checkout flow, a chat widget, an embedded map. Then read the Violations tab and allow what belongs.
Reading violations
Each violation names the directive that refused and the resource it refused:
Work through them one at a time:
- You recognise it and it belongs — add the host to that directive.
- You recognise it but it is obsolete — remove it from your site instead of allowing it. A policy is a good excuse to clear out dead third-party tags.
- You do not recognise it at all — that is the interesting case, and the reason to run this at all. Find out what put it there before allowing anything.
Nonces
Inline scripts are the hardest part of any policy: you cannot list them by
URL because they have none. The usual answers are 'unsafe-inline',
which gives up most of the protection, or rewriting every template.
We use a nonce instead — a random token generated fresh for every single request, stamped onto your script tags as the HTML streams, and named in the policy. The browser runs only scripts carrying that request's token. Because it changes on every request, a policy scraped from one page is worthless on the next, and an injected script never has the right token.
'strict-dynamic' lets scripts you trust load their own
dependencies without you listing every CDN by hand.
Per-path policies
Your checkout does not need the same policy as your blog. Create several policy groups and scope each to a path — the first group whose condition matches the request is the one applied, in priority order.
| Condition | Matches |
|---|---|
All pages | Everything. Use this as the catch-all, at the lowest priority. |
Path contains | Any URL whose path contains the text you give, e.g. /checkout. |
Path regex | A regular expression, for anything more precise. |
A common shape is a permissive catch-all for the marketing site plus one strict group scoped to the pages that handle money — exactly what PCI DSS asks you to demonstrate for payment pages.
Enforcing
When the Violations tab has gone quiet, switch the policy group from Report-Only to enforcing. The same policy now blocks instead of reporting. Keep watching violations for a day afterwards: enforcing changes behaviour, and it is worth confirming nothing was missed.
The master switch
The CSP master switch on the domain is hands-off, not report-only. With it turned off we send no policy at all and leave your response headers untouched — including any Content Security Policy your own web server already sends. Turning our CSP off never leaves you with less than you had before.
<meta http-equiv="Content-Security-Policy"> tag in the
HTML rather than a header, the browser applies both yours and ours, and a
resource has to satisfy each. If something you allowed here still gets
blocked, look for a meta tag in your page source.