Summary
The SimpleRBACAuthorizationProvider shipped with ChromaDB never inspects the AuthzResource (tenant, database, collection). It checks only the action and user_id. Any authenticated user holding a permission (e.g., collection:add) is authorized for every tenant's collections. The CVE-2026-45830/45832 fixes (Rust frontend validate_collection_scope in aed1ab8) were never ported to the Python FastAPI server. The released PyPI package (1.5.9) and current HEAD are equally vulnerable.
Root cause (three independently sufficient layers)
Layer 1: AuthzResource ignored (chromadb/auth/simple_rbac_authz/__init__.py:61-74):
if (user.user_id in self._permissions and action in self._permissions[user.user_id]):
policy_decision = True
Source comment at line 43: "This AuthorizationProvider does not support per-resource authorization." AuthzResource{tenant, database, collection} is accepted but never read. SimpleRBAC is the ONLY production authz provider shipped with ChromaDB.
Layer 2: V1 endpoints pass None (chromadb/server/fastapi/__init__.py):
All 6 V1 data endpoints (add_v1:2126, update_v1:2169, upsert_v1:2206, get_v1:2245, delete_v1:2290, count_v1:2319) call sync_auth_and_get_tenant_and_database_for_request(headers, ACTION, None, None, collection_id) and discard the return value.
Layer 3: Backend resolves by ID only (chromadb/api/segment.py:1160-1164):
def _get_collection(self, collection_id: UUID) -> t.Collection:
collections = self._sysdb.get_collections(id=collection_id) # no tenant/database filter
PoC
Tested against chromadb==1.5.9 (latest PyPI) with chroma_server_authn_provider=basic + chroma_server_authz_provider=simple_rbac:
[+] alice -> own collection : GRANTED (expected)
[!] alice -> VICTIM tenant : GRANTED <-- BUG: cross-tenant write authorized
[!] alice -> VICTIM collection:get : GRANTED <-- BUG
[!] alice -> VICTIM collection:delete : GRANTED <-- BUG
[!] alice -> VICTIM collection:query : GRANTED <-- BUG
VULNERABLE: SimpleRBACAuthorizationProvider grants cross-tenant access.
Attack: POST /api/v1/collections/{victim_collection_uuid}/get|add|delete|update with any valid auth token holding the action permission.
Relation to existing CVEs
- CVE-2026-45830: "any authenticated user can read/write/update/delete any tenant's collections" -- this is still literally true in the Python server at HEAD.
- CVE-2026-45832: "V1 collection-level endpoints pass None for tenant/database to the authorization layer" -- still literally true at HEAD.
- Rust fix (
aed1ab8): validate_collection_scope() added to the Rust frontend. Never ported to Python.
- This is reportable as an incomplete fix / regression of the existing CVE cluster.
Impact
Cross-tenant data breach in multi-tenant ChromaDB deployments. Any authenticated user can read, modify, and delete any tenant's vector embeddings and documents. Affects PyPI 1.5.9 (latest) and HEAD.
Severity: High (CVSS 8.8, AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H, CWE-639/CWE-862)
Suggested fix
Port the Rust validate_collection_scope to the Python server, or make SimpleRBAC resource-aware (check resource.tenant/resource.collection against the user's grants). Also fix V1 data endpoints to use the auth-resolved tenant/database instead of discarding them.
Credit
Pavan Nallamothu
Summary
The
SimpleRBACAuthorizationProvidershipped with ChromaDB never inspects theAuthzResource(tenant, database, collection). It checks only the action and user_id. Any authenticated user holding a permission (e.g.,collection:add) is authorized for every tenant's collections. The CVE-2026-45830/45832 fixes (Rust frontendvalidate_collection_scopeinaed1ab8) were never ported to the Python FastAPI server. The released PyPI package (1.5.9) and current HEAD are equally vulnerable.Root cause (three independently sufficient layers)
Layer 1: AuthzResource ignored (
chromadb/auth/simple_rbac_authz/__init__.py:61-74):Source comment at line 43: "This AuthorizationProvider does not support per-resource authorization."
AuthzResource{tenant, database, collection}is accepted but never read. SimpleRBAC is the ONLY production authz provider shipped with ChromaDB.Layer 2: V1 endpoints pass None (
chromadb/server/fastapi/__init__.py):All 6 V1 data endpoints (
add_v1:2126,update_v1:2169,upsert_v1:2206,get_v1:2245,delete_v1:2290,count_v1:2319) callsync_auth_and_get_tenant_and_database_for_request(headers, ACTION, None, None, collection_id)and discard the return value.Layer 3: Backend resolves by ID only (
chromadb/api/segment.py:1160-1164):PoC
Tested against
chromadb==1.5.9(latest PyPI) withchroma_server_authn_provider=basic+chroma_server_authz_provider=simple_rbac:Attack:
POST /api/v1/collections/{victim_collection_uuid}/get|add|delete|updatewith any valid auth token holding the action permission.Relation to existing CVEs
aed1ab8):validate_collection_scope()added to the Rust frontend. Never ported to Python.Impact
Cross-tenant data breach in multi-tenant ChromaDB deployments. Any authenticated user can read, modify, and delete any tenant's vector embeddings and documents. Affects PyPI 1.5.9 (latest) and HEAD.
Severity: High (CVSS 8.8, AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H, CWE-639/CWE-862)
Suggested fix
Port the Rust
validate_collection_scopeto the Python server, or make SimpleRBAC resource-aware (checkresource.tenant/resource.collectionagainst the user's grants). Also fix V1 data endpoints to use the auth-resolved tenant/database instead of discarding them.Credit
Pavan Nallamothu