What Is CSP? Why & How To Add It To Your Website.

Cross-Site Scripting (XSS) sucks! XSS is when someone sneaks JavaScript or CSS into your site through a comment, a form, an advertisement or a NPM package that's part of your JavaScript build. Now they own every user's account that is visiting your website. XSS is such a common attack, OWASP claims it happens in 2 out of every 3 websites & apps.

You can eliminate most XSS attacks with a CSP (Content Security Policy). A CSP lets you list external and internal scripts, styles, images and other content sources to allow. It's even compatible with all the major browsers.

Since CSP can block one of the most common attacks known you think everyone would be using it, right? Nope! Less than 2.5% of the top million visited sites use it.

Dilbert Comic. Click link for a transcript.>

For most websites security is an afterthought, until someone steals all their data. Then the public rages on social media. The typical company response is to fire someone & promise to put security first, all while crossing their fingers behind their back.

Let's take a look at how we can avoid such a mess.

How to Add a CSP Policy

The first step is to add a header to your server configuration. It's recommended to start with the strictest CSP rule possible but set it to "report only" mode. This creates a report on what would happen if we blocked everything possible. Once you have your report you can start picking which items you want to allow (aka whitelist), which items to create alternate fixes for and which items to block.

Here's a recommended header to start with:

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none';

Once you've added the CSP to your website, you can use your browser developer tools to view it & any other headers.> Your CSP should appear along with your other headers when viewing your page in the browser's developer tools.

If we didn't set it to report mode, you would see "The full power of CSP!" In other words, the CSP would block most of your website.

Remember, the role of a Content Security Policy (CSP) is to block everything you haven't allowed.

If you open up the console in your browser developer tools (F12) you typically will see a lot of errors. The first error might complain about lacking a report-uri but we'll get to that later. The rest of the errors should all start with [Report Only]. This is the CSP report mode letting you know what content would be blocked & how to allow it.

A CSS stylesheet is often one of the first errors that will appear. It will look something like this:

[Report Only] Refused to load the stylesheet 'https://example.com/style.css' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.

To fix this, we adjust our policy by adding a style-src directive that allows 'self'. Adding 'self' allows us to include any CSS stylesheet hosted on the same URL & port number as our page. Without doing this, style-src defaults to the default-src directive which we have set to none.

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self';

Odds are high that you will also want to add 'self' to images and scripts. This would result in adjusting our CSP again.

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self'; script-src 'self'; img-src 'self';

A typical website needs to require external scripts as well. We can allow JavaScript from the domain cdnjs.com by modifying our script-src directive.

Content-Security-Policy-Report-Only: default-src 'none'; form-action 'none'; frame-ancestors 'none'; style-src 'self'; script-src 'self' cdnjs.com; img-src 'self';

One thought you might have looking at our current rule is why did we explicitly declare directives for form-action & frame-ancestors? They are special cases that do not use the default-src fallback.

You can find the entire list of directives on MDN.

Inline Script is My Middle Name

Inline JavaScript and CSS are often used on websites but they are also dangerous. They're the easiest way for a hacker to create an XSS attack. Therefore, to allow them you must add 'unsafe-inline' to the directive you want to allow them for. This is to make sure you understand what you're doing isn't recommended.

A common CSS pattern is to inline your most important CSS that renders your 'above fold content' with