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.)

Tags:

Reactjs