How to Secure JSX in React

React’s JSX syntax provides built-in protections against security threats, but developers must still understand how to handle specific edge cases to keep their applications safe. This article explores how React automatically secures JSX by default, identifies potential vulnerabilities like Cross-Site Scripting (XSS), and outlines essential best practices for securing JSX in your React applications.

How React Protects JSX by Default

React is designed with security in mind. By default, React DOM escapes any values embedded in JSX before rendering them. This means that everything is converted to a string before being rendered to the browser, which effectively prevents Cross-Site Scripting (XSS) attacks.

For example, consider the following code:

const userInput = '<script>badCode()</script>';
const element = <h1>{userInput}</h1>;

React automatically converts the angle brackets into HTML entities (&lt; and &gt;). As a result, the browser displays the raw script as text on the screen rather than executing it as executable code.


Key Vulnerabilities in JSX and How to Fix Them

Despite React’s built-in escaping, developers can accidentally bypass these protections. Below are the most common vulnerabilities associated with JSX and how to secure them.

1. The Danger of dangerouslySetInnerHTML

React provides the dangerouslySetInnerHTML attribute as a way to insert raw HTML into a component. While sometimes necessary, using this attribute with unsanitized user input creates an immediate XSS vulnerability.

// INSECURE
const UserProfile = ({ bio }) => {
  return <div dangerouslySetInnerHTML={{ __html: bio }} />;
};

How to secure it: Always sanitize HTML content before passing it to dangerouslySetInnerHTML. Use a reliable sanitization library like DOMPurify to strip out harmful scripts while keeping safe HTML tags.

import DOMPurify from 'dompurify';

// SECURE
const UserProfile = ({ bio }) => {
  const cleanBio = DOMPurify.sanitize(bio);
  return <div dangerouslySetInnerHTML={{ __html: cleanBio }} />;
};

2. Unsafe URL Attributes (Attribute Injection)

React does not automatically sanitize URLs used in attributes like href or src. If a user can input a URL that begins with javascript:, the browser will execute that script when a user clicks the link.

// INSECURE
const UserLink = ({ userWebsite }) => {
  return <a href={userWebsite}>Visit Profile</a>;
};

If userWebsite is set to javascript:alert('Hacked'), clicking the link runs the malicious payload.

How to secure it: Validate and whitelist URLs to ensure they only use safe protocols, such as http: or https:.

// SECURE
const validateUrl = (url) => {
  try {
    const parsedUrl = new URL(url);
    return ['http:', 'https:'].includes(parsedUrl.protocol) ? url : '#';
  } catch (e) {
    return '#'; // Fallback for invalid URLs
  }
};

const UserLink = ({ userWebsite }) => {
  return <a href={validateUrl(userWebsite)}>Visit Profile</a>;
};

3. Rendering JSON and Server-Side Rendering (SSR) Hydration

When using Server-Side Rendering, developers often pass initial state from the server to the client by embedding JSON inside a <script> tag. If this JSON is not properly escaped, attackers can inject malicious closing tags (</script>) to execute arbitrary code.

// INSECURE (SSR)
<script>
  window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
</script>

How to secure it: Use specialized serialization libraries like serialize-javascript or htmlescape instead of standard JSON.stringify(). These tools automatically escape HTML tags inside JSON strings to prevent script injection.

import serialize from 'serialize-javascript';

// SECURE
<script>
  window.__INITIAL_STATE__ = ${serialize(initialState, { isJSON: true })};
</script>

Quick Checklist for JSX Security

  1. Avoid dangerouslySetInnerHTML unless absolutely necessary. When using it, always sanitize the input with DOMPurify.
  2. Validate protocols for href and src attributes to prevent javascript: payload execution.
  3. Keep React updated to ensure you benefit from the latest security patches and built-in protections.
  4. Use Content Security Policies (CSP) on your web server to act as an extra layer of defense against XSS attacks.