Description
Allowing raw HTML in untrusted Markdown rendered by react-markdown can expose a React application to cross-site scripting (XSS). Current versions escape or skip HTML by default. Enabling HTML parsing with rehype-raw without a sanitization step such as rehype-sanitize can allow malicious tags or attributes into the output. Older options such as allowDangerousHtml or escapeHtml={false} can create the same risk.
Potential impact
- An attacker may obtain cookies, session information, or other sensitive data available to the page.
- Malicious code may run in the user's browser and support further attacks.
- Malicious content may undermine users' trust in the site.
Remediation
- Keep the default rendering for untrusted Markdown and avoid
rehype-raw. - If raw HTML is necessary, apply
rehype-sanitizeafterrehype-rawand keep the schema of permitted tags and attributes minimal. - Validate and sanitize user-supplied Markdown and other rendered data.
- If overriding URL transformation options, block dangerous schemes such as
javascript:anddata:.
Examples
Before
tsx
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
function UnsafeComponent({ markdown }) {
// Unsafe: parse raw HTML from untrusted Markdown
return <ReactMarkdown rehypePlugins={[rehypeRaw]}>{markdown}</ReactMarkdown>;
}
After
tsx
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
function SafeComponent({ markdown }) {
// Safer default: do not parse raw HTML
return <ReactMarkdown>{markdown}</ReactMarkdown>;
}
function SafeHtmlComponent({ trustedButNeedsHtml }) {
// Sanitize HTML when it must be allowed
return (
<ReactMarkdown rehypePlugins={[rehypeRaw, rehypeSanitize]}>
{trustedButNeedsHtml}
</ReactMarkdown>
);
}
Explanation:
- Before: Using
rehype-rawalone turns raw Markdown HTML into React elements. Unsanitized HTML may enter the DOM with executable behavior. - After: Default rendering does not execute raw HTML. When HTML rendering is needed,
rehype-sanitizeretains only permitted tags and attributes to reduce XSS risk.