On August 19, 2026, CISA added CVE-2026-64849 to the Known Exploited Vulnerabilities (KEV) catalog, confirming what many of us in the DFIR community suspected: a server-side request forgery (SSRF) vulnerability in MLflow is being actively exploited in the wild. If your organization runs MLflow — and given its ubiquity in MLOps pipelines, the odds are high that it does — you are now on a remediation clock driven by CISA's BOD 26-04 guidance, and more importantly, by adversaries who are already inside environments through this exact vector.
This is not a theoretical exposure. SSRF in an ML experiment tracking server is a near-perfect attacker primitive: MLflow servers routinely sit in trusted network segments, hold credentials for artifact stores (S3, Azure Blob, GCS), and — critically — run on cloud compute where they can reach the instance metadata service (IMDS). An attacker who can coerce the MLflow server into fetching arbitrary URLs can pivot from an internet-facing experiment tracking UI straight into your cloud control plane.
Technical Analysis
What Is Affected
- Product: MLflow (the open-source ML lifecycle platform from Databricks / Linux Foundation)
- Vulnerability type: Server-Side Request Forgery (CWE-918)
- Affected component: The MLflow tracking server's remote content handling, where attacker-controlled URLs passed to the server cause it to issue server-side HTTP requests and — critically — return the
response_statusandresponse_bodyto the requester
That last detail is what elevates this from a blind SSRF (useful for port scanning and request smuggling) to a full-read SSRF. The attacker doesn't just trigger requests; they receive the responses. This means direct exfiltration of:
- Cloud instance metadata —
http://169.254.169.254/latest/meta-data/iam/security-credentials/(AWS),http://metadata.google.internal(GCP),http://169.254.169.254/metadata/instance?api-version=2021-02-01(Azure). Temporary IAM credentials returned here enable full cloud pivot. - Internal HTTP services — Kubernetes API endpoints, internal dashboards, CI/CD systems, secret managers, and other services that trust the network segment MLflow lives in.
- Artifact store pre-signed or internal endpoints — MLflow's core function is brokering access to model artifacts; SSRF lets attackers ride that trust.
Attack Chain (Defender's View)
- Recon: Attacker identifies an exposed MLflow tracking server (Shodan/Censys exposure of MLflow instances is well documented — default port 5000, distinctive UI/API responses).
- SSRF trigger: A crafted request to the vulnerable endpoint supplies an internal or metadata URL.
- Server-side fetch: The MLflow server, running with its host's network privileges, issues the request.
- Response return:
response_statusandresponse_bodycome back to the attacker — IAM credentials, internal API data, secrets. - Pivot: Stolen cloud credentials are replayed from attacker infrastructure, or internal service data enables lateral movement.
Exploitation requires no authentication in default MLflow deployments, which historically ship without built-in auth — authentication is expected to come from a reverse proxy, and in our incident response experience, it frequently doesn't.
Exploitation Status
- Confirmed active exploitation in the wild (CISA KEV addition, 2026-08-19)
- Remediation is governed by CISA BOD 26-04 — Prioritizing Security Updates Based on Risk — including its Forensics Triage Requirements. Federal civilian agencies have binding deadlines; every private-sector organization should treat the KEV due date as their own.
- If mitigations cannot be applied, CISA's direction is explicit: discontinue use of the product until it can be secured.
Detection & Response
The highest-fidelity detections for SSRF exploitation target the outbound consequence, not just the inbound trigger. Your MLflow server should have a tightly bounded egress profile; any deviation is a strong signal.
Priority detection hypotheses:
- MLflow/Python processes initiating connections to link-local metadata addresses (169.254.169.254, metadata.google.internal).
- MLflow processes connecting to RFC1918 destinations that are not the expected artifact store, database, or model registry endpoints.
- Inbound HTTP requests to the MLflow API containing URL-encoded or literal internal addresses as parameters.
- Unexpected egress volume from the MLflow host (exfil via SSRF responses).
Sigma Rules
---
title: MLflow Process Connecting to Cloud Instance Metadata Service
id: 9c4e2a71-3f8b-4d5a-b7c1-2e6f8a0d1b3c
status: experimental
description: Detects the MLflow server process (or its Python interpreter) initiating a network connection to cloud instance metadata endpoints, consistent with exploitation of CVE-2026-64849 SSRF to steal IAM credentials.
references:
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?search_api_fulltext=CVE-2026-64849
- https://attack.mitre.org/techniques/T1552/005/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.credential_access
- attack.t1552.005
- cve.2026.64849
logsource:
category: network_connection
product: linux
detection:
selection:
Image|contains:
- 'python'
- 'mlflow'
- 'gunicorn'
- 'uvicorn'
DestinationIp:
- '169.254.169.254'
- '100.100.100.200'
DestinationHostname|contains:
- 'metadata.google.internal'
- 'metadata.azure.internal'
condition: selection
falsepositives:
- Legitimate cloud SDK calls from MLflow integrations refreshing credentials (validate process lineage and frequency)
level: critical
---
title: MLflow SSRF Attempt Against Internal Services via Tracking API
id: 5d1b8c34-7a2e-4f09-9c6d-8b3a1e5f2077
status: experimental
description: Detects inbound requests to an MLflow tracking server containing internal IP ranges, loopback, or link-local addresses embedded in request parameters, consistent with SSRF probing or exploitation of CVE-2026-64849.
references:
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?search_api_fulltext=CVE-2026-64849
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.initial_access
- attack.t1190
- cve.2026.64849
logsource:
category: webserver
detection:
selection_uri:
cs-uri-query|contains:
- '169.254.169.254'
- '169.254.170.2'
- 'metadata.google.internal'
- '127.0.0.1'
- 'localhost'
- '10.'
- '172.16.'
- '192.168.'
selection_body:
cs-body|contains:
- '169.254.'
- 'metadata.google.internal'
- 'http://127.'
- 'http://localhost'
- 'file:///'
- 'gopher://'
- 'dict://'
condition: 1 of selection_*
falsepositives:
- Internal health checks referencing loopback (filter by source IP of load balancer)
- Developers testing against internal artifact URIs
level: high
---
title: MLflow Server Process Making Unexpected Internal Network Connections
id: 2f7a9e15-6c4d-4b83-a1e9-0d5c3f8b62e4
status: experimental
description: Detects the MLflow server process initiating connections to RFC1918 or loopback destinations on ports atypical for artifact storage or database access, a hallmark of post-SSRF internal service access via CVE-2026-64849.
references:
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?search_api_fulltext=CVE-2026-64849
- https://attack.mitre.org/techniques/T1046/
author: Security Arsenal
date: 2026/08/19
tags:
- attack.discovery
- attack.t1046
- cve.2026.64849
logsource:
category: network_connection
product: linux
detection:
selection_process:
Image|contains:
- 'mlflow'
- 'gunicorn'
- 'uvicorn'
selection_internal:
DestinationIp|startswith:
- '10.'
- '172.16.'
- '192.168.'
- '127.'
filter_expected_ports:
DestinationPort:
- 443
- 5432
- 3306
condition: selection_process and selection_internal and not filter_expected_ports
falsepositives:
- Connections to internal model serving, feature store, or artifact proxy endpoints (tune DestinationPort filter to your architecture)
level: medium
Tuning note from the trenches: the third rule will require baseline tuning against your real artifact-store and database ports. Do not deploy it wide-open; scope the port filter to your architecture first, or it will be disabled within a week. Rules one and two are high-signal and safe to deploy broadly.
KQL — Microsoft Sentinel / Defender
Hunt across both endpoint network telemetry and ingested web/firewall logs. Even if your MLflow hosts are Linux, Defender for Endpoint and CEF/Syslog ingestion into Sentinel give you coverage.
// Hunt 1: MLflow/python processes reaching cloud metadata endpoints (IMDS credential theft via CVE-2026-64849)
let MetadataIPs = dynamic(["169.254.169.254", "100.100.100.200", "169.254.170.2"]);
union isfuzzy=true
(DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName has_any ("python", "mlflow", "gunicorn", "uvicorn")
| where RemoteIP in (MetadataIPs) or RemoteUrl has_any ("metadata.google.internal", "metadata.azure.internal")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemotePort, RemoteUrl, InitiatingProcessAccountName),
(CommonSecurityLog
| where TimeGenerated > ago(14d)
| where DestinationIP in (MetadataIPs) or DestinationHostName has_any ("metadata.google.internal")
| project TimeGenerated, DeviceName=DeviceHostName, InitiatingProcessFileName=ApplicationProtocol, InitiatingProcessCommandLine="", RemoteIP=DestinationIP, RemotePort=DestinationPort, RemoteUrl=DestinationHostName, InitiatingProcessAccountName=SourceUserName)
;
// Hunt 2: Inbound SSRF probes against the MLflow API in web/proxy logs
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where DeviceAction =~ "allowed" or isnull(DeviceAction)
| where DestinationPort == 5000 or RequestURL has "mlflow"
| where RequestURL has_any ("169.254.169.254", "metadata.google.internal", "127.0.0.1", "localhost", "file:///", "gopher://", "dict://")
or AdditionalExtensions has_any ("169.254.", "metadata.google.internal")
| project TimeGenerated, SourceIP, DestinationIP, DestinationPort, RequestMethod, RequestURL, DeviceProduct
| order by TimeGenerated desc;
// Hunt 3: MLflow hosts with anomalous egress fan-out (internal pivot after SSRF)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName has_any ("python", "mlflow", "gunicorn", "uvicorn")
| where RemoteIPType == "Private"
| summarize Destinations = dcount(RemoteIP), Ports = dcount(RemotePort), RemoteIPs = make_set(RemoteIP, 25) by DeviceName, InitiatingProcessCommandLine
| where Destinations > 10 or Ports > 8
| order by Destinations desc
Velociraptor VQL
Use this hunt artifact to sweep your MLflow fleet for active or recent connections consistent with SSRF exploitation, and to inventory which MLflow processes have an exposed network listener at all.
-- Hunt: MLflow processes with connections to metadata services or unexpected internal destinations (CVE-2026-64849)
SELECT Pid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)mlflow|gunicorn|uvicorn'
OR Exe =~ '(?i)python'
-- Correlate with live network state for metadata-service contact
SELECT Pid, Name, Status, Laddr, Raddr
FROM netstat()
WHERE Raddr =~ '169\\.254\\.169\\.254|169\\.254\\.170\\.2|100\\.100\\.100\\.200'
AND Pid IN (SELECT Pid FROM pslist() WHERE CommandLine =~ '(?i)mlflow|gunicorn|uvicorn|python')
-- Inventory: which MLflow servers are listening on all interfaces (internet-exposure triage)
SELECT Pid, Name, Status, Laddr, Raddr
FROM netstat()
WHERE Status =~ 'LISTEN'
AND Pid IN (SELECT Pid FROM pslist() WHERE CommandLine =~ '(?i)mlflow')
AND Laddr =~ '^0\\.0\\.0\\.0|\\[::\\]'
Remediation
Act in this order. Do not wait for a maintenance window for steps 1–3 — exposure reduction is immediate and reversible.
1. Verify and Upgrade Immediately
Apply the vendor-supplied fix per the MLflow security advisory on the project's GitHub repository (Security tab → Advisories) and CISA's KEV entry. Given KEV listing on 2026-08-19, treat any MLflow version released prior to the advisory as vulnerable until explicitly confirmed otherwise by the vendor. The following script inventories exposure, confirms running versions, and applies compensating network controls while you patch:
#!/bin/bash
# CVE-2026-64849 - MLflow SSRF triage and compensating controls
# Run as root on MLflow hosts. Test in a non-production segment first.
echo "=== [1/5] Inventory running MLflow processes and versions ==="
ps aux | grep -iE 'mlflow|gunicorn|uvicorn' | grep -v grep || echo "No MLflow process found"
if command -v pip >/dev/null 2>&1; then
pip show mlflow 2>/dev/null | grep -E 'Name|Version|Location' || echo "mlflow not installed via system pip"
fi
# Check virtualenvs and containers too
find /opt /srv /home -maxdepth 4 -name "activate" -path "*/bin/*" 2>/dev/null | while read -r venv; do
echo "--- venv: $venv ---"
"$(dirname "$venv")/pip" show mlflow 2>/dev/null | grep -E 'Name|Version'
done
docker ps --format '{{.Names}} {{.Image}}' 2>/dev/null | grep -i mlflow || echo "No MLflow containers detected"
echo "=== [2/5] Detect internet-exposed listeners (default port 5000) ==="
ss -tlnp | grep -E ':(5000)\b' | grep -E '0.0.0.0|\[::\]' && \
echo "WARNING: MLflow listening on all interfaces - restrict immediately" || \
echo "OK: No all-interface MLflow listener found"
echo "=== [3/5] COMPENSATING CONTROL: Block egress to instance metadata service ==="
# AWS/Azure IMDS + ECS task metadata endpoint
iptables -C OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT 2>/dev/null || \
iptables -A OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT
iptables -C OUTPUT -d 169.254.170.2 -p tcp -j REJECT 2>/dev/null || \
iptables -A OUTPUT -d 169.254.170.2 -p tcp -j REJECT
# Persist (Debian/Ubuntu); use firewalld equivalents on RHEL-family
iptables-save > /etc/iptables/rules.v4 2>/dev/null || iptables-save > /root/mlflow-egress-rules.v4
echo "Egress to 169.254.169.254 / 169.254.170.2 blocked."
echo "=== [4/5] Hunt for exploitation evidence in MLflow/HTTP access logs ==="
for logdir in /var/log/nginx /var/log/apache2 /var/log/mlflow /var/log; do
[ -d "$logdir" ] || continue
grep -rEi '169\.254\.169\.254|169\.254\.170\.2|metadata\.google\.internal|127\.0\.0\.1|file:///|gopher://|dict://' \
"$logdir" --include='*.log' 2>/dev/null | head -50
done
echo "Review any hits above against BOD 26-04 Forensics Triage Requirements before remediating."
echo "=== [5/5] Validate: attempt metadata fetch (should fail) ==="
curl -s -m 3 http://169.254.169.254/latest/meta-data/ && \
echo "FAIL: IMDS still reachable - verify iptables ordering / consider IMDSv2 enforcement" || \
echo "PASS: IMDS unreachable from this host"
echo "=== DONE. Next: upgrade MLflow per vendor advisory, enforce authn, restrict egress. ==="
2. Bind Authentication and Network Exposure
- Never expose the MLflow tracking server to the internet unauthenticated. Place it behind a reverse proxy (nginx, ALB, or your identity-aware proxy) enforcing SSO/OIDC. MLflow has no native robust authentication in default configuration — treat any unauthenticated deployment as a critical misconfiguration independent of this CVE.
- Bind the server to loopback or a private interface:
mlflow server --host 127.0.0.1with the proxy terminating external traffic. - Per CISA's required action, stakeholders are responsible for evaluating each asset's internet exposure. Sweep your external attack surface (and your cloud asset inventory) for port 5000 and MLflow UI fingerprints today.
3. Constrain Egress by Policy, Not Just by Patch
Even after patching, SSRF-class bugs recur. Apply defense-in-depth:
- Egress allowlisting: MLflow servers should only reach your artifact store endpoints, database, and package indexes. Deny-all-default outbound.
- Cloud hardening: Enforce IMDSv2 (AWS) so metadata requires a session token — this neuters most simple SSRF retrieval. On Azure, require the
Metadata:trueheader validation path and restrict via NSG. On GCP, constrain service-account scopes on MLflow compute. - Least-privilege IAM: The role attached to MLflow compute should be read-scoped to its artifact bucket/prefix only. If credentials are stolen via SSRF, a tightly scoped role is the difference between an incident and a breach.
4. Forensics Triage Before You Patch
CISA's BOD 26-04 Forensics Triage Requirements apply here: because this CVE is confirmed actively exploited, image or snapshot the MLflow host and preserve web/proxy/application logs before upgrading or reconfiguring. Specifically preserve:
- Reverse proxy and MLflow access logs (lookback of at least 90 days where available)
- Cloud audit logs (CloudTrail / Azure Activity Log / GCP Audit Logs) for anomalous use of the instance's IAM role — calls from IPs outside your cloud environment are the smoking gun for successful metadata theft
- Any credentials the MLflow host could access: rotate them regardless of findings
5. Compliance and Deadline Tracking
- Federal civilian agencies: BOD 26-04 deadlines are binding — track the KEV due date for CVE-2026-64849 in your POA&M.
- Private sector: adopt the same deadline internally. Map remediation to NIST CSF (ID.RA/PR.PS), CIS Control 7 (Continuous Vulnerability Management), and where applicable PCI-DSS 6.2 and HIPAA §164.308(a)(1) risk management obligations. A KEV-listed, internet-exposed MLflow server in a HIPAA or cardholder-data environment is a reportable-risk situation, not a backlog item.
- If the vendor fix cannot be applied: per CISA's explicit guidance, discontinue use of the product until mitigations are available.
Bottom Line
Full-read SSRF in a server that brokers access to your model artifacts and runs with cloud IAM privileges is about as bad as SSRF gets — and adversaries are already using it. Your sequence this week: inventory MLflow assets, kill internet exposure, block metadata egress, hunt for the indicators above, preserve forensic evidence, then patch per the vendor advisory and rotate any credentials the host could touch. Assume any unauthenticated, internet-reachable MLflow instance has already been enumerated.
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.