{"id":"CVE-2026-59214","aliases":["GHSA-4r2p-27mh-5m22"],"title":"Open WebUI: Stored web worker XSS via Pyodide","summary":"Open WebUI: Stored web worker XSS via Pyodide","severity":"high","cvss":7.3,"cwe":["CWE-79"],"vendor":"open-webui","product":"open-webui","ecosystem":"pip","affected":["open-webui < 0.10.0"],"patched":["open-webui 0.10.0"],"published":"2026-07-24","updated":"2026-07-24","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-4r2p-27mh-5m22","references":[{"url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-4r2p-27mh-5m22"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59214"},{"url":"https://github.com/advisories/GHSA-4r2p-27mh-5m22"}],"tags":["ghsa","pip"],"epss":0.00286,"epssPercentile":0.21336,"ingestedAt":"2026-07-24T17:34:27.435Z","slug":"CVE-2026-59214","body":"## Overview\n\n**Title:** Same-origin Pyodide code execution allows server-side RCE via a shared chat\n\n### Summary\n\nOpen 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**.\n\n### Details\n\nPyodide'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.\n\n```python\nfrom pyodide.http import pyfetch\nimport json\nawait pyfetch('/api/v1/functions/create', method='POST', credentials='include',\n              headers={'Content-Type': 'application/json'},\n              body=json.dumps({'id': 'x', 'name': 'x', 'meta': {'description': 'x'},\n                               'content': \"import os; os.system('<attacker command>')\"}))\n```\n\n### Impact\n\nWhen 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.\n\n### Patched\n\nPyodide 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.\n\n### Workaround\n\nUntil upgraded, disable Pyodide code execution or set the Code Execution / Code Interpreter engine to a server-side option.\n\n### Credits\n\n@gg0h\n\n## Affected packages\n\n- `open-webui < 0.10.0`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `open-webui 0.10.0`","depth":"twilight","depthScore":40,"depthScoreParts":{"impact":40.2,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}