typescript.react.security.audit.react-unsanitized-method.react-unsanitized-method

Author
7,258
Download Count*
License
Detection of $HTML from non-constant definition. This can inadvertently expose users to cross-site scripting (XSS) attacks if this comes from user-provided input. If you have to use $HTML, consider using a sanitization library such as DOMPurify to sanitize your HTML.
Run Locally
Run in CI
Defintion
rules:
- id: react-unsanitized-method
message: Detection of $HTML from non-constant definition. This can inadvertently
expose users to cross-site scripting (XSS) attacks if this comes from
user-provided input. If you have to use $HTML, consider using a
sanitization library such as DOMPurify to sanitize your HTML.
metadata:
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation
('Cross-site Scripting')"
owasp:
- A07:2017 - Cross-Site Scripting (XSS)
- A03:2021 - Injection
references:
- https://developer.mozilla.org/en-US/docs/Web/API/Document/writeln
- https://developer.mozilla.org/en-US/docs/Web/API/Document/write
- https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
category: security
confidence: MEDIUM
technology:
- react
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- typescript
- javascript
severity: WARNING
mode: taint
pattern-sources:
- patterns:
- pattern-either:
- pattern-inside: |
function ...({..., $X, ...}) { ... }
- pattern-inside: |
function ...(..., $X, ...) { ... }
- focus-metavariable: $X
- pattern-either:
- pattern: $X.$Y
- pattern: $X[...]
pattern-sinks:
- patterns:
- pattern-either:
- pattern: |
this.window.document. ... .$HTML('...',$SINK)
- pattern: |
window.document. ... .$HTML('...',$SINK)
- pattern: |
document.$HTML($SINK)
- metavariable-regex:
metavariable: $HTML
regex: (writeln|write)
- focus-metavariable: $SINK
- patterns:
- pattern-either:
- pattern: |
$PROP. ... .$HTML('...',$SINK)
- metavariable-regex:
metavariable: $HTML
regex: (insertAdjacentHTML)
- focus-metavariable: $SINK
pattern-sanitizers:
- patterns:
- pattern-either:
- pattern-inside: |
import $S from "underscore.string"
...
- pattern-inside: |
import * as $S from "underscore.string"
...
- pattern-inside: |
import $S from "underscore.string"
...
- pattern-inside: |
$S = require("underscore.string")
...
- pattern-either:
- pattern: $S.escapeHTML(...)
- patterns:
- pattern-either:
- pattern-inside: |
import $S from "dompurify"
...
- pattern-inside: |
import { ..., $S,... } from "dompurify"
...
- pattern-inside: |
import * as $S from "dompurify"
...
- pattern-inside: |
$S = require("dompurify")
...
- pattern-inside: |
import $S from "isomorphic-dompurify"
...
- pattern-inside: |
import * as $S from "isomorphic-dompurify"
...
- pattern-inside: |
$S = require("isomorphic-dompurify")
...
- pattern-either:
- patterns:
- pattern-inside: |
$VALUE = $S(...)
...
- pattern: $VALUE.sanitize(...)
- patterns:
- pattern-inside: |
$VALUE = $S.sanitize
...
- pattern: $S(...)
- pattern: $S.sanitize(...)
- pattern: $S(...)
- patterns:
- pattern-either:
- pattern-inside: |
import $S from 'xss';
...
- pattern-inside: |
import * as $S from 'xss';
...
- pattern-inside: |
$S = require("xss")
...
- pattern: $S(...)
- patterns:
- pattern-either:
- pattern-inside: |
import $S from 'sanitize-html';
...
- pattern-inside: |
import * as $S from "sanitize-html";
...
- pattern-inside: |
$S = require("sanitize-html")
...
- pattern: $S(...)
- patterns:
- pattern-either:
- pattern-inside: |
$S = new Remarkable()
...
- pattern: $S.render(...)
Examples
react-unsanitized-method.jsx
function Test1({input}) {
// ruleid: react-unsanitized-method
this.ref.insertAdjacentHTML('afterend', input.foo);
}
function Test2({input}) {
// ruleid: react-unsanitized-method
document.write(input.foo);
}
function Test3 () {
// ok: react-unsanitized-method
document.writeln(input);
}
function OkTest1 () {
// ok: react-unsanitized-method
this.ref.insertAdjacentHTML('afterend', '<div id="two">two</div>');
}
function OkTest2 () {
// ok: react-unsanitized-method
document.write("<h1>foobar</h1>");
}
function OkTest3 () {
// ok: react-unsanitized-method
document.writeln("<p>foobar</p>");
}
react-unsanitized-method.tsx
function Test1({input}) {
// ruleid: react-unsanitized-method
this.ref.insertAdjacentHTML('afterend', input.foo);
}
function Test2({input}) {
// ruleid: react-unsanitized-method
document.write(input.foo);
}
function Test3 () {
// ok: react-unsanitized-method
document.writeln(input);
}
function OkTest1 () {
// ok: react-unsanitized-method
this.ref.insertAdjacentHTML('afterend', '<div id="two">two</div>');
}
function OkTest2 () {
// ok: react-unsanitized-method
document.write("<h1>foobar</h1>");
}
function OkTest3 () {
// ok: react-unsanitized-method
document.writeln("<p>foobar</p>");
}
Short Link: https://sg.run/E5x8