Safe alternative to dangerouslySetInnerHTML
The article How to prevent XSS attacks when using dangerouslySetInnerHTML in React suggests to use jam3/no-sanitizer-with-danger eslint rule to check that the content passed to dangerouslySetInnerHTML is wrapped in this sanitizer function
Example of valid code is
const sanitizer = dompurify.sanitize;
return <div dangerouslySetInnerHTML={{__html: sanitizer(title)}} />; // Good
It also describes 3 sanitizer libraries:
DOMPurify
Xss.
xss-filters.
If XSS is your primary concern, you can use DOMPurify
to sanitize your HTML before inserting it in the DOM via dangerouslySetInnerHTML
. It's just 10K minified. And it works in Node too.
As stated in other answers, a lot of libraries (dompurify, xss, etc) can parse the HTML you are giving to the browser, remove any malicious part and display it safely.
The issue is: how do you enforce these libraries are used.
To do so, you can install RisXSS which is an ESLint plugin that will warn the uses of dangerouslySetInnerHTML
if you do not sanitize it before (in a sense, this is an improved version of react/no-danger
ESLint rule).
To do so, install dompurify
and eslint-plugin-risxss
:
npm install dompurify eslint-plugin-risxss
Add risxss
to your ESLint plugins then use DOMPurify:
import { sanitize } from 'dompurify';
export const MyArticle = ({ post }) => (
<>
<div dangerouslySetInnerHTML={{ post.content }} /> {/* You will receive a warning */}
<div dangerouslySetInnerHTML={{ __html: sanitize(post.content) }} /> {/* All good here */}
</>
);
Disclaimer: I am a contributor of RisXSS plugin.
https://facebook.github.io/react/tips/dangerously-set-inner-html.html
"The prop name dangerouslySetInnerHTML is intentionally chosen to be frightening. ..."
"After fully understanding the security ramifications and properly sanitizing the data..."
I figure, if you trust your own CMS/Server (and not receiving from a 3rd party), which has sanitized the data (this step is also done), then you can insert using dangerouslySetInnerHTML
.
As Morhaus said, maybe use DOMPurify as it (bonus) probably handles this unfortunate bit: "so the HTML provided must be well-formed (ie., pass XML validation)." I suspect some content using the non-XML version of HTML5 might otherwise be an issue. (Note: I haven't used it myself yet, since i'm new like you.)