GHSA-vrhc-3fr6-pc3c: Open WebUI: Forged chat-file link allows cross-user file read and deletion
SummaryOpen WebUI `v0.9.5` lets an authenticated user attach arbitrary `file_id` values to their own chat message without checking whether they own or can read those files. If the attacker then shares that chat and grants themselves read access, `has_access_to_file()` treats the victim file as accessible through the shared chat, and the file endpoints read or delete the victim file.ImpactSecurity boundary crossed: file confidentiality and integrity.An authenticated attacker who knows or obtains a victim `file_id` can make Open WebUI authorize, through an attacker-owned shared chat:reading the victim file via `GET /api/v1/files/{id}/content`, anddeleting the victim file via `DELETE /api/v1/files/{id}`.Root CauseClient-controlled message file IDs are persisted without file authorization checks:`insert_chat_files()` stores the provided IDs directly:Later, file authorization trusts shared-chat associations:The download endpoint uses this helper:On affected versions this shared-chat branch is not gated on `access_type` (the grant lookup hardcodes `permission='read'`, but nothing checks that the request itself is a read). The same forged association therefore also satisfies the `write` check that `DELETE /api/v1/files/{id}` performs, so the attacker can delete the victim file, not only read it.Because the shared-chat branch ignores `access_type`, the deletion does not require the forged association at all. A user granted only **read** access to a chat that the owner legitimately shared can delete the owner's own files attached to that chat via `DELETE /api/v1/files/{id}`, since the read grant satisfies the `write` check. The forged association (above) broadens this to any victim `file_id`; a legitimate read-only share reaches it without any forgery.PoCAttacker creates or uses a chat they own.Attacker sends `POST /api/chat/completions` or `POST /api/v1/chat/completions` where top-level `user_message.files` contains:Backend inserts a `chat_file` row linking the attacker chat to `VICTIM_FILE_ID`.Attacker shares the chat and grants read access to themselves or public access.Attacker requests:Expected: 404/403 because the attacker does not own or otherwise have access to the victim file.Actual: file authorization succeeds through the attacker-controlled shared-chat association.Local VerificationI verified the bug locally with Open WebUI's real `Chats.insert_chat_files()` and real `has_access_to_file()` implementations. The harness uses fake DB adapters only to avoid this environment's async SQLite hang; the security-sensitive logic under test is the application code.Result:PoC:Recommended FixBefore calling `Chats.insert_chat_files()`, filter `user_message.files` to files the caller owns or can read:Also consider enforcing this inside `Chats.insert_chat_files()` so future call sites cannot create unauthorized `chat_file` associations.Additionally, the shared-chat branch of `has_access_to_file()` should honour `access_type`, so a read grant cannot satisfy the write check used by file deletion.ConsolidationPer Open WebUI's Report Handling policy this consolidates independent reports of the same chat-file authorization flaws into one advisory and CVE:Cross-user file READ via a forged `chat_file` association (`GET /api/v1/files/{id}/content`): @0xEr3n. Fixed by #25054, which gates `Chats.insert_chat_files()` so a caller can only link files they own or can read.Cross-user file DELETION via the shared-chat branch ignoring `access_type` (`DELETE /api/v1/files/{id}`): reported independently by @oxsignal (earliest filing; reached via a legitimately read-only-shared chat, no forged association needed), by @0xEr3n (via the forged association), and by @5yu4n. Fixed by #24755, which makes the shared-chat branch honour `access_type`.Affected: `<= 0.9.5`. Patched: `>= 0.9.6`. One CVE for the consolidated advisory.
CVSS v3.1: 8.3