{"id":"CVE-2026-59715","aliases":["EUVD-2026-42623","GHSA-gmfw-g93r-vg53","PYSEC-2026-3599"],"status":"published","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.6.16 before 0.10.0, the Socket.IO server is configured with always_connect=True. The ydoc:awareness:update and ydoc:document:leave Socket.IO handlers accepted collaborative-document events without requiring an authenticated user, allowing unauthorized manipulation of document collaboration state. This issue is fixed in version 0.10.0.","severity":{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00362,"percentile":0.30492,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-306"],"published":"2026-07-09T16:16:02Z","modified":"2026-10-28T02:30:38Z","fixes":[{"ecosystem":"PyPI","package":"open-webui","fixed_in":["0.10.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"open-webui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.6.16"},{"fixed":"0.10.0"}]}]},{"source":"osv","ecosystem":"PyPI","package":"open-webui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.6.16"},{"fixed":"0.10.0"}]}],"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"]},{"source":"osv","ecosystem":"PyPI","package":"open-webui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.6.16"},{"fixed":"0.10.0"}]}],"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"]}],"products":[{"vendor":"open-webui","product":"open-webui"},{"vendor":"openwebui","product":"open_webui"}],"references":[{"url":"https://github.com/open-webui/open-webui/security/advisories/GHSA-gmfw-g93r-vg53","tags":["x_refsource_CONFIRM","exploit","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/open-webui/open-webui/pull/25946","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://github.com/open-webui/open-webui/commit/22f2fe1ffb66c993dad1e0b2b35514acaed2370e","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/open-webui/open-webui/releases/tag/v0.10.0","tags":["x_refsource_MISC","Product","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59715","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-gmfw-g93r-vg53","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/59xxx/CVE-2026-59715.json","tags":["advisory"]},{"url":"https://github.com/open-webui/open-webui","tags":["package"]},{"url":"https://pypi.org/project/open-webui","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-59715","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.6.16 before 0.10.0, the Socket.IO server is configured with always_connect=True. The ydoc:awareness:update and ydoc:document:leave Socket.IO handlers accepted collaborative-document events without requiring an authenticated user, allowing unauthorized manipulation of document collaboration state. This issue is fixed in version 0.10.0.","status":"published","published":"2026-07-09T16:16:02.977Z","modified":"2026-07-09T17:29:46.103Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low","assessor":"cna"}],"cwes":["CWE-306"],"updated_at":"2026-11-02T14:19:58.560602Z"}],"euvd":[{"id":"EUVD-2026-42623","description":"Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.6.16 before 0.10.0, the Socket.IO server is configured with always_connect=True. The ydoc:awareness:update and ydoc:document:leave Socket.IO handlers accepted collaborative-document events without requiring an authenticated user, allowing unauthorized manipulation of document collaboration state. This issue is fixed in version 0.10.0.","status":"published","published":"2026-07-09T16:16:02Z","modified":"2026-07-09T17:29:46Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low"}],"updated_at":"2026-11-02T18:20:03.742277Z"}],"ghsa":[{"id":"GHSA-gmfw-g93r-vg53","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"## 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) — No auth check at all\n```python\n@sio.on('ydoc:awareness:update')\nasync def yjs_awareness_update(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    update = data['update']\n    # No SESSION_POOL check, no room membership check\n    await sio.emit(\n        'ydoc:awareness:update',\n        {'document_id': document_id, 'user_id': user_id, 'update': update},\n        room=f'doc_{document_id}',\n        skip_sid=sid,\n    )\n```\n\n### `ydoc:document:leave` (line 711) — No auth check at all\n```python\n@sio.on('ydoc:document:leave')\nasync def yjs_document_leave(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    # No auth check\n    await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid)\n    await sio.emit('ydoc:user:left',\n        {'document_id': document_id, 'user_id': user_id},\n        room=f'doc_{document_id}')\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.","status":"published","published":"2026-07-24T16:59:44Z","modified":"2026-07-24T16:59:45Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low"}],"cwes":["CWE-306"],"updated_at":"2026-11-02T14:40:52.46233Z"}],"nvd":[{"id":"CVE-2026-59715","description":"Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.6.16 before 0.10.0, the Socket.IO server is configured with always_connect=True. The ydoc:awareness:update and ydoc:document:leave Socket.IO handlers accepted collaborative-document events without requiring an authenticated user, allowing unauthorized manipulation of document collaboration state. This issue is fixed in version 0.10.0.","status":"published","published":"2026-07-09T17:17:04.353Z","modified":"2026-07-10T02:41:47.573Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low","assessor":"secondary"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","level":"medium","assessor":"primary"}],"cwes":["CWE-306"],"updated_at":"2026-11-02T14:12:28.4135Z"}],"osv":[{"id":"CVE-2026-59715","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.6.16 before 0.10.0, the Socket.IO server is configured with always_connect=True. The ydoc:awareness:update and ydoc:document:leave Socket.IO handlers accepted collaborative-document events without requiring an authenticated user, allowing unauthorized manipulation of document collaboration state. This issue is fixed in version 0.10.0.","status":"published","published":"2026-07-09T16:16:02.977Z","modified":"2026-10-28T02:30:38.297923779Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low"}],"cwes":["CWE-306"],"updated_at":"2026-11-02T15:45:12.496548Z"},{"id":"GHSA-gmfw-g93r-vg53","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"## 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) — No auth check at all\n```python\n@sio.on('ydoc:awareness:update')\nasync def yjs_awareness_update(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    update = data['update']\n    # No SESSION_POOL check, no room membership check\n    await sio.emit(\n        'ydoc:awareness:update',\n        {'document_id': document_id, 'user_id': user_id, 'update': update},\n        room=f'doc_{document_id}',\n        skip_sid=sid,\n    )\n```\n\n### `ydoc:document:leave` (line 711) — No auth check at all\n```python\n@sio.on('ydoc:document:leave')\nasync def yjs_document_leave(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    # No auth check\n    await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid)\n    await sio.emit('ydoc:user:left',\n        {'document_id': document_id, 'user_id': user_id},\n        room=f'doc_{document_id}')\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.","status":"published","published":"2026-07-24T16:59:44Z","modified":"2026-08-04T14:40:49.933438433Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low"}],"cwes":["CWE-306"],"updated_at":"2026-11-02T15:46:47.822182Z"},{"id":"PYSEC-2026-3599","title":"Open WebUI: Unauthenticated WebSocket Access to Collaborative Document Handlers (ydoc:awareness:update, ydoc:document:leave)","description":"## 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) — No auth check at all\n```python\n@sio.on('ydoc:awareness:update')\nasync def yjs_awareness_update(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    update = data['update']\n    # No SESSION_POOL check, no room membership check\n    await sio.emit(\n        'ydoc:awareness:update',\n        {'document_id': document_id, 'user_id': user_id, 'update': update},\n        room=f'doc_{document_id}',\n        skip_sid=sid,\n    )\n```\n\n### `ydoc:document:leave` (line 711) — No auth check at all\n```python\n@sio.on('ydoc:document:leave')\nasync def yjs_document_leave(sid, data):\n    document_id = data['document_id']\n    user_id = data.get('user_id', sid)\n    # No auth check\n    await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid)\n    await sio.emit('ydoc:user:left',\n        {'document_id': document_id, 'user_id': user_id},\n        room=f'doc_{document_id}')\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.","status":"published","published":"2026-08-04T11:34:42.643342Z","modified":"2026-08-04T14:30:28.708679396Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","level":"low"}],"updated_at":"2026-11-02T15:52:56.847083Z"}]}}
