Why can’t I see a Content Security Policy on your website?

Drew Jarrett
4 min readAug 5, 2019

Short answer: I have no idea! It’s quick and easy to do, and is in place to keep your site (and accordingly, your users) safe. So do it. Thanks for reading :)

(Slightly) Longer answer:

I’ve supported many website builds throughout my career, both in Google London (at Google Brand Studio) and Sydney (as a Customer Solutions Engineer), and in my experience there are a few popular reasons why…

1) Maybe you don’t fully know what it is?
2) Too confusing (it shouldn’t be, read on).
3) It’s been getting in the way of using marketing pixels!

but if it’s a website build I’m managing then my answer will typically be — no excuses. Avoid a Death Star weakness. Let me explain in this blog.

Picture this…

It’s time for morning coffee and that quick glance over your favorite news website (I just checked my favorite news website and it doesn’t appear to have a CSP set at all 🧐).

An unbelievable news article grabs your attention. Perhaps you read about a pending stock market crash and need to act on it now, or a new important piece of software, but don’t worry it’s free to download now. We trust this news website, so react. The result, we do something silly in the stock market, or download a free — and potentially very malicious — piece of software.

(Obviously) that news story wasn’t real, in this pretend scenario the website was hacked and the content was injected by someone mischievous. That type of security breach is called a Cross Site Scripting (XSS) attack, achieved by exploiting known vulnerabilities in the web.

The Content Security Policy (CSP) helps protect against a large chunk of them.

What is a CSP?

In a nutshell, it’s a HTTP header setting that tells the browser where your website should allow content / resources to load from. Instead of trusting all sources, we restrict them. That’s it.

So in the case of our news scenario, the fictional news story would have been blocked before we even saw it, as the browser would have seen the content was from an untrusted source and blocked it.

By the way, it’s supported by all modern browsers.

How do I set it?

To get started add to your header…

Content-Security-Policy: script-src ‘self’ https://allowed-domain.com; img-src ‘self’;

Yes it’s this easy (ok, the text length will be a little longer in reality, but you get the gist). The header is set on the web server. As an example, within the App Engine world you would set this in the app.yaml.

What’s going on here…

  • Directives like script-src, indicate what website content we are restricting in this section of the CSP. The directives are separated by ‘;’. In this example I used script-src to indicate that section relates to all script files, and img-src to indicate that section relates to image files. You can include more directives, all detailed at content-security-policy.com (there is also a default-src directive to setup as a fallback).
  • Keywords like ‘self’, to help set rules around each directive. In this example ‘self’ tells the policy to allow any resources from the same domain. A few more keywords are available, again detailed at content-security-policy.com. Be careful with these, as some keywords distract from the security benefits (more on this below).
  • The list of domains that you trust the browser to allow content / resources from. In this case any content from https://allowed-domain.com will be allowed for third party scripts, and all other third party domains will be blocked. A popular set of domains to add here would be www.google-analytics.com and www.googletagmanager.com, to allow Google Analytics to work on your page.

It’s been getting in the way of using marketing pixels

The easy part is adding the marketing pixel domains to the CSP script-src and img-src (or just default-src) directives. The more difficult part is finding these domains since they are added dynamically and it’s not just the obvious ones. As you monitor the CSP these domains will become apparent, check out similar issues to you in online forums, and it’s worthwhile looking to see what domains other popular websites (with marketing tags) have used.

Marketing scripts are added inline on the website. There is a directive that enables inline scripts — ‘unsafe-inline’ — but we want to avoid this, as it would inhibit the XSS protection a CSP provides. This is where a nonce comes in handy. The nonce-value is a random number (used once) that we can associate with the script block and add to the CSP for whitelisting, and (unlike hashing) allows the script to stay dynamic.

Testing it

Now… just because you’re using a CSP it doesn’t mean you’re fully XSS protected! The CSP could be setup wrong, missing something, or still open to an unknown vulnerability.

As an example. Modern day CSP policies (CSP3) allow the use of ‘strict-dynamic’ (to accommodate dynamic scripts) but in older browsers this falls back to the CSP keyword ‘unsafe-inline’.

The CSP Evaluator site is a super useful way of reviewing the policies you’ve set to ensure they are safe for the popular browsers using your site, and may identify possible issues or vulnerabilities.

…and remember you should still care about XSS even with a fully working CSP.

Thanks for reading, and for making the web safer,

Drew Jarrett

--

--

Drew Jarrett

Working @Google across SYD & LDN. Developer. Innovative. Problem solver. Passion for making a difference through what I do. Proud Dad of two amazing girls.