var self = justin();

Software Developer Teammate

A place to remind my future self of what I've learned and experienced. That means both my successes and failures.


Content Security Policy Header 101

Let's say you are developing a website. As a security minded individual, you take care in protecting against malicious scripts being injected into your site by evil-doers. You implement security code reviews to find and seal up and content that isn't being html-encoded when rendered. You scrub the input and perform server side checks for offenses like script tags or malformed html. You do every thing you can think up to prevent script injection.

Try as you might, let's say you missed something. Maybe you rotate team members in various areas to get experience throughout the product and they accidentally expose a vulnerability, or maybe that new guy you just hired didn't understand how allowing users to post html comments via @Html.Raw() is a huge security hole. In any case, there's an opening that you didn't find and someone adds a little bit of html that is going to wreck havoc on your user base:

<script src="http://evilsite.com/evilscript.js"></script>

How do you prevent it? Of course you can go back and try to find the hole, which you should, but there is something else you can do and that's where the Content Security Policy (CSP) header comes into play.

Basically, CSP allows you to tell the browser the places it can download content. With it, you can say "Ok, you are allowed to download pictures from safeImages.com, scripts from safeScripts.com and media from safeMedia.com... oh and everything else can only be downloaded from the same place you received me from."

Being able to dictate a white list of allowable sources that content can be downloaded from is a great step towards securing a site. Here's a break done of what how to construct the CSP:

Content-Security-Policy: <directive> <keyword>|<source>

So a directive is an area you want to restrict like scripts. The keyword defines a special instruction and the source is where content can be downloaded.

How about you want all content to only be available from your domain?

Content-Security-Policy: default-src 'self';

Perhaps you want to allow scripts to be downloaded from only safeScripts.com. The CSP would like this:

Content-Security-Policy: default-src 'self'; scripts-src safeScripts.com;

Notice the 'self' keyword? That means only the address (and port) the browser downloaded the page from is allowed. The default-src means anything that you haven't explicitly set.

Here's one, see if you can figure out what it does.

Content-Security-Policy: default-src 'self' *.mydomain.com; media-src 'none'; scripts-src http://cdn.google.com;

Figure it out? Everything by default can be downloaded from the originating address by default and any subdomain of mydomain.com. No media can be downloaded and scripts can also be downloaded from google's cdn. This should give you an idea of how to use the CSP.

For a complete list of directives, the best place is the Mozilla Developer Network.

Lastly, there is one extremely important piece I haven't covered and that's using the reporting side of CSP. You can define a URI for the browser to automatically send JSON packages to when the content in the markup is attempting to make the browser download from outside of the domains in the CSP. This is huge! Automatic reporting on potential attacks! You just need an endpoint and some persistence to get this working. If any is interested in a basic sample, I can make one and link it here. Just let me know in the comments.

Hit me back if you have any questions or comments.

Left out the browser support:

Browser Support Introduced
Internet Explorer 10+
Firefox 4+
Opera 15+
Safari 5.1+
Chrome 14.0+
comments powered by Disqus