All vulnerabilities
GHSA-9wj4-mcm3-ppj6

open-webui: Stored XSS via user-authored tool-call embeds in the Markdown renderer

open-webui
CVSS
4.6Medium
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in0.11.4Fixed versionGitHub
Published27 Sep 2026Updated 27 Sep 2026GitHub

What fixes it

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Stored XSS via user-authored tool-call embeds in the Markdown renderer

Summary

Any authenticated user can execute arbitrary JavaScript in other users' browsers by sending content shaped as a tool-call <details> block. The Markdown renderer parsed the block's embeds attribute without distinguishing server-generated tool-call output from user-authored input, decoded and JSON-parsed it, and mounted each element in a sandboxed iframe with scripts enabled, so it ran at render time for every viewer. The missing control is a trust gate separating user content from the tool-call embed path.

Preconditions

An authenticated account on the instance. The primary demonstrated surface is channel messages, which requires the Channels feature enabled by an admin (ENABLE_CHANNELS, off by default); the same gadget also reaches main-chat user messages and citation previews of retrieved documents, which need no special feature flag. No elevated role is required. By default the embed iframe is sandboxed allow-scripts without allow-same-origin, so the injected script runs in an opaque origin.

Impact

The injected script executes in a null-origin sandboxed iframe for anyone who views the message or opens the citation. In the default configuration it cannot read the viewer's session token or make same-origin authenticated requests; the confirmed default primitive is contained script execution and convincing in-app phishing content rendered inside the interface. Where an operator has turned on iframeSandboxAllowSameOrigin, the sandbox gains allow-same-origin and the script can read localStorage (session token) and act as the victim, raising the impact to session hijacking. The payload is stored, so it re-executes on every view.

Fix

Fixed in 0.11.4 by PR #29985. Embed rendering is now opt-in: the flag defaults off and is forwarded through every Markdown render path, including the standalone tool-call branch, colon fences and alerts. Assistant responses opt in only for the viewer's own chat; channel messages and read-only/shared views pass it explicitly off, so user-authored content can no longer reach the embed iframe. Upgrading to 0.11.4 fully resolves the issue with no additional configuration.

Root cause

The tool-call embed sink lives in the shared Markdown renderer: ToolCallDisplay.svelte and ConsecutiveDetailsGroup.svelte read the embeds attribute off a <details type="tool_calls"> token and mount each element in FullHeightIframe with allowScripts={true}. The renderer never distinguished tokens produced by the tool-execution pipeline from tokens parsed out of arbitrary user-authored message content, and the later allowEmbeds guard was applied only to the grouped path, so a single standalone details block bypassed it entirely and reached the iframe on every surface that renders user content.

Proof of concept

Reproduced on stock 0.11.3 with default settings and Channels enabled. A non-admin account posted a channel message whose content was <details type="tool_calls" embeds="[&quot;&lt;script&gt;...&lt;/script&gt;&quot;]">...</details>. Opening the channel rendered one iframe with sandbox="allow-scripts allow-popups allow-downloads" and the attacker HTML in srcdoc, and the injected script executed in the viewer's browser (null origin). The same message on 0.11.4 renders no iframe and no script runs.

Credits

@KadirArslan: channel messages, original report and proof of concept. @5yu4n: cross-user delivery through channel direct messages. @ComputerOnFire: citation previews of knowledge-base documents, and the ungated standalone-block path.

Text from GitHub Advisory Database

Affected versions 1

  • open-webui, pip>= 0.6.31, < 0.11.4GitHub