AI Output XSS Lab: When the Chatbot's Reply Is Trusted HTML

✨ AI Summary
ChatBotApp wanted ChatGPT-style rich formatting, so it renders the model's reply with innerHTML. But an LLM reply is just text an attacker can influence — and dropping untrusted text into innerHTML is how stored XSS has worked for twenty years.
Lab at a glance: Advanced · 140 XP · about 20 minutes · runs in your browser, no signup or setup. Try it yourself first; the full solution is behind a spoiler below.

What this lab teaches

Improper output handling treats model output as safe. When an app renders an LLM's reply as HTML without sanitising, any markup the model can be induced to produce — an element with an event handler, say — executes in the victim's browser. It is XSS, with the model as the delivery channel.

The lesson: model output is untrusted. Rendering it as HTML is exactly as dangerous as rendering any user-supplied string that way.

How ChatBotApp renders replies

Your message goes to the LLM; its reply is inserted into the chat panel with innerHTML for 'rich formatting', unsanitised. If you can steer the reply to contain an HTML element that runs script, that script runs on the page.

The attack approach

  • Confirm the reply is rendered as HTML, not escaped text.
  • Get the model to include an HTML element that fires JavaScript on load in its reply.
  • Keep it simple — an element with a load-time handler is enough.
  • Aim for the handler to call the lab's XSS callback.

Full walkthrough (spoiler)

If the markup is escaped rather than rendered, try a different element — open the steps.

Show the step-by-step solution
  1. Prompt the bot so its reply contains an HTML element carrying a load-time event handler (an image with a broken source and an error handler is the classic).
  2. Have that handler call the page's window.onLabXSSFired() function.
  3. The reply is inserted via innerHTML, the handler runs, and the script fires.
  4. The lab detects the XSS and marks you solved.

Why it works

The app assumes the model's reply is safe content. But you influence that reply, and the renderer parses it as HTML. An element with an event handler is live DOM, so it executes — the model simply carried your payload into a sink that never should have received raw HTML.

Core principleModel output is untrusted. Sanitise it before any HTML rendering, or render it as plain text.

Where this happens in the real world

Treating LLM output as trusted HTML is the LLM-era form of stored XSS and is exactly what OWASP LLM05 Improper Output Handling warns about. As products rush to render rich model output, this has become a common, high-impact finding.

How to defend against it

  • Sanitise model output with a trusted library (such as DOMPurify) before any innerHTML rendering.
  • Prefer rendering as plain text or Markdown with HTML disabled.
  • Set a strict Content-Security-Policy as a backstop against injected script.
  • Never pass model output to dangerous sinks (innerHTML, document.write, eval) unfiltered.
Mr Elite tip: Any product that renders model output as HTML for 'rich formatting' should be assumed XSS-prone until you confirm it sanitises. The model is just another untrusted source feeding the sink.

Try it, then go further

Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.

❓ Frequently asked questions

What is LLM-output XSS?
Cross-site scripting where an app renders a language model's reply as HTML without sanitising, so attacker-influenced markup in the reply executes in the browser.
Why is model output untrusted?
Users influence what the model says. If the output is rendered as HTML, the model becomes a channel for delivering an XSS payload.
How is it related to classic XSS?
It is the same bug — untrusted content in an HTML sink — with the model as the source. OWASP calls it Improper Output Handling (LLM05).
How do I prevent it?
Sanitise model output before HTML rendering (DOMPurify), prefer plain text or HTML-disabled Markdown, and add a Content-Security-Policy.
⚡
Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *