CSP stands for content-security-policy and this post will show you how to add CSP to a website using the <meta http-equiv> tag. It defines the sources from which your site can pull its data, i.e. the locations of your images, javascript, stylesheets or media. This greatly reduces the risk of XSS (cross-side scripting) attacks, which can inject malicious script into your page markup, because your CSP explicitly defines the trusted and non-trusted locations. A script running from hackme.noob won’t be allowed unless it has been whitelisted.

It can be enabled at server level, or set in .HTACCESS, or used in the meta http-quiv tag of a .html page. Some examples of what to create CSP entries for are Google Analytics, JQuery library, HTTPS, images/media and stylesheets.

There are some great examples at https://content-security-policy.com/ but I found some of the terms slightly confusing, so this is an attempt to clear them up and create an example of a good CSP entry. The CSP consists of directives, with multiples separated by a semicolon. The following are all basic CSP directives apart from child and form (italics):

  • default-src
  • script-src
  • style-src
  • image-src
  • connect-src
  • font-src
  • object-src
  • media-src
  • child-src
  • frame-src
  • form-action

CSP version 2 notable changes include the child-src replacing frame-src, and with the introduction of a SecurityPolicyViolationEvent.
CSP version 3 notable changes include frame-src being undprecated, and ‘self’ referring to https: entries of the same page.

For all full list of changes, click on the links to go through to the W3C pages for CSP levels 1, 2 and 3.

Most directives are fairly self-explanatory, for example image-src and font-src, and there is a full list of directives at the bottom. Connect-src applies to AJAX, Websockets or EventSource APIs. Will return a 400 HTTP code if not defined. To define <frame> and <iframe> sources, child-src is used and replaces deprecated frame-src directive.

Our CSP entry will define valid sources for everything, whether we use it or not. I don’t actually have any .js but that doesn’t mean I shouldn’t define its permitted sources. To be secure I need to define everything, so I could create an exhaustive list or I could just use the default setting. The full list is at the bottom, but some of the more common options would be:

  • *
  • ‘none’
  • ‘self’
  • https:
  • website.com
  • *.website.com
  • https://website.com

Again, these are all fairly self-explanatory, with the URLs allowing absolute URLs, wildcard * for subdomains and the https:// prefix. The two entries I am concerned with are ‘self’ and ‘none’. The term ‘self’ is slightly confusing because it doesn’t mean the same thing as an absolute URL, for example www.darklinkdigital.com/images, and it doesn’t mean the same thing as ‘anything on darklinkdigital’.
It refers specifically to the protocol, host and port. So a location of ‘self’ would refer to any file with the same protocol+same location+ same port as the file with the CSP settings. That sounds confusing, but practically it would mean that if I want to run https I would need a separate entry in my CSP file. Even though http://darklinkdigital and https://darklinkdigital are the same host they are different protocols and ports, and therefore https would not be classed as self.

A solo wildcard * seems fairly pointless, and I don’t want to restrict to https: only because I don’t use it. However it will be very useful to set the default-src to ‘none’. That means nothing will be loaded unless we explicitly define it. If we set default-src to ‘self’ then elements like AJAX or .js would be enabled even if we didn’t have them, and that would make us more vulnerable. Using default-src ‘none’ we are turning everything off by default and then allowing it bit by bit. This seems sensible.

To add this to our .HTML page, we set the CSP element and then define its content.

  • <meta http-equiv=”Content-Security-Policy” content=” “>

For a simple site our policy defines images, fonts, stylesheets and media like this:

  • default-src ‘none’;
    img-src ‘self’;
    font-src ‘self’;
    style-src ‘self’;
    media-src ‘self’;

Our finished entry looks like this:

  • <meta http-equiv=”Content-Security-Policy” content=”default-src ‘none’; img-src ‘self’; font-src ‘self’; style-src ‘self’; media-src ‘self’; “>

For a full list of directives see the Content Security Policy Reference at CSP.com or visit the CSP Policy Directives page at Mozilla Developers.