React dangerouslySetInnerHTML should not be used
ID |
javascript.react_dangerously_set_innerhtml |
Severity |
high |
Resource |
Risky Values |
Language |
JavaScript |
Tags |
CWE:79, OWASP:2021:A3, PCI-DSS:6.5.4, React |
Description
Taken from React DOM Elements - dangerouslySetInnerHTML:
dangerouslySetInnerHTML
is React’s replacement for using innerHTML
in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack.
Rationale
According to Dangerously Set innerHTML:
Improper use of the innerHTML can open you up to a cross-site scripting (XSS) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the leading causes of web vulnerabilities on the internet. Our design philosophy is that it should be "easy" to make things safe, and developers should explicitly state their intent when performing “unsafe” operations. The prop name `dangerouslySetInnerHTML` is intentionally chosen to be frightening, and the prop value (an object instead of a string) can be used to indicate sanitized data. After fully understanding the security ramifications and properly sanitizing the data, create a new object containing only the key __html and your sanitized data as the value.
function MyComponent() {
const title = response.from.backend.title;
// FLAW: vulnerable to potential XSS attack
return <div dangerouslySetInnerHTML={{__html: title}} />;
}
This detector simply reports any usage of the dangerouslySetInnerHTML
property that it is not sanitized using a sanitizer()
abstraction. Note that other detectors, such as the Cross-Site Scripting
detector for JavaScript
also checks if the value passed to dangerouslySetInnerHTML
could be injected from untrusted input.
Remediation
To fix this issue, remove the dangerouslySetInnerHTML
property from the component if possible. If you cannot remove it, make sure that the value passed to dangerouslySetInnerHTML
is sanitized, using a sanitizer()
function to abstract your chosen sanitizer.
import dompurify from 'dompurify';
function MyComponent() {
const title = response.from.backend.title;
const sanitizer = dompurify.sanitize;
// FLAW: vulnerable to potential XSS attack
return <div dangerouslySetInnerHTML={{__html: sanitizer(title)}} />;
}
Some recommended anti-XSS sanitizers can be chosen among the following libraries:
-
DOMPurify - XSS sanitizer for HTML, MathML and SVG.
-
xss - Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist.
-
xss-filters - Secure XSS Filters.
Configuration
You may configure the accepted sanitizer functions changing the sanitizers
property, a list of regular expressions for the names that will be accepted as sanitizer functions.
References
-
CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
-
Dangerously Set innerHTML, in React Tips.
-
How to prevent XSS attacks when using dangerouslySetInnerHTML in React.