# Open WebUI: Forged chat-file link allows cross-user file read and deletion

Open WebUI persisted attacker-supplied file_ids into chat_file rows without ownership checks, letting any user read or delete another user's files via a shared chat.

- Payout: Research
- Severity: high
- Program: Open WebUI
- Found by: 0xEr3n, 5yu4n, oxsignal
- Disclosed: 2026-06-17
- CVE: CVE-2026-54010
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-vrhc-3fr6-pc3c
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-vrhc-3fr6-pc3c
- Tags: area:web domain:web impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:python technique:source-review vuln:access-control vuln:auth-bypass vuln:idor

**Target:** Chat file attachment API and file content/delete endpoints
**Root cause:** Chats.insert_chat_files() stores client-supplied file_ids without verifying the caller owns or can read them, and has_access_to_file()'s shared-chat branch ignores access_type so a read grant satisfies the write check.
**Steps:**
1. Create/own a chat and send `POST /api/v1/chat/completions` with `user_message.files` containing `[{"type":"file","id":"VICTIM_FILE_ID"}]`
2. Backend inserts a chat_file row linking attacker chat to VICTIM_FILE_ID
3. Share the chat and grant read access to self or public
4. Request `GET /api/v1/files/VICTIM_FILE_ID/content` to read the victim file
5. Request `DELETE /api/v1/files/VICTIM_FILE_ID` to delete it (read grant satisfies write check)
**How found:** Code review of the chat completions file ingestion path and the has_access_to_file() shared-chat branch, noticing insert_chat_files() trusts caller file_ids and the branch hardcodes permission='read' regardless of access_type.
**Exploitation:** Attacker needs a victim file_id, forges a chat_file association via the chat completions API, shares the chat with self, then hits the file content/delete endpoints which authorize through the shared-chat branch.
**Escalation:** Same forged association also satisfies the write check, extending read-only access to file deletion; a legitimate read-only share alone suffices for deletion.
**Insight:** When an ACL helper takes an access_type parameter but a branch hardcodes a permission, that branch will satisfy stricter checks (write/delete) too — grep for hardcoded permission strings inside authorization helpers.

## Proof of concept (copied exactly from the original report)

**Forged chat message file payload**

```
[
  {
    "type": "file",
    "id": "VICTIM_FILE_ID"
  }
]
```

**GET victim file content request**

```
GET /api/v1/files/VICTIM_FILE_ID/content
```

