Protect your data from Cross-Site Scripting Attacks
with Content Security Policy

Kamil Kusy Frontend Developer

Neglecting to implement a Content Security Policy (CSP) for your application can have unfortunate consequences for your business. Without a CSP in place, your application may be vulnerable to cross-site scripting (XSS) attacks, which can lead to a range of negative outcomes.

For instance, sensitive user data, such as login credentials and financial information, may be stolen and lead to data breaches. Additionally, attackers could use XSS to inject malware into your website which could then be spread to other users. This can cause damage to users’ computers and further security incidents, resulting in loss of customer trust and potential legal or regulatory issues.

Even though implementing a Content Security Policy (CSP) is a relatively simple process, we may run into some difficulties. Recently, when updating the CSP in one of our projects, I encountered an issue that required additional research and a specific solution.

After adding the directive:

script-src: ‘self’

[script-src is one of the main directives in the Content Security Policy (CSP) that specifies which sources of scripts are allowed to be loaded by the browser. It is used to restrict the types of scripts that can be executed on a website, which helps to prevent cross-site scripting (XSS) attacks. In this case, the value ‘self’ is used to allow scripts that are on the same origin as the website to be executed, while blocking any external scripts from being loaded.]

The following message greeted me in the console:

After thorough research, it turned out that one of the libraries we use in the project applies under-the-hood inline styles leaving us with two potential solutions. The first option was to utilize the “unsafe-inline” directive, however, this would disable the most vital aspect of the CSP and leave the application vulnerable to outside script injection. Therefore, the second option of adding a hash or nonce to the applied inline style was chosen as it is faster, simpler, and more effective for our specific use case.

How to:

As we can see in the console output, we already got our hashed script obtained using the SHA-256 algorithm (Secure Hash Algorithm 256-bit). How it’s working? The script is converted into a unique string of characters that cannot be reversed, i.e. having the output data (hash) we will not specify the input data. Here you can see what the hashing process looks like step by step.

The received hash must then be added to the CSP, remembering to enclose it within single quotes. The result would look like this:

script-src 'sha256-YGDvU5q+cB+Qm/hzBAtqUGTRsHo19RnXbGLHUr5Gk/o='

That’s all. 😊

It is important to keep in mind that any changes made to the script will result in a change of the hash, requiring the CSP rule to be updated accordingly. Additionally, whitespace must be taken into consideration and if the script is subject to frequent changes, it may be more suitable to consider using a CSP nonce. What is it?

A nonce (number used once) is a unique, random value that is generated for each request. It is typically generated on the server side and included in the Content-Security-Policy header of the response (just like the hash used above). It is generated anew for every request that your web server receives for a specific document, and unlike a hash, it is not dependent on the script code.

In conclusion, it is essential to protect your application and brand reputation by implementing a CSP, such as the script-src directive. Especially since so little can prevent so many potential threats.