Why a Content Security Policy is a Must-Have for Web Devs

Why a Content Security Policy is a Must-Have for Web Devs


Dec 7, 2023
by jessicadunbar
in DevOps

As the digital landscape continues to expand, organizations face increasing challenges with cybersecurity. Websites are particularly vulnerable, with cross-site scripting (XSS) the most common issue discovered by bug bounty hunters in 2022—up 32% from the previous year.

For WebOps teams who deploy and manage multiple websites, it’s never been more critical to increase security. But aside from validating user input and sanitizing data, what more can you do to prevent a cyberattack?

Step forward, Content Security Policy. This protocol delivers extra protection by allowing you to control the resources loaded on your web page by the browser.

But does CSP protect against XSS? And what is a CSP header used for? In this post, we’ll find out.

dark hacker photo.jpg

Free to use image sourced from Pixabay

What Is a Content Security Policy?

A content security policy (CSP) is a security standard that helps WebOps teams give websites and applications an extra layer of protection. The framework is designed to detect and mitigate various cyberattacks, including cross-site scripting (XSS), clickjacking, and data injection.

Supported by most modern browsers, CSPs deliver protection through the Content-Security-Policy HTTP response header (or an HTML alternative). This is a string of code that gives security instructions to the requesting browser, controlling the resources it’s allowed to load—such as JavaScript, CSS, and images—and the URLs it can load them from.

CSPs implement a same-origin policy, so that the browser may only execute code from valid sources. They block the execution of malicious scripts from untrusted sources, guarding against things like data theft, malware distribution, and unauthorized access to IoT devices

Why is a CSP Important for Web Developers?

CSPs bring a host of benefits for web developers. By protecting against data loss and data injection, the protocol gives you peace of mind that the website or app you’ve developed is secure, and won’t cause any problems for end users or the organization you built it for.

A CSP gives you a high level of granular control over things like inline script execution and dynamic code execution. Plus, it’s flexible. You can include as many or as few restrictions as you like, and create separate directives for elements like frames, fonts, scripts, and styles.

So, how exactly does a CSP work? When a user clicks through to a dynamic web page, the browser they’re using will load various assets like fonts, stylesheets, and JavaScript. These inform how the page looks and behaves. 

The problem is, browsers are too trusting­—they don’t question the source of the content. And user-generated input is particularly vulnerable. Therefore, an attacker could trick the browser into loading malicious content hosted from their own source onto a vulnerable page. 

But with a CSP in place, server admins can tell the browser which content sources are to be trusted, so that it only executes scripts loaded in source files received from permitted domains. You can also specify the protocols to be used, such as stating that all content must be loaded using HTTPS. These reduce or even eliminate the potential routes for XSS and other attacks. 

In short, CSP is an important part of operational risk management. As a developer, you can use it to ensure the sites and apps you create will protect end users from having their data compromised. 

When it comes to security, it's important to be vigilant, especially if you're considering web outsourcing for development projects. Establishing clear Non-Disclosure Agreements (NDAs) with external partners is crucial to safeguard sensitive data and maintain security standards. 

Additionally, taking proactive steps such as code refactoring, relocating inline scripts, enhancing event handlers, and implementing Subresource Integrity (SRI) can further mitigate vulnerabilities and script alterations, whether you're handling development in-house or through web outsourcing.

Computer lock.jpgFree to use image sourced from Pixabay

What Does a CSP Contain?

Configuring a content security policy involves adding a CSP header to an HTTP response. The CSP header contains a set of values or “directives” that specify valid sources for content, which the browser is allowed to load. You can also add a list of sources that must be prevented, by specifying server origins and script endpoints. 

There are specific directives for various types of resources, with each type having its own policy. This includes scripts, fonts, frames, images, audio and video media, so you’re covered no matter how many design elements your website has. Directives are categorized according to use-case and content attribute, such as:

  • Fetch directives that specify locations for loading certain resource types
  • Document directives that show where a policy will be effective
  • Navigation directives governing the locations of a form submission
  • Reporting directives that dictate how CSP violations are documented and reported.

How Do I Create CSP Policies?

You can deploy a CSP as a HTTP response header or an HTML meta tag. To configure your web server to return the HTTP Content-Security-Policy header, use:

Content-Security-Policy: [directive] [resource type]

To use the HTML <meta> element to configure a policy, it looks like this:

<meta http-equiv="Content-Security-Policy" content="[directive] [resource type]">

Let’s imagine we’re creating a policy for scripts. This would involve a script-src directive, where the src attribute specifies the location (URL) of the external resource.

If you want the page to only load scripts that come from the site’s own origin (the same server that’s hosting the page), you could use the header: Content-Security-Policy: script-src 'self'

‘script-src’ is the directive, while ‘self’ is the metasource: this tells the browser where it may load scripts from. This header doesn’t list any other sources, so the browser knows to only allow scripts from your domain.

If you want the page to load scripts from a certain domain, you can specify this in the CSP with: script-src <allowed-web-url>

For example, Content-Security-Policy: script-src 'self' https://vonage.com/ would allow the browser to load scripts from your own domain, and Vonage.

You can also use img-src 'self' to restrict the origin of images to be loaded. This helps to protect against dangling markup attacks. If you didn’t want any images/scripts to load at all, you’d use 'none' as the metasource. To load images from any origin, use the wildcard source (*).

CSPs also use values called “nonces” and “hashes” to restrict scripts and mitigate XSS attacks. A nonce (number only used once) is a random value specified in the CSP, which checks for matches before executing the script. Any script in a block containing the nonce can run. With hashes, a script may only run when it contains a hash that exactly matches the value in the CSP directive.

You can specify multiple policies in one header, by separating them with semicolons. So, for example, you could set the CSP to allow images from any origin, but scripts only from specified sources: img-src * ; script-src <allowed-web-url>

Considerations For Using a CSP

Implementing a Content Security Policy is not always easy, nor is it a one-and-done task. For dynamic or complex web projects—for instance, setting up an app for a virtual call center—you’ll need to write policies for multiple pages and ensure you update them as necessary. An automated CSP management tool can be useful.

Browser Support

All major browsers support CSPs, although the level of support may differ. CSP level 2, which adds hashes and nonces, is supported in almost all browsers. You can check which browsers support a certain directive with the Can I use tool. Browsers that don’t support CSP still work with servers that implement it.

Testing the CSP

You can test the security of your CSP by using a proxy tool to examine the meta or response header. Look out for any insecure configurations, such as unsafe-inline event handlers (which can lead to malicious content being inserted into the web server) or the unsafe-eval directive that’s used in many analytics scripts.

It’s also good practice to double-check resources that can be loaded from any origin using the wildcard (*) source. Make sure you haven’t added any restrictions that might negatively affect the site performance—for example, if you omit a required domain from the CSP whitelist, the resources won’t be loaded by the browser and end users won’t be able to use the application.

There are various free tools available online for checking your CSP, such as CSP Evaluator and CSP Validator.

Reporting

Apart from denoting which assets you wish to control, directives are also split into two categories: blockers and reporters. Blockers restrict input into the application (such as img-src), while reporters deliver reports about those blocks. Web admins and developers can then see which of their CSP directives are being targeted, which helps to reveal vulnerabilities.

The reporters report any violations to a provided URI. It’s also possible to run CSP with a report-only header—this is helpful if you want to test a planned revision to a policy without actually deploying it. You can see what sort of effect it’ll have on your website.

Extra Measures

There are a few other ways to improve your CSP and secure your site. For example, you might need to reorganize and refactor the application code, move inline scripts to external files, and rewrite inline event handlers and JavaScript URIs. You can also implement Subresource Integrity, which protects against attackers who seek to take control via an external CDN and modify the scripts.

In addition to implementing a Content Security Policy (CSP) to enhance your website's security, it's essential to consider broader security measures to safeguard your business from various cyber threats. This includes understanding what you need to know to shield your business from ransomware, and taking proactive steps such as code refactoring, relocating inline scripts, enhancing event handlers, and implementing Subresource Integrity (SRI) to mitigate vulnerabilities and script alterations by external sources.

One potential vulnerability for XSS attacks is when a visitor inputs information into a form, such as a sign-up for a virtual phone system. If they enter JavaScript into the query variable, it’ll be output by the site. If you’re using Concrete CMS, you can use the h() function to mitigate this—any malicious JavaScript in the request will be encoded, so it can’t cause any damage when it's output.

Remember, the role of CSP is to block the execution of scripts that don’t meet your criteria. It can’t completely eliminate vulnerabilities that can lead to cyberattacks like XSS. It’s designed to mitigate client-side attacks on your website or app, so you’ll need to take extra measures to guard against server-side or database attacks.

Final Thoughts

Whether you’re developing or administrating websites, it’s vital that you do as much as possible to prevent cyberattacks like XSS. Yes, using reputable tools such as Concrete CMS will give you protection, but a content security policy is a must-have.

This is especially important if your website is dynamic or if it involves a lot of user input. Remember, CSP is most powerful when it’s developed in projects right from the start, but you can create new policies and adjust the directives every time you update the website content.