On August 19, 2026, CISA added CVE-2026-64849, a Server-Side Request Forgery (SSRF) vulnerability in MLflow, to its Known Exploited Vulnerabilities (KEV) Catalog based on evidence of active exploitation. This is not a theoretical risk — threat actors are already abusing this flaw in the wild, and CISA's language is unambiguous: this vulnerability class is a frequent attack vector for malicious cyber actors and poses significant risk to the federal enterprise.
Under Binding Operational Directive (BOD) 26-04 — Prioritizing Security Updates Based on Risk, all Federal Civilian Executive Branch (FCEB) agencies are required to prioritize rapid remediation of CVEs listed in the KEV Catalog. If you operate in the federal space, the clock is running. If you're in the private sector, treat this with the same urgency — KEV listings are the single most reliable leading indicator of vulnerabilities that will show up in ransomware affiliate playbooks and initial-access broker tooling within weeks.
MLflow is the de facto open-source standard for ML lifecycle management — experiment tracking, model registry, and model serving. It sits inside data science pipelines at an enormous number of enterprises, frequently deployed with minimal hardening, default configurations, and direct access to cloud credentials, model artifacts, and internal data stores. That combination — high-value positioning and historically weak deployment hygiene — is exactly why attackers are hitting it.
Technical Analysis
What Is CVE-2026-64849?
CVE-2026-64849 is a Server-Side Request Forgery vulnerability in the MLflow tracking server. SSRF flaws allow an attacker to coerce the vulnerable server into making HTTP requests to arbitrary destinations — destinations the attacker cannot reach directly but the server can.
In the MLflow context, the attack surface is the tracking server's handling of user-supplied URIs in API requests — parameters such as artifact locations, model source URIs, and registry references. An attacker who can reach the MLflow REST API (commonly on TCP/5000) can supply a crafted URI that causes the MLflow server process to issue outbound requests to attacker-chosen targets.
Why This Is Dangerous in Practice
From a defender's perspective, the exploitation chain typically looks like this:
- Reconnaissance — Attacker scans for exposed MLflow instances (default port 5000, frequently internet-facing or reachable from low-trust network segments). MLflow's default deployment has no authentication unless a reverse proxy or plugin adds it.
- SSRF trigger — Attacker submits a crafted API request (e.g., to model registry or artifact endpoints) containing a malicious URI pointing at an internal target.
- Internal pivot — The MLflow server, running with the network reach of its host, fetches the attacker-specified URL. Prime targets include:
- Cloud instance metadata services —
http://169.254.169.254/latest/meta-data/(AWS),http://metadata.google.internal(GCP),http://169.254.169.254/metadata/instance(Azure) — yielding temporary IAM credentials. - Internal services — Kubernetes API servers, unauthenticated Redis/Elasticsearch, internal admin consoles.
- Local services —
http://127.0.0.1:<port>endpoints bound to localhost that assume trusted-only access.
- Cloud instance metadata services —
- Credential theft / escalation — Stolen cloud credentials are replayed from attacker infrastructure, converting a web-layer bug into full cloud account compromise.
Exploitation Status
- CISA KEV: Confirmed — added August 19, 2026
- In-the-wild exploitation: Confirmed by CISA (the sole criterion for KEV inclusion)
- Federal mandate: BOD 26-04 remediation requirement applies to all FCEB agencies
The typical KEV remediation window under BOD directives is aggressive — historically two to three weeks from listing for standard CVEs, and shorter for those used in known campaigns. Check the KEV catalog entry for the exact due date applicable to your agency.
Affected Deployments
Any organization running an internet-accessible or internally exposed MLflow tracking server should assume exposure until version verification is complete. Highest-risk profiles:
- MLflow servers exposed directly to the internet on TCP/5000 (Shodan shows thousands of these at any given time)
- MLflow deployed in cloud VPCs with IMDSv1 enabled on the host (AWS) or unrestricted metadata access
- MLflow containers running with broad network policies and cloud IAM roles attached
- Data science platforms (Databricks Community Edition-style self-hosting, Kubeflow-adjacent deployments) embedding MLflow without authentication
Detection & Response
SSRF exploitation leaves two primary forensic footprints: the inbound malicious request (crafted URI in the API call) and the anomalous outbound connection from the MLflow process itself. The outbound side is your highest-fidelity signal — a Python/MLflow process should essentially never connect to 169.254.169.254 on behalf of a request, and it should rarely connect to arbitrary internal RFC1918 destinations outside its expected artifact storage (S3, ADLS, GCS, or your defined artifact repo).
Sigma Rules
The rules below target the two highest-fidelity behaviors: the MLflow host process reaching cloud metadata endpoints, and the MLflow server process spawning shells (post-exploitation behavior observed when SSRF leads to deeper compromise).
---
title: MLflow Server Process Connecting to Cloud Metadata Service
id: 9b2c4d71-6a3e-4f58-b1c7-2d8e5f9a3c41
status: experimental
description: Detects the MLflow tracking server process (Python/Gunicorn) initiating network connections to cloud instance metadata endpoints, a strong indicator of SSRF exploitation via CVE-2026-64849.
references:
- https://www.cisa.gov/news-events/alerts/2026/08/19/cisa-adds-one-known-exploited-vulnerability-catalog
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.initial_access
- attack.t1190
- attack.credential_access
- attack.t1552.005
logsource:
category: network_connection
product: linux
detection:
selection_image:
Image|contains:
- 'python'
- 'gunicorn'
- 'mlflow'
selection_dest:
DestinationIp:
- '169.254.169.254'
- '100.100.100.200'
DestinationHostname|contains:
- 'metadata.google.internal'
condition: selection_image and selection_dest
falsepositives:
- Legitimate MLflow artifact-store SDK calls to metadata for credential refresh (rare; typically made by cloud SDK processes, correlate with expected automation)
level: critical
---
title: MLflow Server Process Spawning Shell or Download Utility
id: 3f7a1e92-8c4d-4b6a-9e15-7c2d4f8a1b53
status: experimental
description: Detects shells or command-and-download utilities spawned as child processes of the MLflow tracking server, indicating post-exploitation activity following SSRF or related compromise of CVE-2026-64849.
references:
- https://www.cisa.gov/news-events/alerts/2026/08/19/cisa-adds-one-known-exploited-vulnerability-catalog
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.execution
- attack.t1059.004
- attack.t1105
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|contains:
- 'python'
- 'gunicorn'
selection_parent_cmdline:
ParentCommandLine|contains:
- 'mlflow'
- 'mlruns'
selection_child:
Image|endswith:
- '/bash'
- '/sh'
- '/dash'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/python'
- '/perl'
condition: selection_parent and selection_parent_cmdline and selection_child
falsepositives:
- MLflow model serving flavors that shell out for environment builds (conda/pip invocations) — filter on shell and network-utility children specifically
level: high
---
title: Suspicious URI Targets in MLflow API Requests (Proxy/WAF)
id: 6d1e8a44-2b7f-4c93-a5d2-9f4c6b1e7a28
status: experimental
description: Detects HTTP requests to MLflow API endpoints containing URIs referencing cloud metadata services or loopback/link-local addresses, consistent with SSRF probe and exploit attempts against CVE-2026-64849.
references:
- https://www.cisa.gov/news-events/alerts/2026/08/19/cisa-adds-one-known-exploited-vulnerability-catalog
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.initial_access
- attack.t1190
logsource:
category: webserver
detection:
selection_path:
cs-uri|contains:
- '/api/2.0/mlflow/'
- '/api/2.0/preview/mlflow/'
selection_payload:
cs-uri-query|contains:
- '169.254.169.254'
- 'metadata.google.internal'
- '100.100.100.200'
- '127.0.0.1'
- '0.0.0.0'
- 'localhost'
- '[::1]'
- 'file://'
- 'dict://'
- 'gopher://'
condition: selection_path and selection_payload
falsepositives:
- Internal health-check tooling misconfigured to pass loopback references — tune to your environment
level: high
KQL — Microsoft Sentinel / Defender
This query hunts for the outbound exploitation signal: MLflow hosts connecting to cloud metadata endpoints, plus inbound requests carrying SSRF payloads. It assumes Syslog/CEF ingestion of host telemetry and WAF/reverse-proxy logs into CommonSecurityLog.
// Hunt 1: Outbound connections from MLflow hosts to cloud metadata services
let MetadataIPs = dynamic(["169.254.169.254", "100.100.100.200"]);
let MetadataHosts = dynamic(["metadata.google.internal"]);
union isfuzzy=true
(DeviceNetworkEvents
| where RemoteIP in (MetadataIPs) or RemoteUrl has_any (MetadataHosts)
| where InitiatingProcessFileName has_any ("python", "gunicorn")
or InitiatingProcessCommandLine has "mlflow"
| project TimeGenerated=Timestamp, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort),
(CommonSecurityLog
| where DestinationIP in (MetadataIPs) or DestinationHostName has_any (MetadataHosts)
| where ApplicationProtocol has "http"
| project TimeGenerated, SourceHostName, SourceIP, DestinationIP,
DestinationHostName, RequestURL, RequestMethod)
| order by TimeGenerated desc;
// Hunt 2: Inbound SSRF probes against MLflow API endpoints (WAF/proxy logs)
CommonSecurityLog
| where RequestURL has "/api/2.0/mlflow/" or RequestURL has "/api/2.0/preview/mlflow/"
| where RequestURL has_any ("169.254.169.254", "metadata.google.internal", "127.0.0.1",
"localhost", "file://", "dict://", "gopher://", "[::1]")
| summarize Attempts=count(), DistinctTargets=dcount(RequestURL)
by SourceIP, RequestMethod, bin(TimeGenerated, 1h)
| where Attempts > 2
| order by TimeGenerated desc;
// Hunt 3: MLflow server spawning shells (post-exploitation)
union isfuzzy=true
(DeviceProcessEvents
| where InitiatingProcessCommandLine has_any ("mlflow", "gunicorn")
| where FileName in~ ("bash", "sh", "dash", "curl", "wget", "nc", "ncat")
| project TimeGenerated=Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessCommandLine, AccountName),
(Syslog
| where SyslogMessage has "mlflow"
and SyslogMessage has_any ("/bin/bash", "/bin/sh", "curl ", "wget ")
| project TimeGenerated, HostName, ProcessName, SyslogMessage)
| order by TimeGenerated desc;
Velociraptor VQL
Use this artifact across your Linux fleet to identify MLflow server processes with anomalous network connections — particularly to metadata services or unexpected internal destinations.
-- Hunt: MLflow processes with suspicious network connections (SSRF indicator)
SELECT Pid, Ppid, Name, CommandLine, Username,
netstat().Pid AS NPid,
netstat().LocalAddr AS LocalAddress,
netstat().LocalPort AS LocalPort,
netstat().RemoteAddr AS RemoteAddress,
netstat().RemotePort AS RemotePort,
netstat().Status AS ConnStatus
FROM pslist()
WHERE CommandLine =~ '(?i)mlflow|gunicorn'
AND (
netstat().RemoteAddr =~ '169\\.254\\.169\\.254'
OR netstat().RemoteAddr =~ '100\\.100\\.100\\.200'
OR netstat().RemoteAddr =~ '^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)'
)
AND netstat().Status =~ 'ESTABLISHED'
Tuning note: The RFC1918 leg of that VQL will be noisy if your MLflow server legitimately reaches an internal artifact store or database. Baseline your known-good destinations (artifact repo, backing DB) and exclude them — the residual is what you investigate.
Bash — Exposure Verification and Hardening Script
Run this on suspected MLflow hosts to enumerate exposure, verify the running version, check for metadata-access indicators, and apply immediate compensating controls while you schedule the upgrade.
#!/bin/bash
# CVE-2026-64849 - MLflow SSRF exposure check and interim hardening
# Security Arsenal - run as root on the MLflow host
echo "=== [1] Identify running MLflow processes ==="
ps aux | grep -iE 'mlflow|gunicorn' | grep -v grep
echo "=== [2] Report installed MLflow version ==="
for PYBIN in python3 python; do
$PYBIN -c "import mlflow; print('mlflow', mlflow.__version__)" 2>/dev/null
done
pip3 list 2>/dev/null | grep -i mlflow
echo "=== [3] Check listening exposure (is 5000 bound to 0.0.0.0?) ==="
ss -tlnp | grep -E ':5000\b'
echo "=== [4] Check for suspicious outbound connections from MLflow PID ==="
MLPID=$(pgrep -f 'mlflow server' | head -1)
if [ -n "$MLPID" ]; then
echo "MLflow server PID: $MLPID"
ss -tnp | grep "pid=$MLPID" || echo "No active connections from MLflow PID"
echo "--- Metadata access attempts (last 24h, conntrack/netfilter logs if present) ---"
journalctl --since "-24h" 2>/dev/null | grep -E '169\.254\.169\.254' | tail -20
else
echo "No running mlflow server process found"
fi
echo "=== [5] Check cloud metadata reachability + IMDS enforcement (AWS) ==="
TOKEN=$(curl -s -m 2 -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 60")
if [ -n "$TOKEN" ]; then
echo "[INFO] IMDSv2 token endpoint responsive. Checking if v1 is still allowed..."
curl -s -m 2 http://169.254.169.254/latest/meta-data/ >/dev/null \
&& echo "[WARN] IMDSv1 is ENABLED - enforce IMDSv2 to blunt SSRF credential theft" \
|| echo "[OK] IMDSv1 appears disabled"
echo "To enforce IMDSv2:"
echo " aws ec2 modify-instance-metadata-options --instance-id <id> --http-tokens required"
else
echo "[INFO] Not an AWS EC2 host or metadata unreachable"
fi
echo "=== [6] Interim mitigation: block metadata egress for the mlflow user ==="
MLUSER=$(ps -o user= -p "$MLPID" 2>/dev/null)
if [ -n "$MLUSER" ]; then
iptables -C OUTPUT -m owner --uid-owner "$MLUSER" -d 169.254.169.254 -j DROP 2>/dev/null \
|| iptables -A OUTPUT -m owner --uid-owner "$MLUSER" -d 169.254.169.254 -j DROP
iptables -C OUTPUT -m owner --uid-owner "$MLUSER" -d 100.100.100.200 -j DROP 2>/dev/null \
|| iptables -A OUTPUT -m owner --uid-owner "$MLUSER" -d 100.100.100.200 -j DROP
echo "[OK] Egress to metadata services dropped for user: $MLUSER (interim control)"
else
echo "[SKIP] Could not determine mlflow user"
fi
echo "=== [7] Upgrade MLflow to the patched release ==="
echo "Run: pip install --upgrade mlflow"
echo "Then restart the service and re-run sections 1-4 to verify."
echo "=== [8] Confirm authentication is enforced ==="
echo "MLflow has NO built-in auth by default. Place it behind an authenticating"
echo "reverse proxy (nginx/oauth2-proxy) or the MLflow auth plugin, and never"
echo "bind to 0.0.0.0 on untrusted segments."
Remediation
1. Patch Immediately
Upgrade MLflow to the patched release addressing CVE-2026-64849. Verify your running version per the script above and consult the CISA KEV catalog entry and the MLflow project's security advisory/release notes for the exact fixed version number applicable to your deployment:
- CISA Alert: https://www.cisa.gov/news-events/alerts/2026/08/19/cisa-adds-one-known-exploited-vulnerability-catalog
- CISA KEV Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- MLflow releases: https://github.com/mlflow/mlflow/releases
pip install --upgrade mlflow
# Containerized deployments: rebuild from the patched base image and redeploy
# Verify post-upgrade:
python3 -c "import mlflow; print(mlflow.__version__)"
Federal agencies: BOD 26-04 mandates remediation of KEV-listed CVEs within the directive's specified timeline. Confirm the due date on the KEV entry, document your remediation, and report per your agency's BOD compliance procedures.
2. Compensating Controls (If You Cannot Patch Today)
- Remove internet exposure. No MLflow instance should be directly internet-reachable. Audit external attack-surface data (Shodan, Censys, your ASM platform) for port 5000 exposure now.
- Enforce egress filtering. The MLflow host should only reach its defined artifact store and backing database. Explicitly block
169.254.169.254(AWS/Azure),metadata.google.internal(GCP), and100.100.100.200(Alibaba) for the MLflow service account. - Enforce IMDSv2 on AWS (
--http-tokens required) and restrict metadata access on GCP/Azure. This doesn't fix the SSRF, but it breaks the highest-impact exploitation path — IAM credential theft. - Add authentication. MLflow ships without auth by default. Front it with an authenticating reverse proxy (nginx + OIDC, oauth2-proxy) or deploy the MLflow authentication plugin. Unauthenticated + internet-facing + SSRF is the exact combination being exploited.
- Bind to localhost (
--host 127.0.0.1) and expose only through the authenticated proxy.
3. Assume Compromise and Hunt
Because exploitation is confirmed active, patching alone is insufficient for any instance that was exposed before remediation. For every MLflow host that was reachable from untrusted networks:
- Review HTTP access logs for API requests containing metadata IPs, loopback addresses, or non-HTTP URI schemes (
file://,gopher://,dict://) - Review cloud audit logs (CloudTrail, GCP Audit Logs, Azure Activity Log) for IAM credential use from IP addresses outside your known infrastructure — stolen instance credentials replayed from attacker infrastructure is the signature outcome of this attack
- Check the MLflow host for unexpected child processes, cron entries, systemd units, or new user accounts
- If metadata-service access is confirmed in logs, rotate all IAM credentials/roles associated with that host and treat it as a credential-theft incident
4. Structural Fix
This KEV addition should be the forcing function for MLops governance: inventory every MLflow (and adjacent tooling — Jupyter, Kubeflow, Airflow) deployment, bring them under your vulnerability management program's SLA, and enforce baseline hardening (auth required, no direct internet exposure, restricted egress, dedicated least-privilege service accounts). AI/ML infrastructure has been operating outside traditional security controls at most organizations; attackers have noticed.
The Bottom Line
CVE-2026-64849 in the KEV catalog means one thing: someone, somewhere, is already losing cloud credentials to this bug. The exploitation path — unauthenticated SSRF to metadata-service credential theft — is fast, reliable, and requires no sophistication. If you run MLflow, verify your version and exposure today, hunt for the outbound indicators above, and treat any pre-patch exposure as a potential credential-compromise incident, not just a patching ticket.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.