Open WebUI: shared-chat branch ignores access_type, allowing unauthorized file deletion
High8.0CVE-2026-45671 · Published May 14, 2026 · updated Jul 13, 2026
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| open-webui PyPI | < 0.9.0 | 0.9.0 |
Details and references
### Summary Any authenticated user can permanently delete files owned by other users via `DELETE /api/v1/files/{id}` when the target file is referenced in any shared chat. The `has_access_to_file()` authorization gate unconditionally grants access through its shared-chat branch. It checks neither the requesting user's identity nor the type of operation being performed. File UUIDs (which would otherwise be impractical to guess) are disclosed to any user with read access to a knowledge base via `GET /api/v1/knowledge/{id}/files`. ### Details The root cause is in `has_access_to_file()` in [backend/open_webui/routers/files.py](https://github.com/open-webui/open-webui/blob/main/backend/open_webui/routers/files.py). When a user calls `DELETE /api/v1/files/{file_id}`, the endpoint delegates authorization to `has_access_to_file(file_id, access_type="write", user=requesting_user)`. Inside that function, one branch checks whether the file is referenced in any shared chat: ```python chats = Chats.get_shared_chats_by_file_id(file_id, db=db) if chats: return True ``` This branch has two missing checks: 1. **No user check:** It asks "does any shared chat anywhere reference this file?", not "does the requesting user own or participate in that chat." Any authenticated user passes this check. 2. **No operation check:** The `access_type` parameter (`"write"` for delete) is accepted but never inspected. The branch returns `True` regardless of whether the caller is requesting read access or delete access. The result: if any user has shared any chat that references a file, that file becomes deletable by every authenticated user on the instance. The delete endpoint has no secondary ownership check (unlike the content-update endpoint), so this authorization bypass leads directly to permanent file removal from the database, disk, and all knowledge base associations. **How an attacker obtains file UUIDs:** UUIDs are impractical to brute-force, but they don't need to be. Any user with read access to a knowledge base can retrieve the file IDs of every document in it via `GET /api/v1/knowledge/{id}/files`. In deployments where knowledge bases are shared across teams (a common and intended use case), this gives any regular user a list of valid file UUIDs they can target. **Suggested fix**: gate the shared-chat branch on `access_type` so it only authorizes read operations: ```python if access_type == "read": chats = Chats.get_shared_chats_by_file_id(file_id, db=db) if chats: return True ``` **Classification:** - CWE-639: Authorization Bypass Through User-Controlled Key - OWASP API1:2023: Broken Object Level Authorization - CVSS 3.1: 5.7 , `AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H` Tested on Open WebUI **0.8.3** using a default Docker configuration. ### PoC **Prerequisites:** - Default Open WebUI installation (Docker: `ghcr.io/open-webui/open-webui:main`) - Two user accounts: a victim (any role) and an attacker (role: `user`) **Setup (victim):** 1. Log in as the victim 2. Create a knowledge base and upload a document 3. Start a new chat, attach the KB file, and send a message 4. Share the chat using the share button **Obtaining the file UUID (attacker):** If the attacker has read access to the knowledge base (e.g. a shared team KB), the file UUID is available via: ``` GET /api/v1/knowledge/{kb_id}/files ``` This returns metadata for all files in the KB, including their UUIDs. **Exploit (attacker):** ```bash python3 poc.py --url http://<host>:3000 --file-id <target-file-uuid> -t <attacker-jwt> ``` The PoC script (attached as `poc.py`): 1. Authenticates as the attacker 2. Confirms the target file is accessible via `GET /api/v1/files/{id}/data/content` 3. Deletes the file via `DELETE /api/v1/files/{id}` 4. Verifies permanent deletion (HTTP 404 on subsequent GET) No special tooling is required , the script uses only Python 3 standard library (`urllib`). ### Impact **Who is affected:** Any multi-user Open WebUI deplo
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-639
- Also known as
- CVE-2026-45671, PYSEC-2026-2692
More Open WebUI advisories
All Open WebUI| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| May 14 | Open WebUI has Stored Cross-Site Scripting In Profile Picture CVE-2026-45299Medium5.4fixed in 0.8.0 | Medium5.4 | 0.8.0 |
| May 14 | Open WebUI: Missing permission check in files API allows authenticated users to list, access and delete every uploaded file CVE-2026-45301High8.1fixed in 0.3.16 | High8.1 | 0.3.16 |
| May 14 | Open WebUI has stored XSS via the HTML renedering view CVE-2026-45303High7.7fixed in 0.6.5 | High7.7 | 0.6.5 |
| May 14 | Open WebUI has stored XSS via attacker-controlled file extension in /api/v1/audio/transcriptions CVE-2026-45315High8.7fixed in 0.9.3 | High8.7 | 0.9.3 |
| May 14 | Open WebUI has XSS via SVG in /api/v1/channels/webhooks/{webhook_id}/profile/image CVE-2026-45314High6.1fixed in 0.9.3 | High6.1 | 0.9.3 |
| May 14 | Open WebUI: Read-Only Users Can Toggle Note Pin Status via Incorrect Permission Check (Write via Read-Only Access) CVE-2026-45316Low3.5fixed in 0.9.3 | Low3.5 | 0.9.3 |