Is React protected against malicious user inputs?
React claims that it prevents XSS injection attacks by default. But what does it really mean?
March 28, 2023
In the React docs, there's this page which has been the source of much confusion over the last few years. Here, React claims that JSX is by default protected against XSS attacks. What does this mean?
What you should understand: React prevents most XSS attacks by default (if used in the standard way). There are still some attack vectors open, but they need you to do something special.
- If you use an escape hatch like
dangerouslySetInnerHtml
, and you try to set user input to this, then you are asking for trouble. If you really need to do this (for eg, you want to show the preview of user provided HTML template), use a library like dom-purify to escape stuff. Note: even dom-purify is not foolproof, so if you really need to do this, I suggest digging into the issues (they have provided a way to escape properly too`). - If you allow user inputs to define arbitary props keys (by spreading user inputs on a component for eg), then they can easily inject a prop like
dangerouslySetInnerHtml
, and you are open to attacks. - Another case when it might be an issue is when doing server side rendering. You often need to to do a
JSON.stringify
when doing SSR, and that is open to attacks (because it's outside React). In that case, use a library like serialize-javascript on the server, instead of doingJSON.stringify
. - Another issue could occour when you are passing user input directly to an anchor element's
href
prop, so a user can potentially use something likejavascript:alert('123')
as a href, which will lead to script execution. If you need to do this, make sure you escape stufff, by doing.replace(/^(javascript\:)/, "");
for eg, (and also check for encoding etc). You would rarely need to do something like this, but if you, it's best to look up more resources here. - This goes without saying, but just leaving it here – don't touch the DOM directly in React, unless you know what you are doing. If you do that, all React XSS gurantees are out the window.
An interesting point to note: Angular does escape all URLs by default, which ensures that dynamically-created URLs are safe to use in the application. React does not do this, so if you are passing user input directly to href, you need to do this yourself.
One solution for the href issue is to use a <SafeLink>
component as mentioned in the tweet here:
Further reading:
- About the attack vectors: reactjs - What does it mean when they say React is XSS protected? - Stack Overflow
- About DOM Purify: Preventing XSS in React Applications - DEV Community
- More reading on how to prevent some XSS attack vectors in React when you are doing special stuff (three part series): Preventing XSS in React (Part 1): Data binding and URLs (pragmaticwebsecurity.com)
- Here's a cheatsheet/checklist for React XSS: https://pragmaticwebsecurity.com/files/cheatsheets/reactxss.pdf