SoFunction
Updated on 2025-04-07

Detailed explanation of how React prevents XSS attack theory of $$typeof

JSX

Let’s briefly review the basics of JSX first. JSX YesSyntax sugar

<div >hello</div>

go throughbabelAfter compilation:

(
  "div" /* type */,
  { id: "container" } /* props */,
  "hello" /* children */
);

The final result is an object.as follows:

{
  type: 'div',
  props: {
    id: 'container',
    children: 'hello',
  },
  key: null,
  ref: null,
  $$typeof: (''),
}

This is a React element object.

We can even write React element objects directly in the code.React can still render our content normally:

render() {
  return (
    <div>
      {{
        $$typeof: (''),
        props: {
          dangerouslySetInnerHTML: {
            __html: '<img src="x" onerror="alert(1)">'
          },
        },
        ref: null,
        type: "div",
      }}
    </div>
  );
}

You can copy this code and run it locally. You can find a pop-up window popup in the browser, andimgAlready inserted into the dom.

here,$$typeofWhat is the function of  ? Why useSymbol()As a value?

Before we understand, let's take a brief look.XSSAttack

XSS Attack

We often need to construct HTML strings and insert them into the DOM, for example:

const messageEl = ("message");
var message = "hello world";
 = "<p>" + message + "</p>";

The page is displayed normally. But if we insert some malicious code,for example:

const messageEl = ("message");
var message = '<img src onerror="alert(1)">';
 = "<p>" + message + "</p>";

At this time, a pop-up window will pop up on the page, and the content of the pop-up window will be displayed as 1

Therefore, directly using innerHTML to insert text content poses a risk of XSS attacks

How to prevent XSS attacks

To solve a similar XSS attack method, we can use some secure APIs to add text content.for example:

  • use('hello world')Insert text node.
  • Or usetextContentInstead ofinnerHTMLSet text content.
  • For some special characters, such as<>, we can escape and convert it to&#60;as well as&#62;
  • For rich text content, we can set a blacklist to filter some attributes, such asonerrorwait.

React processing of text nodes

React UsecreateTextNodeortextContentSet text content.

For the following code:

render() {
  const { count } = 
  return (
    <div onClick={() => ({ count: count + 1})}>
      {count}
    </div>
  );
}

React will be called during renderingsetTextContentThe method isdivThe node settings content, where, when rendering for the first time, it is set directlydivNode'stextContent, the second or second update rendering, because the first time it is settextContent,thereforedivoffirstChildThe value exists and is a text node. This text node is updated directlynodeValueJust

var setTextContent = function (node, text) {
  if (text) {
    var firstChild = ;
    // If the current node node has already set textContent, firstChild is not empty, it is a text node TEXT_NODE    if (
      firstChild &amp;&amp;
      firstChild ===  &amp;&amp;
       === TEXT_NODE
    ) {
       = text;
      return;
    }
  }
  // For the first rendering, directly set textContent   = text;
};

In summary, for ordinary text nodes, since React is added in textContent or createTextNode, there will be no XSS attacks, even if the value of count is'<img src="x" onerror="alert(1)">'There is no risk of being attacked

dangerouslySetInnerHTML handles rich text nodes

Sometimes we do need to display rich text content, React providesdangerouslySetInnerHTMLConvenient for us to explicitly insert rich text content

render() {
  return (
    <div
      
      dangerouslySetInnerHTML={{ __html: '<img src="x" onerror="alert(1)">' }}
    >
    </div>
  );
}

React determines the attribute'skeyYes or nodangerouslySetInnerHTML, if so, callsetInnerHTMLThe method is directly given to the dominnerHTMLProperties Set Text Content

function setInitialDOMProperties(
  tag,
  domElement,
  rootContainerElement,
  nextProps
) {
  for (var propKey in nextProps) {
    if (propKey === "dangerouslySetInnerHTML") {
      var nextHtml = nextProp ? nextProp.__html : undefined;
      if (nextHtml != null) {
        setInnerHTML(domElement, nextHtml);
      }
    }
  }
}
var setInnerHTML = function (node, html) {
   = html;
};

It can be seen that when React processes rich text, it is just a simple setting of DOM.innerHTMLattributes are implemented.

The potential security risks of rich texts are left to the developer to control them.

The role of $$typeof

render() {
  const { text } = 
  return (
    <div>
      {text}
    </div>
  );
}

Assume thistextIt is returned from the backend, and the backend allows the user to store JSON objects.If the user passes in the following object similar to React element:

{
  type: "div",
  props: {
    dangerouslySetInnerHTML: {
      __html: '<img src="x" onerror="alert(1)">'
    },
  },
  ref: null
}

Don't forget as mentioned earlier, we can render normally by inserting React element objects directly in JSX.

In this case,React0.13When it comes to version, this is a potentialXSSattack,This vulnerability originated from the server. If the attacker maliciously forges data similar to a React element object and returns it to the front end, React will execute malicious code. But React can take steps to prevent such attacks.

fromReact0.14Starting with the release, React adds one for each elementSymbolLogo:

{
  $$typeof: (''),
  props: {
    id: 'container'
  },
  ref: null,
  type: "div",
}

This works because JSON does not support itSymbol. Therefore, even if the server has a risky vulnerability and returns a JSON, this JSON will not include('')., During the Reconcile stage, React will checkelement.$$typeofWhether the sign is legal. If it is illegal, it will directly report an error. React cannot accept the object as children

The advantage of using () specifically is that Symbols is global between environments such as iframe and worker. Therefore, even under more peculiar conditions, Symbols can pass trusted elements between different applications. Likewise, even if there are multiple React copies on the page, they can still "consent" to valid $$typeof values

If the browser does not support itSymbols, React uses0xeac7replace

{
  $$typeof: '0xeac7',
}

This is the end of this article about how React prevents XSS attacks from being attacked. For more related React $$typeof, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!