Content Security Policy has never been simpler

 

Application security is about adding extra layers of protection. One easy win is to add a Content Security Policy (CSP) to your web application’s headers.

What is a CSP? And how does it protect your web application? Let’s dig in and understand why a CSP is an important layer in your app’s security.

Quick Content Security Policy FAQ

What is a Content Security Policy header?

The CSP ensures that assets loaded by a user’s browser are part of the whitelist defined in the content security policy header, named “Content-Security-Policy”.

What protections does a Content Security Policy offer?

Enforcing a CSP can protect your app from cross-site scripting (XSS), clickjacking and other code injection attacks.

How does a Content Security Policy work?

A Content Security Policy (CSP) is based on a powerful HTTP header that restricts the browser to loading external assets such as scripts, styles or media from a wide variety of sources, as well as inline scripts. So let’s say your website loads Google Analytics or Facebook JavaScript files. Those will only be loaded by your users if Google and Facebook are part of your CSP whitelist.
Read more about the nitty-gritty details here.Content Security Policy CSP

What are the limitations of implementing a Content Security Policy?

The configuration and maintenance of a CSP can be really painful. The number of reports received can quickly become unmanageable. Making mistakes in your policy can have bad consequences.
If you want to read more about real-life implementations of CSP take a look at Github’s CSP journey and Troy Hunt’s experience.

So should I implement a Content Security Policy (CSP) header to my app?

The quick answer is yes. The level of protection that a good Content Security Policy brings, outweighs by far the implementation pains.

So let’s see how you can implement it in your app.

Implementing a CSP in your app

Adding the security header

The most common implementations of CSPs are either directly in your server configuration or using a library.

If you’re using standard technologies, the best way to implement your Content Security Policy is probably to use one of the widely used libraries.

  • Ruby
    • For Rails apps, use the “Secure Headers” gem developed by the Twitter engineering team. It will also add several other important security headers in your app.
  • Python
    • For Django apps, the most popular library is Django-CSP from the Mozilla team.
  • Node.js
    • To implement a Content Security Policy in Node.js, you can use the Helmet package. Helmet will also add the main HTTP headers in your Express app.
  • PHP
    • For PHP apps you can use the csp-builder package to integrate your CSP.

Configuring your Content Security Policy

Now that you’ve added your CSP to your app, it’s time to configure it.

A complete policy defines a set of allowed and restricted behaviors and is comprised of directives and sources. Here are some of the directives that you can set with concrete examples from mozilla.org:

  • `script-src`: Specifies valid sources for JavaScript.
    • Example: script-src ‘self’ *.mozilla.net *.mozilla.org *.mozilla.com
  • `img-src`: Specifies valid sources of images and favicons.
    • Example: img-src ‘self’ *.mozilla.net *.mozilla.org *.mozilla.com data: *.optimizely.com www.googletagmanager.com www.google-analytics.com *.tiles.mapbox.com api.mapbox.com creativecommons.org ad.doubleclick.net sp.analytics.yahoo.com
  • `child-src`: Defines the valid sources for web workers and nested browsing contexts loaded.
    • Example: child-src *.optimizely.com www.googletagmanager.com www.google-analytics.com www.youtube-nocookie.com trackertest.org www.surveygizmo.com accounts.firefox.com accounts.firefox.com.cn www.youtube.com
  • `default-src`: Serves as a fallback for the other fetch directives.
    • Example: default-src ‘self’ *.mozilla.net *.mozilla.org *.mozilla.com
  • Etc.

The detailed list of directives can be found on the w3.org website.

Each policy has an associated disposition, which is either “enforce” or “report”. Reporting will not block any request. It can, however, report the policy violations if you configured the report-uri directive.

Finally, each directory has a source set that can be either a specific domain, a subdomain, etc.

Here is the inferred Content Security Policy example for Github:

Once it’s deployed you will need to closely monitor for new violations and update your policy accordingly.

If you’re looking for a way to easily implement and manage your Content Security Policy then carry on

A modern Content Security Policy

Sqreen, just like the other tools we mentioned earlier, is a library that you can simply add to your app. It will insert the most important HTTP security headers without needing big configurations: X-Xss-Protection, X-Frame-Options header, Referrer-Policy HTTP header, X-Content-Type-Options header and of course the Content Security Policy header. (It does so much more than that but that’s not the point of this article).

Implementing a CSP with Sqreen

Let’s take the example of implementing a content security policy in a Node.js app.
It just takes a couple of minutes.

First, register to Sqreen.
Then create an app and retrieve the Node.js installation instructions.
It should look similar to this:
Install the package from npmjs and save it into your project:

npm install --save sqreen
echo '{ "token": "YOUR_TOKEN" }' > sqreen.json

Require Sqreen at the top of your main script:

require('sqreen');

That’s it! Now just relaunch your application and enable a CSP in your app settings:

Content Security Policy Generator Sqreen

Why would you want to use Sqreen to add a CSP to your app?

Sqreen Content Security Policy CSP

Sqreen offers several advantages:

  • It offers an automated Content Security Policy generator without errors
  • You can deploy it in just one single click
  • You will be notified whenever there is a suspicious or known-to-be malicious domain that starts generating violations
  • You will get domain suggestions to add to your policy

Let me know if you have any questions!