# Open WebUI: Cross-user code-interpreter and tool execution via unvalidated Socket.IO event-caller session_id

Open WebUI's Socket.IO event-caller trusted a client-supplied session_id, letting any user run code-interpreter/tool events in another user's session, escalating to server RCE via an admin victim.

- Payout: Research
- Severity: high
- Program: Open WebUI
- Found by: waiveyk
- Disclosed: 2026-07-24
- CVE: CVE-2026-59216
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-74h3-cxq7-vc5q
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-74h3-cxq7-vc5q
- Tags: area:web domain:web impact:ato impact:rce kind:research platform:ghsa sev:high tech:python tech:websocket technique:chained technique:source-review vuln:access-control vuln:auth-bypass vuln:rce

**Target:** Socket.IO event-caller / chat-completions API (backend/open_webui/socket/main.py)
**Root cause:** get_event_call() only checks that the client-supplied session_id exists in SESSION_POOL, never that it belongs to the authenticated requester; session_id comes from the request body in main.py while user_id is server-derived.
**Steps:**
1. Authenticate as a low-privilege `user`; ensure code interpreter is enabled.
2. Share a note with the victim (admin) and have them open it while online; obtain their live socket id via `ydoc:document:join`.
3. Send `POST /api/v1/chat/completions` with the victim's `session_id` in the body and a model/Direct Connection you control to choose the payload.
4. `execute:python` / `execute:tool` events are delivered to the victim's socket, running attacker code in their session.
5. With an admin victim, use the hijacked context to call `POST /api/v1/functions/create`; source is `exec()`'d server-side → RCE as the server process (root in default container).
**How found:** Code review of get_event_call() showing session_id sourced from the request body and validated only by membership in SESSION_POOL, plus noticing ydoc:document:join leaks other participants' socket ids.
**Exploitation:** Attacker uses own account plus a shared note to learn the victim's socket id, then submits chat completions carrying the victim's session_id so code-interpreter/tool events execute in the victim's browser context; against an admin victim the hijacked context reaches the admin-only Functions API whose source is exec()'d server-side, giving blind OOB RCE (callback returned uid=0(root)).
**Escalation:** Cross-user session hijack chained into admin Functions API code execution for server-side RCE as root.
**Insight:** When a server routes events to a client-supplied session/socket id, check whether ownership is verified against the server-derived user id, not just pool membership; collaboration features that broadcast peer socket ids turn an IDOR into targeted cross-user execution.

