Defaults.Exposed

Defaults.ExposedFixes › Content-Security-Policy (CSP)

How to fix Content-Security-Policy (CSP)

A Content Security Policy is a safety rule your website hands to every visitor's browser, telling it exactly which code is allowed to run. Without one, if anything malicious ever lands on a page — through a comment box, a hacked plugin, or a third-party script — the browser will run it freely, including code that quietly skims your customers' card numbers and passwords as they type, with the padlock still showing.

Bottom line for your business: If your site is ever tampered with, malicious code can read your customers' payment-card and login details straight off your own checkout while everything looks completely normal — leaving you with chargebacks, fraud claims, a reportable data breach, and a check failure that larger clients' security teams use to stall or kill a deal.

What this can cost you

Why it matters. The padlock proves the connection to your site is private, but it does nothing to control what code runs once a visitor is on the page. A Content Security Policy is the safeguard that does — it tells browsers to ignore any script that didn't come from a source you trust, so a single tampered field, ad, or plugin can't be turned into a tool for stealing your customers' money and data. It is a graded check on your scorecard, worth real points, and one of the first things a professional security review looks for.

What this is, in plain words

When someone visits your website, their browser downloads your page and runs whatever code is on it — the scripts that make menus drop down, buttons work, payment forms submit, and so on. By default, the browser trusts all of it. It has no way of knowing which code is genuinely yours and which was sneaked in by someone else.

A Content Security Policy (often shortened to CSP) is a short list of rules your website attaches to every page, telling the browser: “only run code from these sources I’ve approved, and refuse everything else.” It’s the difference between a nightclub that lets anyone in and one with a guest list on the door.

The reason this matters so much is that websites get tampered with constantly — not always by hacking your server, but through the back doors most sites leave open: a comment field, a search box, an outdated plugin, a third-party script for ads or analytics, or a chat widget. If an attacker gets even one line of their own code onto one of your pages, the browser runs it as if it were yours. From there it can read everything your customers type — card numbers, passwords, addresses — and quietly send it elsewhere. A Content Security Policy shuts that door by refusing to run anything from a source you didn’t approve.

What this can cost you

This is not abstract. The attack a Content Security Policy prevents — code injected into a page that steals data from your own customers — is behind some of the largest card-skimming breaches on record. Here is how it tends to play out for a normal business:

What it actually is (the detail)

A Content Security Policy is delivered as a single HTTP response header — a line your web server sends with every page. Its value is a set of directives, each naming a type of content and the sources allowed for it. For example:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self'

In plain terms, that says: by default only load things from my own site; only run scripts from my own site; allow no old-style plugins; and don’t let other sites embed mine in a frame.

What “good” looks like. Our check does not just look for the header’s presence — it reads the policy directive by directive and scores how strong it actually is, the way a security reviewer would. A strong policy:

A policy that exists but leans on 'unsafe-inline', 'unsafe-eval', or wildcards will still score poorly — because in practice it provides little real protection. The goal is a tight policy, not just any policy.

How to fix it (free, ~1–2 hours)

Hand this to your IT person or whoever runs your website — the fix itself is completely free. We only ever charge to monitor that it stays in place and stays correct over time; switching it on costs nothing. The reason this takes an hour or two rather than minutes is the careful trial step that stops it accidentally blocking parts of your own site.

  1. Start in report-only mode — do not enforce yet. Add a Content-Security-Policy-Report-Only response header. This watches and logs what would be blocked without actually blocking anything, so the live site keeps working while you learn what every page genuinely depends on. (Important: report-only on its own gives visitors no protection — it is only the safe first step.)

  2. Build the policy from what your site actually uses. Review the reports to find every legitimate source of scripts, styles, fonts, and images — your own domain, your analytics, your payment provider, your fonts host, your chat widget — and list them as allowed sources. A solid starting point is default-src 'self' plus explicit entries for the trusted third parties you really use.

  3. Avoid the loopholes that defeat the whole point. Steer clear of 'unsafe-inline' and 'unsafe-eval' for scripts, and avoid wildcard sources like * and bare schemes like https: for scripts — these re-open the exact gap the policy is meant to close. Where inline scripts are unavoidable, use a nonce or hash so only your specific approved code runs.

  4. Lock down framing and plugins. Add frame-ancestors 'self' (this also stops other sites embedding yours to trick your customers, and it satisfies the related clickjacking check) and object-src 'none' to block legacy plugin-based attacks.

  5. Switch from report-only to enforcing. Once the reports are clean and the site works, change the header name from Content-Security-Policy-Report-Only to Content-Security-Policy. This is the step that actually delivers protection — a report-only policy alone does not, and will not pass the check.

    Where you set the header depends on your platform:

    • Cloudflare: Rules → Transform Rules → Modify Response Header → set Content-Security-Policy. (You can use Cloudflare for the report-only trial too.)
    • Nginx: add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';" always;
    • Apache: Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';"
    • IIS (web.config): add a custom HTTP response header named Content-Security-Policy with the policy as its value.
    • Google Workspace / Microsoft 365: these run your email, not your public website, so the policy is set wherever your website is actually hosted (Cloudflare or your web host above), not in your email admin console.
  6. Re-check your domain to confirm the policy now shows as switched on and enforcing, with no weakening loopholes.

Common mistakes

FAQ

I'm not technical — can I deal with this myself?

You don't need to understand the details. This is a setting added by whoever runs your website or hosting, and on services like Cloudflare it's largely guided. Hand them the 'How to fix it' section below. It's free; the one caution is that it should be rolled out carefully in a watch-only trial first so it doesn't accidentally block parts of your own site — which is exactly what the steps cover.

I already have the padlock and an SSL certificate — isn't my site secure?

The padlock secures the delivery of your page; it doesn't police what runs inside it. If malicious code ever ends up on a page — via a hacked plugin, a compromised ad, or an injected field — the padlock won't stop it from stealing data. A Content Security Policy is the layer that limits what's allowed to run in the first place. They protect different things, and you want both.

Could turning this on break my site?

It can if it's switched on aggressively all at once, because it may block legitimate scripts you actually use. That's why the standard approach is to start in a 'report-only' trial mode that watches without blocking, fix anything it flags, and only then enforce it. Done this way it's safe — and the trial step is built into the fix below.

We put it in 'report-only' mode already — are we covered?

No, and this is the most common false sense of security. Report-only mode watches and logs what would be blocked, but it blocks nothing — visitors get zero real protection. It's only the safe first step. Our check gives report-only a small fraction of the credit of a real policy and will not record it as a pass. You're only protected once you switch to enforcing mode.

Does this affect our score, or is it just advisory?

It affects your score. The Content Security Policy check is graded and worth up to 25 points in the Web Security category. A missing or weak policy is marked high severity and drags your grade down — and it's exactly the kind of gap a client's security questionnaire asks about.

Our developer added a policy but the score is still low — why?

A policy can exist and still be weak. The most common culprits are loopholes like 'unsafe-inline' and 'unsafe-eval' for scripts, or wildcard sources (a bare *), which re-open the exact gap the policy is meant to close. Our check reads the policy directive by directive and scores down those weaknesses — a policy that allows anything scores little better than having none. The fix is to tighten the script rules using nonces or hashes instead of those loopholes.