In Depth: Content Security Policy

[InDepth#7] CSPs are an incredibly powerful security feature built into the browser.

In Depth: Content Security Policy

A Content Security Policy (CSP) is an incredibly powerful web application security feature built into modern web browsers. It adds an extra layer of security by blocking unexpected content from executing, preventing Cross-Site Scripting and other injection attacks from affecting your site.

You define a Content Security Policy on your site through the a response header or a meta tag. The browser checks for a CSP before rendering the page, and if it finds one, it will follow the policy and prevent any unexpected resources from loading.

A CSP defines a list of directives relating to specific content types (i.e. scripts, styles, images, fonts, etc), and the resources from where these content types can be loaded. This allows them to be both incredibly specific and incredibly flexible, depending on what you need to cover your site. For example, you can use a CSP to only allow Javascript when loaded from an external file hosted on the same domain, while also allowing inline styles and fonts loaded from a third-party domain.

HTTP Header:
Content-Security-Policy: _policy_

HTML Meta Element:
<meta http-equiv="Content-Security-Policy" content="_policy_">

CSPs may sound quite daunting and complicated to set up (and like a great way to break your site!), but they are a lot simpler than they sound. Plus they include some features that make setting them up quite simple!

Writing a Basic CSP

Let’s get started with a simple example, to give you an overview of what a CSP is and how it works.

I’ll use a local copy of our demo site as an example, adding a basic CSP header. When I tell it to block everything through a CSP, you can see the page looks rather broken:

Broken webpage showing CSP header in the request and error message in the console. (Both the CSP header and the console error are included in text below the image.)
Broken webpage showing CSP header in the request and error message in the console.

This is the CSP header I added to the page:

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

And the error message in the console is:

Refused to load the stylesheet 'https://larasec.valorin.dev/css/app.css?id=...' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'style-src-elem' was not explicitly set, so 'default-src' is used as a fallback.

There are a few things going on here, so let’s bisect it.