Introduction to Content Security Policy

Content Security Policy (CSP) is a built-in protection mechanism in web browsers that allows you to specify trusted sources for content such as JavaScript and allows you to block inline incudes. It can effectively stop attacks such as Cross-site Scripting and ClickJacking.

The settings are configured server side and given to the web browser via a server response header, the “Content-Security-Policy” header, here’s a simple example of one of these headers:

Content-Security-Policy: script-src 'self'; object-src 'self'

The header has a lot of options, but effectively it allows you to specify a resource type and then specify a whitelist of locations from which those resources can be loaded. So the above header is talking about script files and defining that only the same origin can be used to load resources by using the short name ‘self’, but we can whitelist sources easily using the following options:

‘none’Disallow all resource locations
‘self’Same origin only
*Wildcard, allows any URL except data: blob: filesystem:
domain.example.orgspecific domain
*.example.organy subdomain
https://domain.example.orgspecific domain and protocol
‘unsafe-inline’allow embedding of elements including script tags and handlers such as onfocus=, onerror=
‘unsafe-eval’allows evaluated JavaScript, such as eval()
data:allow loading resources via the data: scheme

We’re not only restricted to whitelisting sources for scripts, we can define where we can load scripts, images, videos, fonts, objects, all sorts. Here’s a few you might want:

default-srcDefines the default sources for directives which haven’t been given a more specific source list. So if you just specify this one it’ll set up the others for you, but you can specify default and then additional ones such as script-src and default-src will be used for all resource types other than scripts, which will use the more specific list given.
script-srcDefines valid sources for scritpts
style-srcDefines valid sources for CSS
frame-ancestorsDefines which pages may embed this page as a <frame> or <iframe>

A full list of directives can be found here: https://developer.mozilla.org/en/docs/Web/Security/CSP/CSP_policy_directives

Now you obviously want to configure your whitelist to be as restrictive as possible, but you don’t want to break any functionality you’ve forgotten about by blocking its source (such as analytics scripts for example!), so this requires a lot of testing. Thankfully there’s another header which can help:

Content-Security-Policy-Report-Only:

This header will simply log in the Chrome Developer Console any violations of the policy, but allow the execute to continue, you can also set up reporting, so the browser will send your server a list of violations, with a header configuration making use of the “report-uri” directive:

Content-Security-Policy: default-src https:; report-uri https://report.gracefulsecurity.com

Don’t forget though, that the reports are effectively user input, so you should ensure that you filter the input and ensure the application handles malicious input safely.

Violations are sent in JSON format and look something like this:

{
  "csp-report": {
    "document-uri": "http://example.com/testing.html",
    "referrer": "",
    "blocked-uri": "http://example.com/main.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /csp"
  }
}

A note on Browser Support

CSP is supported by all modern browsers, although it’s worth noting that the standard defines the header as:

Content-Security-Policy

But Internet Explorer uses:

X-Content-Security-Policy

So you might have to define both headers, to ensure the most compatibility possible!

Read More