PYSEC-2026-3599
Vulnerability from pysec - Published: 2026-08-04 11:34 - Updated: 2026-08-04 13:36Summary
The Socket.IO server is configured with always_connect=True (lines 78, 91 in backend/open_webui/socket/main.py) and the connect handler (line 329) never rejects unauthenticated connections. Two Ydoc event handlers have zero authentication checks, allowing unauthenticated clients to interact with collaborative document sessions.
Vulnerable Code
ydoc:awareness:update (line 741) — No auth check at all
@sio.on('ydoc:awareness:update')
async def yjs_awareness_update(sid, data):
document_id = data['document_id']
user_id = data.get('user_id', sid)
update = data['update']
# No SESSION_POOL check, no room membership check
await sio.emit(
'ydoc:awareness:update',
{'document_id': document_id, 'user_id': user_id, 'update': update},
room=f'doc_{document_id}',
skip_sid=sid,
)
ydoc:document:leave (line 711) — No auth check at all
@sio.on('ydoc:document:leave')
async def yjs_document_leave(sid, data):
document_id = data['document_id']
user_id = data.get('user_id', sid)
# No auth check
await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid)
await sio.emit('ydoc:user:left',
{'document_id': document_id, 'user_id': user_id},
room=f'doc_{document_id}')
Root Cause: always_connect=True (line 78)
sio = socketio.AsyncServer(
always_connect=True, # Never rejects connections
...
)
The connect handler (line 329) adds authenticated users to SESSION_POOL but never returns False or raises an exception for unauthenticated connections.
Exploitation
- An unauthenticated attacker connects via Socket.IO (no token needed)
- The attacker emits
ydoc:awareness:updatewith: document_id: a known/guessed note UUID (format:note:{uuid})user_id: spoofed to impersonate any userupdate: arbitrary awareness data (fake cursor positions, selections)- The fake awareness data is broadcast to all legitimate users in the document room
- The attacker can also emit
ydoc:document:leavewith spoofeduser_idto broadcast fakeydoc:user:leftevents
Impact
- UI disruption: Fake cursor positions and user presence in collaborative editing sessions
- User impersonation: Attacker can spoof any
user_idin awareness updates - Resource exhaustion: Unlimited unauthenticated WebSocket connections maintained by the server
Note: Other Ydoc handlers (ydoc:document:join, ydoc:document:update, ydoc:document:state) correctly check SESSION_POOL membership.
Suggested Fix
- Set
always_connect=Falseor reject unauthenticated connections in theconnecthandler - Add
SESSION_POOLchecks toydoc:awareness:updateandydoc:document:leave - Add room membership verification before broadcasting to document rooms
AI Disclosure (per Rule 11): AI (Claude) was used to assist with source code review, identifying potential vulnerability patterns, and drafting this report. The researcher directed the analysis, selected focus areas, and independently verified all findings against a running v0.8.12 Docker instance using real HTTP requests with two test accounts. The PoCs included are reproducible and were confirmed live before submission.
| Name | purl | open-webui | pkg:pypi/open-webui |
|---|
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "open-webui",
"purl": "pkg:pypi/open-webui"
},
"ranges": [
{
"events": [
{
"introduced": "0.6.16"
},
{
"fixed": "0.10.0"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.6.16",
"0.6.18",
"0.6.19",
"0.6.20",
"0.6.21",
"0.6.22",
"0.6.23",
"0.6.24",
"0.6.25",
"0.6.26",
"0.6.26.dev1",
"0.6.27",
"0.6.28",
"0.6.29",
"0.6.30",
"0.6.31",
"0.6.32",
"0.6.33",
"0.6.34",
"0.6.35",
"0.6.36",
"0.6.37",
"0.6.38",
"0.6.39",
"0.6.40",
"0.6.41",
"0.6.42",
"0.6.43",
"0.7.0",
"0.7.1",
"0.7.2",
"0.8.0",
"0.8.1",
"0.8.10",
"0.8.11",
"0.8.12",
"0.8.2",
"0.8.3",
"0.8.4",
"0.8.5",
"0.8.6",
"0.8.7",
"0.8.8",
"0.8.9",
"0.9.0",
"0.9.1",
"0.9.2",
"0.9.3",
"0.9.4",
"0.9.5",
"0.9.6"
]
}
],
"aliases": [
"CVE-2026-59715",
"GHSA-gmfw-g93r-vg53"
],
"details": "## Summary\n\nThe Socket.IO server is configured with `always_connect=True` (lines 78, 91 in `backend/open_webui/socket/main.py`) and the `connect` handler (line 329) never rejects unauthenticated connections. Two Ydoc event handlers have zero authentication checks, allowing unauthenticated clients to interact with collaborative document sessions.\n\n## Vulnerable Code\n\n### `ydoc:awareness:update` (line 741) \u2014 No auth check at all\n```python\n@sio.on(\u0027ydoc:awareness:update\u0027)\nasync def yjs_awareness_update(sid, data):\n document_id = data[\u0027document_id\u0027]\n user_id = data.get(\u0027user_id\u0027, sid)\n update = data[\u0027update\u0027]\n # No SESSION_POOL check, no room membership check\n await sio.emit(\n \u0027ydoc:awareness:update\u0027,\n {\u0027document_id\u0027: document_id, \u0027user_id\u0027: user_id, \u0027update\u0027: update},\n room=f\u0027doc_{document_id}\u0027,\n skip_sid=sid,\n )\n```\n\n### `ydoc:document:leave` (line 711) \u2014 No auth check at all\n```python\n@sio.on(\u0027ydoc:document:leave\u0027)\nasync def yjs_document_leave(sid, data):\n document_id = data[\u0027document_id\u0027]\n user_id = data.get(\u0027user_id\u0027, sid)\n # No auth check\n await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid)\n await sio.emit(\u0027ydoc:user:left\u0027,\n {\u0027document_id\u0027: document_id, \u0027user_id\u0027: user_id},\n room=f\u0027doc_{document_id}\u0027)\n```\n\n### Root Cause: `always_connect=True` (line 78)\n```python\nsio = socketio.AsyncServer(\n always_connect=True, # Never rejects connections\n ...\n)\n```\n\nThe `connect` handler (line 329) adds authenticated users to `SESSION_POOL` but never returns `False` or raises an exception for unauthenticated connections.\n\n## Exploitation\n\n1. An unauthenticated attacker connects via Socket.IO (no token needed)\n2. The attacker emits `ydoc:awareness:update` with:\n - `document_id`: a known/guessed note UUID (format: `note:{uuid}`)\n - `user_id`: spoofed to impersonate any user\n - `update`: arbitrary awareness data (fake cursor positions, selections)\n3. The fake awareness data is broadcast to all legitimate users in the document room\n4. The attacker can also emit `ydoc:document:leave` with spoofed `user_id` to broadcast fake `ydoc:user:left` events\n\n## Impact\n\n- **UI disruption**: Fake cursor positions and user presence in collaborative editing sessions\n- **User impersonation**: Attacker can spoof any `user_id` in awareness updates\n- **Resource exhaustion**: Unlimited unauthenticated WebSocket connections maintained by the server\n\nNote: Other Ydoc handlers (`ydoc:document:join`, `ydoc:document:update`, `ydoc:document:state`) correctly check `SESSION_POOL` membership.\n\n## Suggested Fix\n\n1. Set `always_connect=False` or reject unauthenticated connections in the `connect` handler\n2. Add `SESSION_POOL` checks to `ydoc:awareness:update` and `ydoc:document:leave`\n3. Add room membership verification before broadcasting to document rooms\n\n---\n\n\u003e **AI Disclosure (per Rule 11):** AI (Claude) was used to assist with source code review, identifying potential vulnerability patterns, and drafting this report. The researcher directed the analysis, selected focus areas, and independently verified all findings against a running v0.8.12 Docker instance using real HTTP requests with two test accounts. The PoCs included are reproducible and were confirmed live before submission.",
"id": "PYSEC-2026-3599",
"modified": "2026-08-04T13:36:26.443650Z",
"published": "2026-08-04T11:34:42.643342Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/security/advisories/GHSA-gmfw-g93r-vg53"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-59715"
},
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/pull/25946"
},
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/commit/22f2fe1ffb66c993dad1e0b2b35514acaed2370e"
},
{
"type": "PACKAGE",
"url": "https://github.com/open-webui/open-webui"
},
{
"type": "WEB",
"url": "https://github.com/open-webui/open-webui/releases/tag/v0.10.0"
},
{
"type": "PACKAGE",
"url": "https://pypi.org/project/open-webui"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-gmfw-g93r-vg53"
}
],
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.