facebook / react

The library for web and native user interfaces.

Home Page:https://react.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: Incorrect escaping inside `style` tags

GrantGryczan opened this issue · comments

In general, only backslashes escape things in CSS, while HTML entities are only treated by CSS as plain text.

Despite this, ReactDOMServer.renderToString escapes HTML special characters (e.g. &, <, >, ", ') into HTML entities (e.g. &amp;, &lt, etc.) that are inside a style element, even if it makes the stylesheet invalid or transforms it to be different from what is intended in many cases. For example, when writing a CSS "string", it is transformed into &quot;string&quot;, which is invalid CSS.

Additionally, client-side, ReactDOM.render does not escape HTML special characters within style elements at all, even though it should be escaping < and > into \< and \> respectively (as it should on the server as well). Not doing this causes an inconsistency between client and server rendering in isomorphic apps. For me, this logs a warning in dev mode that looks like this:

image

React version: 17.0.2

Steps To Reproduce

  1. Write any HTML special characters into a React style element anywhere in your app.
  2. Call ReactDOMServer.renderToString on your app.

Link to code example: https://jsfiddle.net/3qnsxept/

The current behavior

HTML special characters are escaped unnecessarily and/or incorrectly inside style elements outputted by ReactDOMServer.renderToString, often invalidating the stylesheet and/or making it inconsistent with what's rendered client-side.

For example, the JSX <style>{'body::before { content: "\</style>"; }'}</style> currently outputs the HTML <style>body::before { content: &quot;\&lt;/style&gt;&quot;; }</style> server-side, which is invalid, and it outputs the HTML <style>{'body::before { content: "\</style>"; }'}</style> client-side, which is inconsistent.

The expected behavior

There should be no HTML escaping within style elements outputted by ReactDOMServer.renderToString, just like ReactDOM.render. The only exception is that < and > within style elements should escape to \< and \> (if they are not already escaped) to avoid XSS, which is a change that should be implemented for both client-side and server-side rendering in order to support isomorphism.

For example, the JSX <style>{'body::before { content: "\</style>"; }'}</style> should output the HTML <style>body::before { content: "\</style\>"; }</style> both client-side and server-side.

commented

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!