CVE-2026-59214: Open WebUI: Stored web worker XSS via Pyodide
Open WebUI runs Pyodide Python in a same-origin web worker, so code in a shared chat can make authenticated requests as the viewer. If a victim with admin or workspace function and tool rights clicks Run, the code can create a Function that executes on the server. Versions before 0.10.0 are affected. Upgrade to 0.10.0.
Published Jul 24, 2026 · Analysis Oct 25, 2026
What an attacker can do
Pyodide's js bridge and pyodide.http.pyfetch give Python in the worker the same reach as JavaScript on the page's origin. Because the worker is same-origin, a credentialed fetch to the app's own API carries the victim's session cookie. No separate XSS sink is needed.
The attack: a low-privileged user stores a payload in a chat message and shares the chat. A victim opens it and clicks Run. The code, using pyfetch with credentials include, posts to /api/v1/functions/create with a body that calls os.system. When the victim is an admin, or holds workspace.functions or workspace.tools permission, that Function or Tool runs server-side Python, which is remote code execution on the Open WebUI host.
For other victims, the code can still send any authenticated request as them. The attack needs the victim to click Run and needs Open WebUI configured to use Pyodide. Scoring reflects a low-privilege attacker plus user interaction, with high confidentiality and integrity impact.
Who is affected
open-webui (pip) before 0.10.0, on instances where Pyodide is the code execution engine. Instances that use a server-side code execution or interpreter engine are not exposed to this path. Check:
pip show open-webuiFor Docker, read the version from the image tag or from the About page in Settings.
open-webui
- Ecosystem
- PyPI
- Affected
- < 0.10.0
- Fixed in
- 0.10.0
- Check
pip show open-webui
How to fix it
Upgrade to open-webui 0.10.0:
pip install --upgrade open-webui==0.10.0Pyodide now runs by default in a sandboxed iframe at an opaque origin (sandbox="allow-scripts", no allow-same-origin). Requests from it to the app become cross-origin, carry no session cookie and are blocked by CORS, and the js bridge cannot reach the parent page's cookie, token, localStorage or DOM. The release notes also mark Pyodide as legacy.
Do not set ENABLE_PYODIDE_FILE_PERSISTENCE=true unless you accept the risk: it restores the same-origin worker. Before upgrading, disable Pyodide code execution or switch the Code Execution / Code Interpreter engine to a server-side option.
How to tell if you were hit
Review Functions and Tools in the admin workspace for entries you did not create, especially ones with ids like x, short generic names, or bodies calling os.system, subprocess or network tools. Check audit or access logs for POST /api/v1/functions/create or tools create calls made from an admin session shortly after that user opened a shared chat. Look in shared chats for Python blocks that import pyodide.http or js. Confirm whether Pyodide is your execution engine.
Original advisory
From the GitHub Advisory Database (CC BY 4.0).
Title: Same-origin Pyodide code execution allows server-side RCE via a shared chat
Summary
Open WebUI runs client-side Python (Pyodide) in a same-origin web worker. Through Pyodide's JavaScript API (pyodide.http.pyfetch, or the js module which exposes the page's fetch / XMLHttpRequest) executed Python can issue requests on the application origin, and those requests carry the victim's session cookie. A low-privileged user can store such a payload in a chat message, share the chat, and when a victim opens it and clicks Run the payload executes authenticated same-origin requests as the victim. When the victim is an admin (or a user holding workspace.functions / workspace.tools permissions) the payload creates a Function/Tool whose body runs server-side, yielding remote code execution.
Details
Pyodide's js bridge gives Python in the worker the same reach as inline JavaScript on the origin, and the worker is same-origin, so a credentialed request to the app's own API is authenticated as the victim. No separate XSS sink is required: storing the payload in a shared chat and having the victim run it is enough.
from pyodide.http import pyfetch
import json
await pyfetch('/api/v1/functions/create', method='POST', credentials='include',
headers={'Content-Type': 'application/json'},
body=json.dumps({'id': 'x', 'name': 'x', 'meta': {'description': 'x'},
'content': "import os; os.system('<attacker command>')"}))Impact
When the victim runs the shared code, an authenticated low-privileged user achieves remote code execution on the server (the created Function/Tool runs server-side Python) if the victim is an admin or holds workspace.functions / workspace.tools permissions. More generally the executed code can issue any authenticated request as the victim. Requires the victim to click Run, and Open WebUI configured to use Pyodide.
Patched
Pyodide now runs in a sandboxed iframe at an opaque origin by default (sandbox="allow-scripts", no allow-same-origin). At an opaque origin pyfetch, fetch and XMLHttpRequest to the app become cross-origin requests that carry no session cookie and are CORS-blocked, and the js bridge operates on the isolated iframe window with no access to the parent's cookie, token, localStorage or DOM. Full Python, JavaScript and external fetch keep working. IDBFS persistence is available only behind ENABLE_PYODIDE_FILE_PERSISTENCE=true, which restores the same-origin worker and re-accepts this risk.
Workaround
Until upgraded, disable Pyodide code execution or set the Code Execution / Code Interpreter engine to a server-side option.
Credits
@gg0h
Credited to gg0h, Classic298.
Questions
- Does CVE-2026-59214 need the victim to do anything?
Yes. The victim must open the shared chat and click Run on the code. The advisory says it also requires Open WebUI to be configured to use Pyodide.
- Who gets server-side code execution from this?
A victim who is an admin or holds workspace.functions or workspace.tools permission. For other users the code can only send authenticated requests as them.
- What setting re-opens the hole after upgrading?
ENABLE_PYODIDE_FILE_PERSISTENCE=true. It enables IDBFS persistence by restoring the same-origin worker, which brings back this risk.
References
How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology
More Open WebUI vulnerabilities
All Open WebUI entriesCVE-2026-87011
Open WebUI: Unauthenticated requests can stall the server via uncached OIDC fetches in back-channel logout
high7.5Sep 10, 2026CVE-2026-87012
Open WebUI: Any authenticated user can suppress calendar alerts instance-wide via a non-numeric alert value
medium4.3Sep 10, 2026CVE-2026-87013
Open WebUI: Any authenticated user can start a non-terminating request via a folder parent cycle
medium4.3Sep 10, 2026CVE-2026-87014
Open WebUI: Admin demoted through SSO role sync keeps read and write access to all users' notes
medium6.5Sep 10, 2026CVE-2026-87015
Open WebUI: A user's session cookies are sent to tool servers configured for bearer authentication
medium6.8Sep 10, 2026CVE-2026-87016
Open WebUI: Sign-in as another user via wildcard characters in the OAuth subject claim on SQLite
high8.1Sep 10, 2026
