GHSA-wch8-mhj5-9frg Open WebUI: Cross-user file disclosure via /api/chat/completions image_url field
summary`POST /api/chat/completions` accepts an `image_url.url` value that, when it does NOT start with `http://`, `https://`, or `data:image/`, is interpreted as a file id and resolved against the global file table with no ownership check. An authenticated user can therefore set `image_url.url` to another user's file id, the server reads that file from disk, base64-encodes it, and injects the data URI into the LLM request. The user then prompts the LLM to describe / OCR the file and reads the content back.Same class as CVE-2026-44560 (RAG cross-user access) and the multiple `has_access_to_file` checks added in `routers/files.py` -- the auth boundary was tightened on the file router but not on this conversion path.affected code`backend/open_webui/utils/middleware.py:2113-2150` -- `convert_url_images_to_base64`:called from the main chat completion middleware at `middleware.py:2357`:`backend/open_webui/utils/files.py:57-95` -- `get_image_base64_from_url`:`Files.get_file_by_id` in `models/files.py:161` does a bare `db.get(File, id)` -- no ownership filter. there is a separate `Files.get_file_by_id_and_user_id` at line 172 that does filter on `user_id`, and the file router uses `has_access_to_file(id, 'read', user, db)` at `routers/files.py:626` etc. neither check exists on this path.reproductionAs user A, upload any file (image works cleanly, pdf works if a vision-capable model is configured). Note the file id from the upload response, e.g. `c7f1d8e3-...`.As user B, POST to `/api/v1/chat/completions` with body:Server reads user A's file from disk, base64-encodes it, and sends to the LLM as user B's image attachment. LLM response contains the file content.file id discoveryFile ids are UUIDs and not enumerable directly, but they leak via:shared chats / channels containing the original uploadknowledge base members can see ids of files contributed by othersa user who can read a folder index sees the file ids of files insidechat history exports (`/api/v1/chats/{id}`) include file idsthe user themselves can be tricked into pasting / sharing an id (less likely)impactAny authenticated user can read any other user's file content (image and any file with an image-guess mimetype path) via this channel. Severity is bounded by what the LLM will accept in `image_url` -- in practice, image files work cleanly with any vision model; pdf / docx work with multi-modal providers that accept them.suggested fixThread the authenticated user through to `get_image_base64_from_url` and resolve the file via `Files.get_file_by_id_and_user_id(id, user.id)` (or `has_access_to_file(id, 'read', user, db)` if shared-via-knowledge-base access is intended). Same pattern that's already used in `routers/files.py:626` and elsewhere.minimal patch sketch:and pipe `user` through `convert_url_images_to_base64(form_data, user)` from the middleware caller. happy to send a PR once you confirm the fix shape you want.variant notethis was found via patch-diffing existing advisories. the same bug class likely exists in any other site that calls `Files.get_file_by_id` without an adjacent `has_access_to_file` / `get_file_by_id_and_user_id` check. quick grep:worth a sweep across utils/ and routers/ for missed sites.environmentOpen-webui main branch as of commit `3660bc0` (2026-05-10). python 3.x backend. confirmed by reading the source; no instance stood up.
CVSS v3.1 score: 6.5