Why your application needs a Content Security Policy (And How to Build One)


As a web application owner, it is crucial to understand the concept of a content security policy (CSP) and how it can protect your application. CSP is a powerful security control that can help prevent specific types of attacks, such as cross-site scripting (XSS) and HTML injection. In this blog post, we will discuss the importance of CSP and how you can build a CSP for your web application. Let's get started!

What is a CSP?

A CSP is a set of rules that are defined in an HTTP response header. These rules restrict how the browser will load certain types of resources. For example, you can use CSP to specify that only resources from your own domain can be loaded on your web page. This would prevent an attacker from loading malicious JavaScript from another domain on your page.

CSP can also be used to allowlist specific resources, such as JavaScript libraries, that you want to allow the browser to load. It is even possible to specify a resource's hash so that only the approved version of that resource will be loaded. This type of restriction helps prevent attackers from loading a malicious version of a resource that they control. Hash-based restrictions offer improved protection against supply chain attacks where a 3rd party resource becomes compromised.

CSP is a powerful security tool that can help protect your web application from certain types of attacks. However, it is important to note that CSP is not a silver bullet. It will not prevent all attacks, but it can be an effective part of your overall security strategy.

How do I build a CSP?

Building a CSP is relatively simple. You will need to add a CSP header to your web application's responses. The header should contain a list of CSP directives that define the rules for loading resources in your web page. Each directive in a policy includes the name of the directive and one or more values for that directive. Most directives end in -src, which means they will accept a list of sources for their value.

There are many CSP directives, but some of the most important ones are:

- 'default-src': This directive defines the default source for loading resources. Resources can be loaded from any source if no other CSP directives are defined.

  •  'script-src': This directive restricts where JavaScript can be loaded from.
  •  'style-src': This directive restricts where CSS can be loaded from.
  •  'base-uri': This directive defines which URLs are permitted to be set in the HTML base tag.
  •  'form-action': This directive defines valid sources for form actions.
  •  'connect-src': This directive restricts where XMLhttprequests (AJAX) can be made to.

There are many other CSP directives, but these are some of the most important ones. You can find a full list of CSP directives here: https://content-security-policy.com/

Example Policy

Here is an example content security policy:

default-src 'none'; script-src 'self'; img-src 'self' img.example.com; form-action 'self'

Let's break this down:

  • default-src: is set to 'none' which means the default behavior for all unspecified -src directives is to not load the resource no matter where it is. So this means things like AJAX calls and CSS simply won't load with this policy.
  • script-src: is set to 'self' which means scripts will only be loaded from the same origin as the page.
  • img-src: is set to 'self' img.example.com which means images can be loaded from the same origin as the page plus from the host img.example.com.
  • form-action: is set to 'self' which means forms can only be submitted back to the same origin as the page.

This is a very restrictive example policy, and most applications will need additional directives in order to work.

Which CSP directive values should be avoided?

When it comes to CSP directives, it is important to choose the right values. Some CSP directive values are more secure than others, and some should be avoided altogether.  The CSP source value 'unsafe-inline' is one of the least secure options and should be avoided if possible. 'Unsafe-inline' allows the execution of inline JavaScript, which can lead to XSS vulnerabilities. Another source value that should be avoided is 'unsafe-eval'. 'Unsafe-eval' allows the execution of arbitrary JavaScript code, which can lead to DOM-based XSS vulnerabilities. It is wise to design your application so that neither of these directives is necessary.

In addition to the above, * (wildcard) is a supported source value for directives and should be avoided in most situations.

How can you test and monitor your CSP?

The Content-Security-Policy-Report-Only header can be used to test if a CSP rule will be triggered without blocking the site from working.

Here's how it works: first, specify a CSP policy in the Content-Security-Policy-Report-Only header. This CSP policy won't actually block anything - it  will just report any attempts to violate it. Then, open your browser's console. Any violation of the CSP policy will be logged there.

This is a great way to test whether a new CSP rule will actually block anything on your site without breaking the application for other users.

By using the report-uri CSP directive, you can set up ongoing monitoring of CSP violations. This way, you can be sure that your CSP is actually doing its job.

Additionally, monitoring CSP violations can alert you to an attacker attempting certain types of attacks. For example, if you see a lot of CSP violations for a particular site, it may be due to an XSS or HTML Injection attack. You can stay one step ahead of the attackers by keeping an eye on these violations.