Frontend Development 15 min read

Understanding XSS Attacks in React

This article explains what XSS attacks are, categorizes their types, and demonstrates how React’s automatic escaping, JSX compilation, and internal element validation work together to mitigate XSS vulnerabilities while highlighting common unsafe patterns and server‑side defenses.

政采云技术
政采云技术
政采云技术
Understanding XSS Attacks in React

Preface

Frontend developers often face XSS security risks, but modern frameworks like React provide built‑in defenses. This article examines React’s source code to see how it prevents XSS.

What is XSS?

Cross‑Site Scripting (XSS) is a code‑injection attack that lets an attacker inject malicious scripts into a web page, which the browser then executes, potentially stealing data or performing actions on behalf of the user.

Types of XSS

Reflected XSS

XSS script comes from the current HTTP request.

When the server concatenates request data into HTML without sanitisation, the payload can be crafted via the URL.

// 某网站具有搜索功能,该功能通过 URL 参数接收用户提供的搜索词:
https://xxx.com/search?query=123
// 服务器在对此 URL 的响应中回显提供的搜索词:
您搜索的是: 123
// 如果服务器不对数据进行转义等处理,则攻击者可以构造如下链接进行攻击:
https://xxx.com/search?query=
// 该 URL 将导致以下响应,并运行 alert('xss'):
您搜索的是:
// 如果有用户请求攻击者的 URL ,则攻击者提供的脚本将在用户的浏览器中执行。

Stored XSS

XSS script is stored in the server database.

Attacker submits malicious code as a comment, which is later rendered to other users.

// 某个评论页,能查看用户评论。
// 攻击者将恶意代码当做评论提交,服务器没对数据进行转义等处理
// 评论输入:
// 则攻击者提供的脚本将在所有访问该评论页的用户浏览器执行

DOM‑based XSS

This vulnerability exists purely on the client side; the payload is taken from the URL and inserted into the DOM without server interaction.

How React Prevents XSS

React’s rendering engine automatically escapes characters such as &, <, >, " and ' before inserting them into the DOM. The following source snippet shows the escape logic.

Automatic Escaping

React escapes the characters "'&<>" during rendering.

for (index = match.index; index < str.length; index++) {
  switch (str.charCodeAt(index)) {
    case 34: // "
      escape = '&quot;';
      break;
    case 38: // &
      escape = '&amp;';
      break;
    case 39: // '
      escape = '&#x27;';
      break;
    case 60: // <
      escape = '&lt;';
      break;
    case 62: // >
      escape = '&gt;';
      break;
    default:
      continue;
  }
}

Example of escaped output:

// 一段恶意代码
// 转义后输出到 html 中
&lt;img src=&quot;empty.png&quot; onerror=&quot;alert(&#x27;xss&#x27;)&quot;&gt;

JSX Compilation

JSX is compiled by Babel into React.createElement() calls that return a ReactElement . The transformation steps are shown below.

// JSX
const element = (
Hello, world!
);
// Babel compiled code
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);
// ReactElement representation
const element = {
  $$typeof: Symbol('react.element'),
  type: 'h1',
  key: null,
  ref: null,
  props: {children: 'Hello, world!', className: 'greeting'}
  ...
};

Attempting to inject a malicious ReactElement via JSON fails because the internal $$typeof Symbol is lost during serialization, causing React to reject the object.

const storedData = `{
  "ref":null,
  "type":"body",
  "props":{
    "dangerouslySetInnerHTML":{
      "__html":"
"
    }
  }
}`;
const parsedData = JSON.parse(storedData);
render() {
  return
{parsedData}
;
}
// Runtime error: Objects are not valid as a React child (found: object with keys {ref, type, props})

Common Vulnerable Patterns in React

Using dangerouslySetInnerHTML

The dangerouslySetInnerHTML prop bypasses React’s escaping and renders raw HTML, which can lead to XSS if the content is not validated.

function getNonChildrenInnerMarkup(props) {
  const innerHTML = props.dangerouslySetInnerHTML; // raw HTML rendering
  if (innerHTML != null) {
    if (innerHTML.__html != null) {
      return innerHTML.__html;
    }
  } else {
    const content = props.children;
    if (typeof content === 'string' || typeof content === 'number') {
      return escapeTextForBrowser(content);
    }
  }
  return null;
}

Passing User‑Provided Objects as Props

Spreading user‑controlled objects directly into component props can introduce XSS when the object contains dangerouslySetInnerHTML or other unsafe values.

// User input
const userProvidePropsString = `{"dangerouslySetInnerHTML":{"__html":"
"}}`;
const userProvideProps = JSON.parse(userProvidePropsString);
render() {
  return
;
}

Rendering User‑Supplied URLs in href or src

Embedding user input directly into href or src attributes without validation allows javascript: or data: schemes to execute arbitrary scripts.

const userWebsite = "javascript:alert('xss');";
Click me

Server‑Side Defences

Strict input filtering to remove dangerous tags and event‑handler keywords.

Context‑aware output escaping (HTML, JavaScript, CSS, URL).

Set the HttpOnly flag on cookies.

Deploy a Content Security Policy (CSP) to restrict script sources.

Conclusion

XSS arises from insufficient input‑output validation. React provides strong default protection, but misuse of APIs like dangerouslySetInnerHTML or careless handling of user data can re‑introduce vulnerabilities. Complementary server‑side checks remain essential.

Mini‑Game

Try the XSS mini‑game (https://xss-game.appspot.com/) to practice exploiting XSS and deepen your understanding.

Call to Action

If you found this article helpful, consider clicking “Watch” to increase its visibility, and follow the official WeChat account “政采云前端团队” for more curated content.

Recruitment

The ZooTeam front‑end group in Hangzhou is hiring. If you are interested in joining a young, passionate team working on front‑end platforms, cloud applications, and data visualization, send your resume to [email protected] .

javascriptReactXSSweb securityfrontend security
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.