CVE-2025-15381
Executive Summary
CVE-2025-15381 is a missing authorization vulnerability in the MLflow open-source platform, specifically affecting deployments using the basic-auth authentication app. When this app is enabled, the tracing and assessment endpoints are not protected by permission validators. This allows any authenticated user, including those with NO_PERMISSIONS on an experiment, to read trace information and create assessments for traces they should not have access to. The vulnerability impacts confidentiality by exposing trace metadata and integrity by allowing unauthorized creation of assessments. The CVSS score is 7.1 (High), and the EPSS score is 0.0%, indicating low exploitation likelihood at this time. No public exploit code or patch details are available.
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 affects the MLflow Python package (PyPI). Organizations using MLflow in their MLOps pipelines should verify their deployment configuration and ensure that the basic-auth app is not used in production environments without additional authorization controls.
CVSS Breakdown & Threat Level
- CVSS Score: 7.1 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low (authenticated user)
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: Low (exposure of trace metadata)
- Integrity Impact: Low (unauthorized creation of assessments)
- Availability Impact: None
Threat Level: High. While the EPSS score is low, the vulnerability is easy to exploit once authenticated, and it affects a widely used MLOps tool.
Deep Dive & Mechanics
The vulnerability lies in the basic-auth app of MLflow. When this app is enabled via mlflow server --app-name=basic-auth, the tracing and assessment endpoints are not protected by permission validators. This means that any authenticated user, regardless of their permissions on a specific experiment, can access these endpoints.
The affected endpoints include:
/api/2.0/mlflow/traces(GET) - to read trace information/api/2.0/mlflow/assessments(POST) - to create assessments
The root cause is a missing authorization check in the route handlers for these endpoints. The basic-auth app only checks for authentication (valid credentials) but does not enforce experiment-level permissions.
Vulnerable vs. Patched Code
Vulnerable Code (conceptual):
# In basic-auth app, routes are registered without permission validators
@route('/api/2.0/mlflow/traces')
def get_traces():
# Only checks authentication, not experiment permissions
user = authenticate(request)
if not user:
return 401
return get_all_traces()
Patched Code (expected):
# Patched version should include permission validators
@route('/api/2.0/mlflow/traces')
@require_permission('READ_TRACE')
def get_traces():
user = authenticate(request)
if not user:
return 401
# Check experiment-level permissions
experiment_id = request.args.get('experiment_id')
if not user.has_permission(experiment_id, 'READ_TRACE'):
return 403
return get_traces_for_experiment(experiment_id)
Exploitation & Lab Setup
Red Team
Prerequisites:
- Access to an MLflow server with
basic-authenabled - Valid credentials for any user (even with
NO_PERMISSIONS)
Exploitation Steps:
- Authenticate to the MLflow server:
curl -u username:password https://mlflow-server/api/2.0/mlflow/traces - Read trace information from any experiment:
curl -u username:password "https://mlflow-server/api/2.0/mlflow/traces?experiment_id=123" - Create unauthorized assessments:
curl -X POST -u username:password \ -H "Content-Type: application/json" \ -d '{"trace_id": "abc123", "assessment": "malicious"}' \ https://mlflow-server/api/2.0/mlflow/assessments
Blue Team
Detection:
- Monitor for unusual access to
/api/2.0/mlflow/tracesand/api/2.0/mlflow/assessmentsendpoints - Look for users with
NO_PERMISSIONSaccessing these endpoints - Check for anomalous assessment creation patterns
Mitigation:
- Disable
basic-authapp in production - Use a reverse proxy with proper authorization (e.g., OAuth2 proxy)
- Implement network segmentation to restrict access to MLflow server
- Monitor logs for unauthorized access attempts
Indicators of Compromise (IOCs)
- Network: HTTP requests to
/api/2.0/mlflow/tracesand/api/2.0/mlflow/assessmentsfrom users withNO_PERMISSIONS - Logs: MLflow access logs showing 200 responses for these endpoints from unauthorized users
- File: Unusual trace data or assessments in experiments that should be restricted
Detection Engineering
YARA Rule
rule mlflow_basic_auth_bypass {
meta:
description = "Detects MLflow basic-auth permission bypass attempts"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-15381"
strings:
$s1 = "/api/2.0/mlflow/traces" ascii wide nocase
$s2 = "/api/2.0/mlflow/assessments" ascii wide nocase
$s3 = "NO_PERMISSIONS" ascii wide nocase
condition:
any of ($s1, $s2) and $s3
}
Sigma Rule
title: MLflow Basic-Auth Permission Bypass
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects unauthorized access to MLflow tracing and assessment endpoints
author: Valters IT
date: 2025/04/10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-15381
logsource:
category: webserver
product: mlflow
detection:
selection:
cs-method:
- 'GET'
- 'POST'
cs-uri-stem:
- '/api/2.0/mlflow/traces'
- '/api/2.0/mlflow/assessments'
sc-status: 200
filter:
cs-username: 'admin'
condition: selection and not filter
falsepositives:
- Legitimate admin access
level: high
Suricata Rule
alert http any any -> any any (msg:"MLflow Basic-Auth Permission Bypass Attempt"; flow:to_server; content:"/api/2.0/mlflow/traces"; http_uri; nocase; content:"/api/2.0/mlflow/assessments"; http_uri; nocase; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the
basic-authapp if not required:mlflow server --app-name=no-auth - Implement a reverse proxy with proper authorization (e.g., OAuth2 proxy, nginx with auth_request)
- Restrict network access to the MLflow server using firewall rules
Long-term Fix:
- Apply the official patch when available from MLflow maintainers
- Upgrade to a patched version once released
- Implement experiment-level permission checks in custom authentication middleware
Workaround:
- Use MLflow's built-in permission system with a different authentication backend (e.g., LDAP, OAuth)
- Monitor logs for unauthorized access and set up alerts
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert
{/* [Security Hash: BE0889BDDC18289CD8C68C62] */}