Every CVE Search/ Get API key

CVE-2026-116690

MLflow: Arbitrary file read on unauthenticated MLflow servers via prompt model version source

7.5 HighFix available

MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. From 3.10.0 until 3.17.0, the prompt branch in _create_model_version() accepts schemeless relative sources because path validation runs only when a source has a URL scheme, and mlflow.prompt.is_prompt is interpreted by tag presence rather than a true value. A remote caller can store a server-local path as the model version artifact location and use /api/2.0/mlflow/model-versions/get-artifact to read files accessible to the MLflow server process. Default unauthenticated servers require no privileges, while basic-auth deployments are exposed to authenticated users who can create registered models. This issue is fixed in version 3.17.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

1.80%Up 1.2 points since Oct 28, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

MLflow: Arbitrary file read on unauthenticated MLflow servers via prompt model version source

MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. From 3.10.0 until 3.17.0, the prompt branch in _create_model_version() accepts schemeless relative sources because path validation runs only when a source has a URL scheme, and mlflow.prompt.is_prompt is interpreted by tag presence rather than a true value. A remote caller can store a server-local path as the model version artifact location and use /api/2.0/mlflow/model-versions/get-artifact to read files accessible to the MLflow server process. Default unauthenticated servers require no privileges, while basic-auth deployments are exposed to authenticated users who can create registered models. This issue is fixed in version 3.17.0.

Record
CVE-2026-116690
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
EUVDEUVD-2026-111362 7.5

MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. From 3.10.0 until 3.17.0, the prompt branch in _create_model_version() accepts schemeless relative sources because path validation runs only when a source has a URL scheme, and mlflow.prompt.is_prompt is interpreted by tag presence rather than a true value. A remote caller can store a server-local path as the model version artifact location and use /api/2.0/mlflow/model-versions/get-artifact to read files accessible to the MLflow server process. Default unauthenticated servers require no privileges, while basic-auth deployments are exposed to authenticated users who can create registered models. This issue is fixed in version 3.17.0.

Record
EUVD-2026-111362
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-m65p-9j7q-6w33 7.5

MLflow vulnerable to arbitrary file read on unauthenticated servers via prompt model version source

Summary

On MLflow tracking servers running without authentication, which is the default for mlflow server, a remote attacker can read arbitrary files from the server’s filesystem by creating a model version tagged as a prompt whose source is a schemeless local path.

The fix for CVE-2026-2614 in 3.10.0 added a prompt-specific branch to the CreateModelVersion handler that rejects file:// URIs and absolute paths but runs path validation only when the source carries a URL scheme. A schemeless value such as ../../etc, a plain relative name, ., a percent-encoded path, or a Windows drive-letter path is therefore stored unchanged as the model version’s artifact location, and the model-versions/get-artifact endpoint later serves files from it with the privileges of the server process. The tag check also keyed on the presence of the mlflow.prompt.is_prompt tag rather than its value, so a false value still selected the weaker branch.

Servers using --app-name basic-auth are also affected: any authenticated user can create a registered model, so a low-privilege account can use this to read the authentication database, including the admin password hash.

Affected: MLflow 3.10.0 through 3.16.1. Fixed in 3.17.0 by mlflow/mlflow#25870, which accepts only MLflow’s own placeholder sources for prompt versions and requires the prompt tag to be true.

Details

When creating a model version with the mlflow.prompt.is_prompt tag set to true, the request is handled by the prompt branch in _create_model_version().

mlflow/server/handlers.py:2674-2690:

is_prompt = _is_prompt_request(request_message)
if is_prompt:
    source = request_message.source
    parsed = urllib.parse.urlparse(source)
    if parsed.scheme == "file" or (parsed.scheme == "" and source.startswith("/")):
        raise MlflowException(...)
    if parsed.scheme:
        _validate_non_local_source_contains_relative_paths(source)
else:
    if request_message.model_id:
        _validate_source_model(request_message.source, request_message.model_id)
    else:
        _validate_source_run(request_message.source, request_message.run_id)

The prompt branch does not call _validate_source_run(), _validate_source_model(), or _validate_non_local_source_contains_relative_paths() for schemeless relative paths.

The artifact-read sink later trusts the stored source:

mlflow/server/handlers.py:2765-2782:

def get_model_version_artifact_handler():
    name = request.args.get("name")
    version = request.args.get("version")
    path = request.args["path"]
    path = validate_path_is_safe(path)
    artifact_uri = _get_model_registry_store().get_model_version_download_uri(name, version)
    ...
    else:
        artifact_repo = get_artifact_repository(artifact_uri)
        artifact_path = path

    return _send_artifact(artifact_repo, artifact_path)

_send_artifact() calls artifact_repository.download_artifacts(path) and serves the resulting local file with send_file().

PoC

Prerequisite: A reachable MLflow tracking server with model registry endpoints enabled.

  1. Create a sentinel file on the server:
printf 'MLFLOW_PWNED_SENTINEL_REPORT' > /tmp/sentinel-mlflow.txt
  1. Send the following requests to the MLflow server to exploit the traversal:

First, create a registered model:

POST /api/2.0/mlflow/registered-models/create HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/json

{"name": "pwned-model"}

Next, create a prompt-tagged model version with the malicious relative source ../../../tmp:

POST /api/2.0/mlflow/model-versions/create HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/json

{
  "name": "pwned-model",
  "source": "../../../tmp",
  "tags": [{"key": "mlflow.prompt.is_prompt", "value": "true"}]
}

Finally, retrieve the arbitrary file via the artifact download endpoint by supplying the target filename in the path…

Record
GHSA-m65p-9j7q-6w33
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
NVD 7.5

MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. From 3.10.0 until 3.17.0, the prompt branch in _create_model_version() accepts schemeless relative sources because path validation runs only when a source has a URL scheme, and mlflow.prompt.is_prompt is interpreted by tag presence rather than a true value. A remote caller can store a server-local path as the model version artifact location and use /api/2.0/mlflow/model-versions/get-artifact to read files accessible to the MLflow server process. Default unauthenticated servers require no privileges, while basic-auth deployments are exposed to authenticated users who can create registered models. This issue is fixed in version 3.17.0.

Record
CVE-2026-116690
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
OSV 7.5

MLflow: Arbitrary file read on unauthenticated MLflow servers via prompt model version source

MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. From 3.10.0 until 3.17.0, the prompt branch in _create_model_version() accepts schemeless relative sources because path validation runs only when a source has a URL scheme, and mlflow.prompt.is_prompt is interpreted by tag presence rather than a true value. A remote caller can store a server-local path as the model version artifact location and use /api/2.0/mlflow/model-versions/get-artifact to read files accessible to the MLflow server process. Default unauthenticated servers require no privileges, while basic-auth deployments are exposed to authenticated users who can create registered models. This issue is fixed in version 3.17.0.

Record
CVE-2026-116690
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02
OSVGHSA-m65p-9j7q-6w33 7.5

MLflow vulnerable to arbitrary file read on unauthenticated servers via prompt model version source

Summary

On MLflow tracking servers running without authentication, which is the default for mlflow server, a remote attacker can read arbitrary files from the server’s filesystem by creating a model version tagged as a prompt whose source is a schemeless local path.

The fix for CVE-2026-2614 in 3.10.0 added a prompt-specific branch to the CreateModelVersion handler that rejects file:// URIs and absolute paths but runs path validation only when the source carries a URL scheme. A schemeless value such as ../../etc, a plain relative name, ., a percent-encoded path, or a Windows drive-letter path is therefore stored unchanged as the model version’s artifact location, and the model-versions/get-artifact endpoint later serves files from it with the privileges of the server process. The tag check also keyed on the presence of the mlflow.prompt.is_prompt tag rather than its value, so a false value still selected the weaker branch.

Servers using --app-name basic-auth are also affected: any authenticated user can create a registered model, so a low-privilege account can use this to read the authentication database, including the admin password hash.

Affected: MLflow 3.10.0 through 3.16.1. Fixed in 3.17.0 by mlflow/mlflow#25870, which accepts only MLflow’s own placeholder sources for prompt versions and requires the prompt tag to be true.

Details

When creating a model version with the mlflow.prompt.is_prompt tag set to true, the request is handled by the prompt branch in _create_model_version().

mlflow/server/handlers.py:2674-2690:

is_prompt = _is_prompt_request(request_message)
if is_prompt:
    source = request_message.source
    parsed = urllib.parse.urlparse(source)
    if parsed.scheme == "file" or (parsed.scheme == "" and source.startswith("/")):
        raise MlflowException(...)
    if parsed.scheme:
        _validate_non_local_source_contains_relative_paths(source)
else:
    if request_message.model_id:
        _validate_source_model(request_message.source, request_message.model_id)
    else:
        _validate_source_run(request_message.source, request_message.run_id)

The prompt branch does not call _validate_source_run(), _validate_source_model(), or _validate_non_local_source_contains_relative_paths() for schemeless relative paths.

The artifact-read sink later trusts the stored source:

mlflow/server/handlers.py:2765-2782:

def get_model_version_artifact_handler():
    name = request.args.get("name")
    version = request.args.get("version")
    path = request.args["path"]
    path = validate_path_is_safe(path)
    artifact_uri = _get_model_registry_store().get_model_version_download_uri(name, version)
    ...
    else:
        artifact_repo = get_artifact_repository(artifact_uri)
        artifact_path = path

    return _send_artifact(artifact_repo, artifact_path)

_send_artifact() calls artifact_repository.download_artifacts(path) and serves the resulting local file with send_file().

PoC

Prerequisite: A reachable MLflow tracking server with model registry endpoints enabled.

  1. Create a sentinel file on the server:
printf 'MLFLOW_PWNED_SENTINEL_REPORT' > /tmp/sentinel-mlflow.txt
  1. Send the following requests to the MLflow server to exploit the traversal:

First, create a registered model:

POST /api/2.0/mlflow/registered-models/create HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/json

{"name": "pwned-model"}

Next, create a prompt-tagged model version with the malicious relative source ../../../tmp:

POST /api/2.0/mlflow/model-versions/create HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/json

{
  "name": "pwned-model",
  "source": "../../../tmp",
  "tags": [{"key": "mlflow.prompt.is_prompt", "value": "true"}]
}

Finally, retrieve the arbitrary file via the artifact download endpoint by supplying the target filename in the path…

Record
GHSA-m65p-9j7q-6w33
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
mlflow
PyPI
3.10.0 up to 3.17.0
3.17.0
mlflow
PyPI
3.10.0 up to 3.17.0, plus listed versions
3.10.13.11.03.11.0rc03.11.0rc13.11.1
Show 10 moreShow less
3.12.03.12.0rc03.13.03.13.0rc03.14.03.15.03.15.13.15.23.16.03.16.1
3.17.0

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
NucleiMLflow 3.10.0-3.16.1 - Arbitrary File Read

History

History
RecordedChangedSources
exploits, factsNuclei
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-116690 is a high vulnerability (CVSS 7.5) in Mlflow, published October 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 1.80%, the 78th percentile. Fixed in mlflow 3.17.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open