CVE-2026-69148 Overview
CVE-2026-69148 is a missing authorization flaw [CWE-862] in MLflow, an open source platform for managing agents, large language models, and machine learning models. Prior to version 3.15.0, the CreateModelVersion handler accepts a run_id or model_id after _validate_source_run() or _validate_source_model() in mlflow/server/handlers.py verifies only path containment. Authenticated users can create a model version that references another user's artifact directory and read files through GET /model-versions/get-artifact without holding the required READ permission. Version 3.15.0 fixes the issue.
Critical Impact
Authenticated users can read artifacts owned by other tenants by anchoring a new model version to a run or model they do not own.
Affected Products
- MLflow versions prior to 3.15.0
- MLflow deployments using the built-in authentication server (mlflow.server.auth)
- Multi-tenant MLflow tracking and model registry environments
Discovery Timeline
- 2026-08-17 - CVE-2026-69148 published to NVD
- 2026-08-18 - Last updated in NVD database
Technical Details for CVE-2026-69148
Vulnerability Analysis
MLflow's model registry stores each model version's source inside the artifact directory of a run or logged model. The CreateModelVersion endpoint requires the caller to hold update rights on the target registered model, but it did not require READ on the source run or model referenced by run_id/model_id. Downstream artifact reads through GET /model-versions/get-artifact are gated on the registered model, not the underlying run. An attacker can register a new version pointing at another tenant's artifact directory and then retrieve its files through their own registered model.
Root Cause
The pre-patch validators _validate_source_run() and _validate_source_model() in mlflow/server/handlers.py only confirmed that source sits within an allowed artifact path. They did not consult the authorization layer to verify that the caller can read the source run or model. This is a classic missing authorization check [CWE-862] where path containment was conflated with access control.
Attack Vector
An authenticated user with permission to create model versions on a registered model they control sends a CreateModelVersion request whose run_id or model_id references a run or model owned by another user. The server accepts the request, creates a version anchored to the victim's artifact directory, and subsequent GET /model-versions/get-artifact calls return the victim's files.
return _get_permission_from_registered_model_or_prompt_name().can_manage
+def validate_can_create_model_version():
+ # A model version anchors its `source` inside the artifact directory of the run/model
+ # named by `run_id`/`model_id`. Downstream artifact reads are gated on the model version's
+ # registered model, so without a read check here a caller could point `source` at another
+ # user's run/model and read those artifacts through their own registered model. Require read
+ # on the source run/model to keep create-time access consistent with artifact-read gating.
+ if not _validate_can_update_registered_model_or_prompt():
+ return False
+ body = request.get_json(force=True, silent=True)
+ body = body if isinstance(body, dict) else {}
+ # Presence of run_id/model_id means the version is anchored to that source, so require
+ # READ on it. Guard on presence (not truthiness): an explicitly-supplied empty id is
+ # denied here rather than being allowed to slip past the guard as if it were absent.
+ if "run_id" in body and not (body["run_id"] and _get_permission_from_run_id().can_read):
+ return False
+ if "model_id" in body and not (body["model_id"] and _get_permission_from_model_id().can_read):
+ return False
+ return True
+
+
def validate_can_create_experiment() -> bool:
return _user_can_create_in_workspace()
Source: GitHub Commit 4bb7474. The patch introduces validate_can_create_model_version() in mlflow/server/auth/__init__.py, which requires READ permission on any run_id or model_id supplied in the request body before the version is created.
Detection Methods for CVE-2026-69148
Indicators of Compromise
- CreateModelVersion requests where the authenticated user's identity does not match the owner of the referenced run_id or model_id.
- GET /model-versions/get-artifact responses returning files whose underlying storage path belongs to a different user's experiment or logged-model directory.
- New model versions whose source URI resolves outside the caller's own experiment or model artifact roots.
Detection Strategies
- Correlate MLflow audit logs across CreateModelVersion and GetModelVersionArtifact calls, flagging chains where the source run or model belongs to a different principal than the registered model owner.
- Parse the source field of newly created model versions and compare its artifact path against the caller's authorized experiments and logged models.
- Alert on 2xx responses to /api/2.0/mlflow/model-versions/create when the request body contains a run_id or model_id that the caller lacks READ on in the MLflow permissions store.
Monitoring Recommendations
- Forward MLflow server access logs and the auth database to a centralized SIEM for cross-user access pattern analysis.
- Track the version distribution of MLflow servers across the environment and alert on any instance running below 3.15.0.
- Baseline per-user artifact download volume and rate; investigate deviations that follow model version creation events.
How to Mitigate CVE-2026-69148
Immediate Actions Required
- Upgrade all MLflow tracking servers to version 3.15.0 or later.
- Inventory existing model versions and validate that each source URI belongs to a run or logged model owned by, or explicitly shared with, the registering user.
- Rotate any secrets, tokens, or credentials that may have been stored inside experiment artifacts on multi-tenant MLflow deployments.
Patch Information
The fix is included in MLflow 3.15.0 via Pull Request #24293 and commit 4bb7474. Full advisory details are available in GHSA-gqch-g4w5-7qcw. The patch adds validate_can_create_model_version(), enforcing READ on run_id and model_id at model version creation time.
Workarounds
- Restrict CreateModelVersion privileges to a small set of trusted service accounts until the upgrade is complete.
- Place MLflow behind a reverse proxy that inspects /model-versions/create payloads and rejects requests referencing run_id or model_id values outside the caller's namespace.
- Isolate tenants into separate MLflow instances with dedicated artifact stores where cross-tenant registration is not required.
# Upgrade MLflow to the patched release
pip install --upgrade 'mlflow>=3.15.0'
# Verify the running server version
mlflow --version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

