OPEN-WEBUI · CVE-2026-109291 · AI agents & MCP
FIX → 0.11.4
Open WebUI's citation click handler opens a stored embed_url without checking its scheme, so a javascript: URL runs script in the app's origin. A user who opens a shared chat and clicks the malicious citation has their session token readable by the attacker, allowing account takeover.
first public Sep 27, 2026 · 2 sources
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Any Open WebUI deployment from 0.6.33 through 0.11.3 with default settings is exposed, because any authenticated user can share a chat containing the malicious citation with another user. Exposure requires a victim to open the shared chat and click the citation. Instances on 0.11.4 or later are not affected.
Not affected if no-shared-chats, version-0.11.4-or-later
Who cares open-webui, python, self-hosted
pip show open-webui and confirm it is below 0.11.4.>= 0.6.33 and < 0.11.4.Upgrade to 0.11.4
Any authenticated user can store a javascript: URL in the embed_url field of a chat citation and share that chat with another user. When the second user opens the shared chat and clicks the citation, the URL is passed straight to window.open, executing attacker script in the Open WebUI origin. The frontend never checks the URL scheme before opening it, so the attacker's script runs with the victim's session and can read localStorage.token and act as the victim.
Default configuration, fresh database, no special settings. The attacker is any authenticated user who can create and share a chat (no admin rights, no workspace.* permission). The victim is any user who opens the shared read-only chat (/s/{share_id}), expands the sources, and clicks the malicious citation. The embed_url value is set by editing the attacker's own chat through the normal chat update API, which stores the attacker-controlled citation structure.
Script executes in the application origin as the victim, so the attacker can exfiltrate localStorage.token (the JWT used for every API call) and then act with the victim's permissions, including reading the victim's private chats. Exploitation requires the victim to click the citation in the shared chat. If the victim is an administrator, the account compromise extends to admin capabilities. Only the citation-embed click path is affected; citations whose is a normal http/https link are unaffected.
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
open-webui to 0.11.4 (fixed by PR #29701). The sources state no further configuration is needed.embed_urlFixed in 0.11.4 by PR #29701. The citation click handler now requires the embed_url to be an http/https URL (or protocol-relative) before it is opened or handed to the embed panel; any other value, including a javascript: URL, falls back to the citation modal, which renders the source safely. Upgrading to 0.11.4 fully resolves the issue with no further configuration.
src/lib/components/chat/Messages/Citations.svelte (showSourceModal) read citations[index].source.embed_url and, when the chat is read-only, called window.open(embedUrl, '_blank') directly. The value comes from the stored chat, which a user fully controls through the chat update API, and no URL-scheme validation stood between the stored value and the sink. The read-only window.open branch shipped from 0.6.33 onward, so every build from 0.6.33 through 0.11.3 carried the code.
The reporter reproduced with two normal accounts on a default 0.11.3 instance: the attacker stored a citation with embed_url set to a javascript: payload that fetched localStorage.token to a listener, shared the chat with the victim, and on the victim clicking the citation the token was exfiltrated and then used to read a private victim chat that the attacker account could not access directly. Independently confirmed in Chromium that window.open with a javascript: URL and a _blank target runs in the opening page's origin and can read and send its localStorage.token. On 0.11.4 the guard rejects javascript: and data: values and admits only http, https and protocol-relative URLs to that path.
Reported by @zyakir13. Fix by @Classic298.
This page as .md · .json · CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.