CVE-2024-1558
Executive Summary
CVE-2024-1558 is a high-severity path traversal vulnerability in the MLflow machine learning lifecycle platform. The flaw resides in the _create_model_version() function within server/handlers.py, where improper validation of the source parameter allows an unauthenticated attacker to read arbitrary files from the server's filesystem. By crafting a source value that bypasses the _validate_non_local_source_contains_relative_paths(source) check—specifically by using unquoted URL characters—an attacker can traverse directories and access sensitive files. The vulnerability is exploitable via the /model-versions/get-artifact endpoint, leading to unauthorized disclosure of configuration files, credentials, or other sensitive data. The CVSS score is 7.5 (High), with a vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. No public exploit code or Nuclei template is available, but the vulnerability is considered publicly known. The patch was released in MLflow version 2.9.0.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
MLflow is a Python package distributed via PyPI. Organizations using MLflow in their MLOps pipelines should verify their installed version and update to 2.9.0 or later. The vulnerability does not directly affect the supply chain of MLflow itself, but it can be used to compromise the host system, potentially leading to further supply chain risks if the server is used to store or distribute models.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Attack Vector (AV): Network – The vulnerability is exploitable remotely.
- Attack Complexity (AC): Low – No special conditions are required.
- Privileges Required (PR): None – No authentication is needed.
- User Interaction (UI): None – No user action is required.
- Scope (S): Unchanged – The exploit does not affect other components.
- Confidentiality (C): High – Sensitive files can be read.
- Integrity (I): None – No file modification is possible.
- Availability (A): None – No denial of service.
Threat Level: High. The vulnerability allows unauthenticated remote file read, which can lead to exposure of credentials, API keys, or other sensitive data.
Deep Dive & Mechanics
The vulnerability exists in the _create_model_version() function in server/handlers.py. The function receives a source parameter that specifies the location of the model artifact. To prevent path traversal, the code calls _validate_non_local_source_contains_relative_paths(source), which checks for relative path components like ... However, the validation fails to account for URL-encoded characters. An attacker can encode the path traversal sequence as %2e%2e%2f (which decodes to ../) to bypass the check. After validation, the original (unquoted) source value is used to create the model version. When the /model-versions/get-artifact handler is later invoked, it uses this unvalidated path to read files, allowing the attacker to read arbitrary files on the server.
Key Code Flow:
- Attacker sends a request to create a model version with
sourceset to%2e%2e%2f%2e%2e%2fetc%2fpasswd. - The
_validate_non_local_source_contains_relative_paths()function checks the decoded string (../../etc/passwd) and blocks it if it contains... - However, the validation is applied to the decoded string, but the original encoded string is stored and used later. The attacker can craft a payload that passes the check but still results in path traversal when decoded later.
- The
/model-versions/get-artifactendpoint then reads the file at the path derived from the storedsource, leading to arbitrary file read.
Vulnerable vs. Patched Code
Vulnerable Code (pre-2.9.0):
def _create_model_version(self, request):
source = request.json.get("source")
# Validation that can be bypassed with URL encoding
_validate_non_local_source_contains_relative_paths(source)
# Original source stored and used later
model_version = self._store.create_model_version(source=source, ...)
Patched Code (2.9.0):
def _create_model_version(self, request):
source = request.json.get("source")
# Decode URL-encoded characters before validation
decoded_source = urllib.parse.unquote(source)
_validate_non_local_source_contains_relative_paths(decoded_source)
# Use the decoded source for storage
model_version = self._store.create_model_version(source=decoded_source, ...)
The patch ensures that URL decoding is performed before validation, preventing the bypass.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A vulnerable MLflow server (version < 2.9.0) running with default settings.
- Network access to the server's API endpoint (typically port 5000).
Exploitation Steps:
- Identify the MLflow server endpoint, e.g.,
http://target:5000. - Send a POST request to
/api/2.0/mlflow/model-versions/createwith a craftedsourceparameter:{ "name": "test-model", "source": "%2e%2e%2f%2e%2e%2fetc%2fpasswd" } - The server will create a model version with the malicious source.
- Retrieve the file by sending a GET request to
/model-versions/get-artifact?name=test-model&version=1&path=artifact(or similar endpoint). The exact path may vary; the attacker may need to experiment with the endpoint to read the file.
Note: No public exploit code is available, but the above steps demonstrate the attack.
Blue Team
Detection:
- Monitor API logs for unusual
sourceparameters containing URL-encoded characters like%2e,%2f, or%00. - Alert on multiple failed model version creation attempts with different
sourcevalues. - Use the YARA and Sigma rules provided in the Detection Engineering section.
Hunting:
- Search for model versions with
sourcefields that contain encoded path traversal sequences. - Review server logs for requests to
/model-versions/get-artifactthat reference model versions with suspicious sources.
Lab Setup:
- Deploy a vulnerable MLflow instance (e.g., version 2.8.0) in a sandboxed environment.
- Use tools like Burp Suite or curl to send crafted requests.
- Monitor logs and network traffic to observe the attack.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP POST requests to
/api/2.0/mlflow/model-versions/createwithsourcecontaining URL-encoded path traversal sequences (e.g.,%2e%2e%2f). - HTTP GET requests to
/model-versions/get-artifactwith parameters referencing model versions created with suspicious sources.
- HTTP POST requests to
- File System IOCs:
- Unexpected files read from the server (e.g.,
/etc/passwd,/etc/shadow, application config files).
- Unexpected files read from the server (e.g.,
- Log IOCs:
- MLflow server logs showing model version creation with
sourcevalues containing encoded characters. - Error logs indicating attempts to read files outside the allowed artifact directory.
- MLflow server logs showing model version creation with
Detection Engineering
YARA Rule
rule CVE_2024_1558_MLflow_Path_Traversal {
meta:
description = "Detects path traversal attempts in MLflow source parameter"
author = "Valters IT"
date = "2024-10-27"
reference = "CVE-2024-1558"
strings:
$encoded_dotdot = /%2e%2e%2f|%2e%2e%5c|\.\.\/|\.\.\\/
$source_param = "source"
condition:
$source_param and $encoded_dotdot
}
Sigma Rule
title: MLflow Path Traversal via Source Parameter
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects attempts to exploit CVE-2024-1558 by sending URL-encoded path traversal in the source parameter
author: Valters IT
logsource:
category: webserver
product: mlflow
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/api/2.0/mlflow/model-versions/create'
cs-uri-query|contains:
- '%2e%2e%2f'
- '%2e%2e%5c'
condition: selection
falsepositives:
- Legitimate use of encoded characters in model source paths (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-1558 MLflow Path Traversal Attempt"; flow:to_server; content:"POST"; http_method; content:"/api/2.0/mlflow/model-versions/create"; http_uri; content:"%2e%2e%2f"; http_client_body; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade MLflow to version 2.9.0 or later. This is the only complete fix.
- If upgrade is not possible, apply a virtual patch using a Web Application Firewall (WAF) to block requests containing
%2e%2eor..in thesourceparameter. - Restrict network access to the MLflow API endpoint to trusted IPs only.
Long-term Measures:
- Implement input validation and sanitization for all user-supplied parameters, especially those used in file paths.
- Use a reverse proxy (e.g., Nginx) to filter malicious requests before they reach the MLflow server.
- Regularly audit and update dependencies.
Workarounds:
- Disable the model version creation endpoint if not needed.
- Use a custom authentication proxy to require API keys for all requests.
Valters IT