RBAC Authorization Bypass: Resource Context Ignored
June 12, 2026

CVE Number
CVE-2026-45831
Summary
ChromaDB's SimpleRBACAuthorizationProvider, the only built-in RBAC provider and the one used in all official documentation examples, evaluates whether a user holds a given permission but never checks which tenant, database, or collection that permission applies to. A user configured with read access to a specific tenant can read from any tenant. A user with write access can modify data across all tenants.
Products Impacted
This vulnerability affects ChromaDB versions from 0.5.0 to the latest release at the time of publication
CVSS Score: 8.8
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
CWE Categorization
CWE-863: Incorrect Authorization
Details
The vulnerability is in chromadb/auth/simple_rbac_authz/__init__.py:40-75. The initialization code builds a mapping of user_id -> set(actions):
class SimpleRBACAuthorizationProvider(ServerAuthorizationProvider):
def __init__(self, system: System):
super().__init__(system)
# ...
# This AuthorizationProvider does not support
# per-resource authorization so we just map the user ID to the
# permissions they have.
self._permissions: Dict[str, Set[str]] = {}
for user in self._config["users"]:
_actions = self._config["roles_mapping"][user["role"]]["actions"]
self._permissions[user["id"]] = set(_actions)
The authorization decision in authorize_or_raise() only checks whether the user’s action set contains the requested action:
def authorize_or_raise(
self, user: UserIdentity, action: AuthzAction, resource: AuthzResource
) -> None:
policy_decision = False
if (
user.user_id in self._permissions
and action in self._permissions[user.user_id] # Only checks action
):
policy_decision = True
logger.debug(
f"Authorization decision: Access "
f"{'granted' if policy_decision else 'denied'} for "
f"user [{user.user_id}] attempting to "
f"[{action}] [{resource}]"
)
if not policy_decision:
raise HTTPException(status_code=403, detail="Forbidden")
The resource parameter is of type AuthzResource, defined at chromadb/auth/__init__.py:186-194:
@dataclass
class AuthzResource:
tenant: Optional[str]
database: Optional[str]
collection: Optional[str]
It carries the tenant, database, and collection context for the authorization decision, but authorize_or_raise() never reads resource.tenant, resource.database, or resource.collection. The decision is purely action in permissions[user_id].
Timeline
- February 17th, 2026 - Initial disclosure to ChromaDB per their security page https://www.trychroma.com/security.
- February 24th, 2026 - Attempted follow up through other trychroma emails.
- March 5th, 2026 - Attempted contact through IT-ISAC.
- April 16th, 2026 - Attempted final follow up through all previous channels and social media.
- May 18th, 2026 - Publicly disclosed a first vulnerability, no response from the vendor.
Project URL:
https://github.com/chroma-core/chroma/
RESEARCHER: Esteban Tonglet, Security Researcher, HiddenLayer
Related SAI Security Advisory
September 11, 2026
_READ_ONLY_COMMANDS_POSIX expansion adds 31 commands with no path checking, granting unconditional access to the full host filesystem
Mistral Vibe automatically approves a large set of commands that are not subject to the expected workspace path restrictions, allowing files anywhere on the host to be accessed without user approval.
September 11, 2026
Environment variable prefixes stripped from permission check enable RCE via env injection
Mistral Vibe does not consider environment variable assignments when checking whether a command can run without approval, allowing environment controlled behavior in allowlisted programs such as Git to be abused for arbitrary code execution.