Security: Unsafe HTML/Markdown Rendering via Streamdown Component#2966
Security: Unsafe HTML/Markdown Rendering via Streamdown Component#2966tomaioo wants to merge 1 commit into
Conversation
The `Markdown` component in `chat-ui/src/internal/markdown.tsx` renders untrusted model text using `Streamdown` without any explicit sanitization or HTML escaping. While the comment mentions 'safe Streamdown render', there is no evidence of DOMPurify or similar sanitization being applied. If `Streamdown` renders raw HTML, this creates a Cross-Site Scripting (XSS) vulnerability when displaying AI-generated content that may contain malicious HTML/JavaScript payloads. Signed-off-by: tomaioo <203048277+tomaioo@users.noreply.github.com>
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
WalkthroughIn Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@chat-ui/src/internal/markdown.tsx`:
- Line 20: The Markdown renderer configuration is using the wrong Streamdown
prop, so HTML is still not being disabled as intended. Update the Streamdown
usage in markdown.tsx to use skipHtml instead of rawHtml={false}, and keep the
component wired around the existing content rendering so the HTML-skipping
behavior takes effect correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: df457663-56f1-459a-b90b-23f6a5d55d17
📒 Files selected for processing (1)
chat-ui/src/internal/markdown.tsx
| return ( | ||
| <div className={cn("mcpjam-chat-markdown [overflow-wrap:anywhere]", className)}> | ||
| <Streamdown>{content}</Streamdown> | ||
| <Streamdown rawHtml={false}>{content}</Streamdown> |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
For streamdown version 2.1.0, what prop disables raw HTML rendering on the React component: skipHtmlorrawHtml?
💡 Result:
For Streamdown version 2.1.0, the prop that disables raw HTML rendering is skipHtml [1][2][3]. When the skipHtml prop is set to true, Streamdown completely ignores raw HTML in the Markdown source rather than escaping it or rendering it [2][4][3]. This behavior aligns with the react-markdown API, as Streamdown is designed to be a drop-in replacement [5][1][3]. Additionally, you can completely remove raw HTML support by omitting the default rehype-raw plugin from the rehypePlugins configuration [2][4].
Citations:
- 1: https://github.com/vercel/streamdown/blob/main/skills/streamdown/references/api.md
- 2: https://streamdown.ai/docs/security
- 3: https://streamdown.ai/docs/configuration
- 4: https://github.com/vercel/streamdown/blob/HEAD/skills/streamdown/references/security.md
- 5: https://vercel-streamdown.mintlify.app/customization/configuration
Use skipHtml here. rawHtml isn’t the Streamdown prop for disabling HTML; skipHtml is. Keeping rawHtml={false} leaves HTML rendering enabled.
Suggested change
- <Streamdown rawHtml={false}>{content}</Streamdown>
+ <Streamdown skipHtml>{content}</Streamdown>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Streamdown rawHtml={false}>{content}</Streamdown> | |
| <Streamdown skipHtml>{content}</Streamdown> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@chat-ui/src/internal/markdown.tsx` at line 20, The Markdown renderer
configuration is using the wrong Streamdown prop, so HTML is still not being
disabled as intended. Update the Streamdown usage in markdown.tsx to use
skipHtml instead of rawHtml={false}, and keep the component wired around the
existing content rendering so the HTML-skipping behavior takes effect correctly.
|
hi @tomaioo, Streamdown already sanitizes HTML by default (rehype-sanitize + rehype-harden), so there's no XSS hole. would like to know if this was considered in your investigation |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
10 similar comments
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
|
Hi @chelojimenez, thanks for clarifying. I wasn't aware that |
Summary
Security: Unsafe HTML/Markdown Rendering via Streamdown Component
Problem
Severity:
High| File:chat-ui/src/internal/markdown.tsx:L1The
Markdowncomponent inchat-ui/src/internal/markdown.tsxrenders untrusted model text usingStreamdownwithout any explicit sanitization or HTML escaping. While the comment mentions 'safe Streamdown render', there is no evidence of DOMPurify or similar sanitization being applied. IfStreamdownrenders raw HTML, this creates a Cross-Site Scripting (XSS) vulnerability when displaying AI-generated content that may contain malicious HTML/JavaScript payloads.Solution
Verify that
Streamdownperforms HTML sanitization by default. If not, integrate a sanitization library like DOMPurify or use a markdown parser that sanitizes HTML by default (e.g.,markedwithsanitize-html). Consider rendering markdown to a safe AST first before converting to HTML.Changes
chat-ui/src/internal/markdown.tsx(modified)Summary by cubic
Prevent XSS by disabling raw HTML rendering in the
Markdowncomponent viaStreamdown. Untrusted content is now rendered without interpreting HTML.<Streamdown rawHtml={false}>inchat-ui/src/internal/markdown.tsxto block raw HTML from being rendered.Written for commit 96a3313. Summary will update on new commits.