Why should I use Content-Security-Policy?

HTML and Web Applications are the dominant applications of our time. HTML was originally designed as a read-only documentation format and over time became rich, interactive. Many popular web applications today accept user-generated content (comments, images, etc.) and then display to other users.

In addition, as the web has become more complex, sites have adopted libraries from many 3rd parties, including ones which dynamically choose content such as advertisements and news feeds.

When you mix these things together you create risk. A user, entering their credit card into a travel-site to buy something alongside an advertisement, presented via JavaScript coming from a CDN, and community comments, is a recipe for security disaster. And yet, it’s the norm.

Many different tools address this challenge, but today we will talk about the most powerful (and most complex), Content-Security-Policy.

Content-Security-Policy is a header that a web site emits, instructing the browser what to allow and deny, broken down by type (fonts, CSS, images, etc), and by domain (self, inline, other websites).

A strong, secure Content-Security-Policy will only allow `self`. This means that we allow nothing hosted anywhere other than the source web server. However, this is not very realistic, it prohibits e.g. Google Analytics, fonts served from a CDN, etc. Previously I showed how to use Google Tag Manager with Content-Security-Manager.

The risks you protect against with a strong Content-Security-Policy include unsafe 3rd party code evaluating (running) in the page model of the browser for your web page. Some pages are more sensitive than others (login pages, form submittals). However, with modern applications,  a session cookie or a JSON Web Token (JWT) representing the login and permission, are available on all pages: we need the Content-Security-Policy to be strong on all pages.

A hybrid between `self` and named sites is called subresource-integrity. The browser checks a signature of the content, executing it only if matched. This is far more flexible than trying to estimate all possible sources of 3rd party content. However, it can be challenging to set up since all libraries must support it.

If possible, use either `self` or subresource-integrity for all types. Block `object`. Do not allow `unsafe-inline` or `unsafe-eval` or `data:`.

If you have an Angular application, I recommend compiling it as

ng build --aot --subresourceIntegrity --outputHashing=all --prod=true

An excellent resource to assess your Content-Security-Policy is the Mozilla Observatory.

If you own and operate a web application, whether it be a static site like WordPress, or an e-commerce site, you must setup your Content-Security-Policy. No exceptions. Your customers fate rests in your hands, be responsible.