typescript.react.security.react-markdown-insecure-html.react-markdown-insecure-html
Verifed by r2c
Community Favorite
semgrep
Author
64,103
Download Count*
License
Overwriting transformLinkUri
or transformImageUri
to something insecure, or turning allowDangerousHtml
on, or turning escapeHtml
off, will open the code up to XSS vectors.
Run Locally
Run in CI
Defintion
rules:
- id: react-markdown-insecure-html
message: Overwriting `transformLinkUri` or `transformImageUri` to something
insecure, or turning `allowDangerousHtml` on, or turning `escapeHtml` off,
will open the code up to XSS vectors.
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://www.npmjs.com/package/react-markdown#security
category: security
technology:
- react
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- typescript
- javascript
severity: WARNING
patterns:
- pattern-either:
- pattern-inside: |
$X = require('react-markdown/with-html');
...
- pattern-inside: |
$X = require('react-markdown');
...
- pattern-inside: |
import 'react-markdown/with-html';
...
- pattern-inside: |
import 'react-markdown';
...
- pattern-either:
- pattern: |
<$EL allowDangerousHtml />
- pattern: |
<$EL escapeHtml={false} />
- pattern: |
<$EL transformLinkUri=... />
- pattern: |
<$EL transformImageUri=... />
Examples
react-markdown-insecure-html.jsx
import ReactMarkdown from "react-markdown";
import htmlParser from "react-markdown/plugins/html-parser";
// For more info on the processing instructions, see
// <https://github.com/aknuds1/html-to-react#with-custom-processing-instructions>
const parseHtml = htmlParser({
isValidNode: (node) => node.type !== 'script',
processingInstructions: [
/* ... */
]
})
function bad1() {
// ruleid: react-markdown-insecure-html
return <ReactMarkdown astPlugins={[parseHtml]} allowDangerousHtml children={markdown} />;
}
function bad2() {
// ruleid: react-markdown-insecure-html
return <ReactMarkdown astPlugins={[parseHtml]} escapeHtml={false} children={markdown} />;
}
function ok1() {
// ok: react-markdown-insecure-html
return <ReactMarkdown renderers={renderers} children={markdown} />;
}
function ok2() {
// ok: react-markdown-insecure-html
return <ReactMarkdown renderers={renderers} escapeHtml={true} children={markdown} />;
}
react-markdown-insecure-html.tsx
import ReactMarkdown from "react-markdown";
import htmlParser from "react-markdown/plugins/html-parser";
// For more info on the processing instructions, see
// <https://github.com/aknuds1/html-to-react#with-custom-processing-instructions>
const parseHtml = htmlParser({
isValidNode: (node) => node.type !== 'script',
processingInstructions: [
/* ... */
]
})
function bad1() {
// ruleid: react-markdown-insecure-html
return <ReactMarkdown astPlugins={[parseHtml]} allowDangerousHtml children={markdown} />;
}
function bad2() {
// ruleid: react-markdown-insecure-html
return <ReactMarkdown astPlugins={[parseHtml]} escapeHtml={false} children={markdown} />;
}
function ok1() {
// ok: react-markdown-insecure-html
return <ReactMarkdown renderers={renderers} children={markdown} />;
}
function ok2() {
// ok: react-markdown-insecure-html
return <ReactMarkdown renderers={renderers} escapeHtml={true} children={markdown} />;
}
Short Link: https://sg.run/9qAk