How to Prevent Cross-Site Scripting (XSS) Attacks in React

How to Prevent Cross-Site Scripting (XSS) Attacks in React?

Cross-site scripting, also referred to as XSS is one of the prevalent and risky problems in the system being developed in web applications. It happens when the attacker embeds unauthorized code into any website or web application which in turn is run on the visitor’s browser. Such attacks may result in theft of identification details, session hijacking, and outright control of the user’s account. While being one of the most used front-end frameworks, React offers decent protection against XSS attacks out of the box yet it leaves much to be implemented to achieve good security practices. However, it is still possible for security issues to occur if, by mistake, developers allow un-sanitized data to be placed on the page. React developers need to appreciate what XSS attacks are and how best to safeguard their applications against such threats.

Whether you are a beginner or an experienced XSS attacker, this guide will provide you with an easy-to-understand explanation of the basics of XSS attacks and their impact on React-based applications. Then you will be guided through different steps on how to mitigate the occurrence of these attacks by embracing the common practices, using security tools, and following the latest development trends.

Types of XSS Attacks

Stored XSS: This is an attack that happens when viruses are permanently placed in the target server such as in a database or comment field. Each time the user visits the page containing the compromised code, the unauthorized script operates in the visitor’s browser.

Example: A user tags a comment with JavaScript code which is saved in the database and runs when the page is loaded for other users.

Reflected XSS: In this attack, the script is hidden in the link or the request and is automatically loaded inside the server’s response to the user. When using stored XSS, the malicious script is not even saved anywhere.

Example: A user receives an e-mail message with a hyperlink to the site containing the infected code; on the click of a button, an attacker’s script runs.

DOM-based XSS: This type of XSS is completely a client-side inclusion vulnerability. This is true when the DOM of the browser is compromised thereby running afoul of the scripting codes on the webpage. As with all types of XSS, DOM-based XSS can be achieved if the user input is used for changing the content of the page without proper input validation.

Example: While using the document. Location or inner HTML to refresh an element in a webpage without input data disinfection opens the application to DOM-based XSS.

How XSS Works

XSS attacks are most effective where the web application used does not adequately filter or scrub inputs. The browser can however not distinguish between good scripts and bad scripts, therefore it makes it execute any script that is hard coded within the web page. In the React applications, this problem can be seen when the user data handling is incorrect or the creators intentionally use potentially dangerous functions such as dangerouslySetInnerHTML.

Real-World Examples of How to Prevent Cross-Site Scripting (XSS) Attacks in React?

MySpace XSS Worm (Samy Worm): A stored XSS attack was carried out through a social networking site in 2005. A script was planted in the users’ profile where the account will default to sending friend requests and further distribute the exploit. 

British Airways Data Breach: The following year in 2018, the hackers took advantage of the loophole to plant their scripts and stole over 380,000 customers’ credit card numbers.XSS attacks are increasingly becoming a thorn in the flesh of React applications and are highly essential to understand how they affect them as we continue into the article. Despite this, React contains certain measures of security through escaping many types of input, it is still possible to accidentally open one’s self to XSS attacks by not properly sanitizing input or using features such as dangerouslySetInnerHTML improperly. 

Here's how XSS impacts React apps:

Session Hijacking: The attackers can exploit the XSS to capture the session tokens or cookies, which will help them mimic the victim. 

Example: If a React component retrieves input from the user, and processes it without using an escape or a sanitizer, the attacker will be able to place a script that sends the victim’s session cookies to a remote server.

Phishing Attacks: With XSS an attacker can post fake forms or login prompts on the real site and get unsuspecting users to submit information like login information.

Defacement: With the help of more hazardous scripts, the appearance of the webpage is changed, and fake data or incorrect information is displayed.

Why React Developers Need to Pay Attention

By default, React sanitizes the HTML content to avoid injection attacks. However, the authors mentioned that miscellaneous problems such as improper handling of user input, or when developers require using raw HTML in the DOM, can still cause vulnerabilities. 

For example, using features like dangerouslySetInnerHTML, or including third-party libraries without checking for security issues.

How to Control and Mitigate XSS Attacks in React

1. Sanitizing User Inputs

Especially when using values coming from the users always sanitize all inputs to be able to cut out on scripts that may be posted. There are plenty of libraries available in a market such as DOMPurify which is used to sanitize inputs and strip all the malicious content from it.

DOMPurify Example: 

import DOMPurify from 'dompurify';

const sanitizedInput = DOMPurify.sanitize(userInput);

2. Avoiding dangerouslySetInnerHTML

The film is also guilty of using ‘dangerouslySetInnerHTML’ which should never be made a good practice or normal. React’s dangerouslySetInnerHTML is one of the tools that are simple but rather dangerous: it helps developers render Raw HTML content. This should be minimized for it poses a potential risk of being hacked via cross-site scripting since the page inserts the HTML code into the DOM without escaping it. 

Unsafe Example: 
<div dangerouslySetInnerHTML={{ __html: userInput }} />
Safe Alternative: Always prefer rendering dynamic content safely using JSX:
<div>{userInput}</div>

3. Escaping Outputs

Check that all data that is shown in the DOM is escaped corresponding, if you use some third-party libraries which ignore special React features for the DOM protection.

Use escape functions to sanitize outputs:

const escapeHTML = (str) => str.replace(/[&<>"']/g, match => {

   const escapeChars = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' };

   return escapeChars[match];

});

4. Using JSX Safely

The use of JSX keeps on introducing HTML in the React components, but it is good to know how it works. JSX escapes everything by default so you are not vulnerable to injection attacks. Do not write HTML or JavaScript code in the JSX when programming with this language. Data validation must always be done before the data is rendered.

5. Content Security Policy (CSP)

CSP is an HTTP header that prevents XSS by indicating from where only a page can load different types of content. Successfully deploying a strict CSP for applications, prevents the execution of injected scripts from the attackers. 

Example of a basic CSP:

Content-Security-Policy: default-src 'self'; script-src 'self';

6. Validating User Data

Ideally the validation should be done before sending the information to the server and also on the server side. In terms of validation, it requires the client side to check data consistency before getting transmitted to the server; however, server-side validation is very important since only it can be the last line of defense for checking unsafe input.

7. Third-Party Library Security

As attackers go for the third party libraries, one can use npm audit or Snyk tools to detect certain vulnerabilities in those libraries.Run npm audit regularly to detect and fix vulnerabilities in your React project:

npm audit

Case Studies: Exploring XSS and Risks: Roles of React

Case Study 1: XSS is well handled in a commenting system:

Stored XSS was found in a commenting system that is built with React. Visitors could place scripts in the comment section and the contents were triggered each time other people viewed the comments. Solution: Protect input data via DOMPurify and use special escape to avoid execution of scripts.

Case Study 2: Preventing DOM-Based XSS Problem:

A shopping cart application that enabled users to change the contents of the page as they chose was present. However, DOM-based XSS vulnerabilities were discovered when inputs from the user were incorporated into DOM manipulation. Solution: HTML cleaning, use of secure DOM manipulation methods, and last but not least, always filter the inputs from the users.

Case Study 3: Preventing XSS in Third Party Includes Problem:

An eCommerce application was using a third-party plugin for displaying the product’s reviews. It failed to sanitize the inputs accordingly hence resulting in a case of the reflected Cross-Site Scripting vulnerability. Solution: Only download and install third-party plugins that have been tested for security issues and apply a basic cleaning to user-generated content.

XSS Prevention Techniques for a React Application

1. Trusted Types Policy

Trusted Types is a security feature of browsers and it was developed to eliminate DOM-based XSS. They were able to control the types of content that could be rendered in the DOM by only allowing trusted types by the developers. 

Implementing Trusted Types in React:

const trustedHTML = window.trustedTypes.createPolicy('default', {

   createHTML: (html) => DOMPurify.sanitize(html)

});

Subresource Integrity (SRI)

Subresource Integrity is a security component that checks whether resources or scripts loaded by the browser originated from a genuine source. Using SRI ensures an attacker will not execute this script within the browsers. 

Example of adding SRI:

<script src="https://example.com/somescript.js" integrity="sha384-..."></script>

Securing React with Modern Security Features

1. Webpack Security

Webpack, a popular bundler for React applications, can be configured to enhance security. Plugins like webpack-subresource-integrity help ensure that external resources are protected against tampering.

Example Webpack configuration for SRI:

const SubresourceIntegrityPlugin = require('webpack-subresource-integrity');

module.exports = {

   plugins: [

      new SubresourceIntegrityPlugin({

         hashFuncNames: [‘sha256’, ‘sha384’],

      }),

   ],

};

2.Using Web Application Firewalls (WAF) 

A WAF can add a layer of protection for React applications by detecting and blocking malicious traffic. Integrating a WAF helps mitigate XSS attacks before they even reach the application.

Common Mistakes React Developers Make

Misusing dangerouslySetInnerHTML: 

One of the most common mistakes is using dangerouslySetInnerHTML without fully understanding its risks. Developers must avoid using this method unless necessary, and even then, ensure that proper sanitization is in place. 

Ignoring External Libraries’ Vulnerabilities: 

Many developers use external libraries without verifying their security. Ensure that all third-party libraries are safe by checking for vulnerabilities regularly. 

Assuming React is Automatically Secure:

 While React offers built-in protections, it is not foolproof. Developers should not assume that using React alone guarantees security. 

Conclusion

Preventing Cross-Site Scripting (XSS) in React applications requires a combination of best practices, secure coding techniques, and the right tools. While React provides significant protection against XSS by escaping inputs by default, developers must remain vigilant and proactive in identifying and eliminating potential vulnerabilities. By sanitizing user inputs, avoiding risky practices like dangerouslySetInnerHTML, and implementing additional security features like CSP, React applications can be safeguarded from XSS attacks. Developers should adopt a security-first mindset and continuously audit and update their applications as new vulnerabilities are discovered. Preventing XSS is a continuous effort, but by adhering to these guidelines, developers can greatly minimize the risk of XSS in their React applications.