CVE-2026-59714: Open WebUI Cross-channel Message Overwrite Vulnerability
HIGHCVE-2026-59714 is a HIGH (CVSS 7.1) cross-channel message overwrite vulnerability (CWE-862: Missing Authorization) affecting Open WebUI libraries in the PyPI ecosystem. The issue involves cross-channel message overwrite via chat completion api (single-model and multimodel message_ids). Remediation is available by upgrading affected packages to version 0.10.0.
CVE-2026-59714 at a Glance
Security Impact
CVSS: 7.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L).
How to Fix CVE-2026-59714
To remediate this vulnerability, upgrade all affected Open WebUI dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install open-webui>=0.10.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show open-webui
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-59714, inspect your installed packages using pip:
pip show open-webui
Analyze the terminal output to locate any version of Open WebUI in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.10.0), your application is affected.
Note: The pip show open-webui command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-862: Missing Authorization, where the product does not perform an authorization check when an actor attempts to access a resource or perform an action. In Open WebUI, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-59714 Affected Open WebUI Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
open-webui
|
PyPI |
≥ 0.9.5
< 0.10.0
|
0.10.0
|
References
Frequently Asked Questions
What is CVE-2026-59714?
Which Open WebUI versions are affected?
What version fixes CVE-2026-59714?
Is open-webui affected?
What is the CVSS score of CVE-2026-59714?
What CWE is associated with CVE-2026-59714?
How can I check PyPI dependencies for CVE-2026-59714?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-x2ff-v5v8-m75m",
"modified" : "2026-07-24T17:01:07Z",
"published" : "2026-07-24T17:01:07Z",
"aliases" : [ "CVE-2026-59714" ],
"summary" : "Open WebUI: Cross-channel message overwrite via chat completion API (single-model and multimodel message_ids)",
"details" : "## Summary\n\nAny authenticated user can overwrite the content of a message in a channel they do not belong to (including private and DM channels) by sending a chat completion request with a `channel:`-prefixed `chat_id` and a target `message_id`. The `channel:` path routes pipeline output through `_make_channel_emitter`, which writes to the `Messages` table using the caller-supplied `message_id` without binding it to the channel.\n\nThis advisory consolidates two filings of the same flaw: the original single-model form, and a multimodel `message_ids` variant that survives the partial fix shipped in v0.9.6 (see \"Fix status\" below).\n\n## Details (as introduced in v0.9.5)\n\nWhen a user submits a chat completion request with a `chat_id` starting with `channel:`, three authorization gaps combined in v0.9.5:\n\n1. **Ownership check skipped** (`main.py`): the `channel:` prefix caused the entire ownership/membership verification block to be skipped, with no channel membership/write check replacing it.\n\n```python\nif not chat_id.startswith('local:') and not chat_id.startswith('channel:'): # temporary/channel chats are not stored\n if is_new_chat:\n ...\n else:\n if not await Chats.is_chat_owner(chat_id, user.id) and user.role != 'admin':\n raise HTTPException(...)\n```\n\n2. **Message ID from user input**: `id` (and each value of the multimodel `message_ids` map) comes directly from the request body and is passed as `message_id` to the channel emitter.\n\n3. **Unchecked database write** (`socket/main.py` `_make_channel_emitter`):\n\n```python\nasync def _make_channel_emitter(request_info):\n channel_id = request_info['chat_id'].removeprefix('channel:')\n message_id = request_info['message_id'] # user-supplied\n ...\n await Messages.update_message_by_id(message_id, update_form) # no channel/user authz\n```\n\n`Messages.update_message_by_id` performs a direct primary-key update with no `channel_id`/`user_id` validation.\n\n## Fix (shipped in v0.10.0)\n\nv0.9.6 added a channel gate to the `channel:` branch (PR #24725) that closed the single-model path, but it validated only the first entry of the multimodel `message_ids` map, leaving the multimodel fan-out exploitable. v0.10.0 closes the remaining gap with two layers:\n\n1. **Request-time per-entry validation** (`backend/open_webui/main.py`): every entry of `message_ids` is validated against the target channel, not just the first; any entry whose target message does not belong to the channel in `chat_id` is rejected.\n2. **Fail-closed emitter** (`backend/open_webui/socket/main.py`, `_make_channel_emitter`): before writing, it re-reads the target message and returns without writing unless `msg.channel_id` matches the channel derived from `chat_id`. A missing or mismatched message is a no-op, so a write can no longer land in a channel the caller does not target.\n\n## PoC\n\nSingle-model (fixed in v0.9.6):\n\n```bash\ncurl -X POST http://target:8080/api/chat/completions \\\n -H \"Authorization: Bearer $USER_JWT\" -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llama3\", \"stream\": true,\n \"chat_id\": \"channel:any-channel-uuid-here\",\n \"id\": \"target-message-uuid-to-overwrite\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Repeat exactly: This message has been tampered with\"}]\n }'\n```\n\nMultimodel (still works on v0.9.6):\n\n```json\nPOST /api/chat/completions\n{\n \"chat_id\": \"channel:<attacker_channel_id>\",\n \"message_ids\": {\n \"model-a\": \"<message_id_in_attacker_channel>\",\n \"model-b\": \"<victim_channel_message_id>\"\n },\n \"messages\": [{\"role\": \"user\", \"content\": \"...\"}]\n}\n```\n\nThe first id passes channel scope validation; the second id is used by the per-model fan-out and overwrites the victim-channel message (with model output, or the provider-error string on a deterministic error). Even a failing model call writes error content to the target message.\n\n## Impact\n\n**Message integrity destruction:** an authenticated user can overwrite a message in a channel they cannot access, regardless of membership. The overwritten message retains the original author attribution while displaying attacker-chosen content (**impersonation**). Private channels, DM channels, and channels the attacker has no access to are all affected; the REST channel routes correctly return 403 for the same attacker, so the bypass is specific to the chat-completion channel pipeline.\n\n## Affected versions\n\n- Single-model path: introduced in commit `0037baeb2` (v0.9.5), fixed in v0.9.6 (#24725).\n- Multimodel `message_ids` path: present from v0.9.6, fixed in v0.10.0.\n- Consolidated Affected: `>= 0.9.5, < 0.10.0`. Patched: `>= 0.10.0`.\n\n## Distinction from existing CVEs\n\nCVE-2026-45385 (GHSA-wwhq-cx22-f7vv) covered IDOR in the REST endpoint `POST /channels/{id}/messages/{message_id}/update` (`routers/channels.py`); its fix (commit `f5e110f`) only touched `channels.py`. This finding uses a different code path (`POST /api/chat/completions` with `chat_id: \"channel:<id>\"` → `main.py` → `socket/main.py:_make_channel_emitter`), untouched by that fix.\n\n## Suggested fix\n\nValidate **every** value in `message_ids` against the channel (not just the first), rejecting any whose target message does not belong to the channel in `chat_id`. Additionally, make `_make_channel_emitter` fail closed: re-check that the target message's `channel_id` matches the channel before calling `Messages.update_message_by_id`, treating a missing or mismatched message as an error/no-op.\n\n## Consolidation\n\nPer Open WebUI's Report Handling policy this advisory consolidates independent reports of the same chat-completions channel-overwrite flaw:\n\n- Single-model cross-channel overwrite via the `channel:` path: @sfwani (earliest filing).\n- Multimodel `message_ids` fan-out variant that bypasses the v0.9.6 first-id-only gate: @DavidCarliez.\n\nOne CVE for the consolidated advisory.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "open-webui"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0.9.5"
}, {
"fixed" : "0.10.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/open-webui/open-webui/security/advisories/GHSA-x2ff-v5v8-m75m"
}, {
"type" : "WEB",
"url" : "https://github.com/open-webui/open-webui/commit/33e4e0dcc43afcca80f9c635d762cdc76c768ba9"
}, {
"type" : "WEB",
"url" : "https://github.com/open-webui/open-webui/commit/ac3449cac91e62b08a7c28e54fcd044d14dea791"
}, {
"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"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-862" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-24T17:01:07Z",
"nvd_published_at" : null
}
}