Back to Intelligence

MLflow SSRF and FUXA Exploitation in the Wild: A Defender's Guide to Blocking Cloud Credential Theft

SA
Security Arsenal Team
August 18, 2026
11 min read

Two open-source platforms sitting at opposite ends of the enterprise stack — MLflow, the de facto standard for machine learning lifecycle management, and FUXA, a web-based SCADA/HMI platform used in operational technology environments — are now being actively scanned and targeted by attackers. According to independent reporting from watchTowr and VulnCheck, the MLflow issue is a server-side request forgery (SSRF) flaw that attackers are leveraging to steal cloud credentials and secrets, while the FUXA vulnerability exposes industrial automation interfaces to compromise.

This is not theoretical. Malicious scanning and exploitation attempts are already underway. If your data science teams run internet-exposed or weakly segmented MLflow servers — and in my experience across dozens of cloud assessments, most do — an attacker can coerce your ML infrastructure into handing over the IAM credentials of the cloud instance it runs on. From there, the blast radius extends to every S3 bucket, model artifact store, and secrets manager those credentials can touch. For FUXA deployments, the stakes are physical: HMI compromise in an OT environment means visibility into — and potentially control over — industrial processes.

This post breaks down how these attacks work, how to detect them in your environment, and the concrete remediation steps your teams should execute this week.

Technical Analysis

The MLflow SSRF Flaw

Affected product: MLflow open-source ML lifecycle platform (tracking server and model registry deployments)

Vulnerability class: Server-Side Request Forgery (SSRF), mapped to MITRE ATT&CK technique T1552.005 (Cloud Instance Metadata API) as the primary post-exploitation objective

SSRF in MLflow is particularly dangerous because of where MLflow lives. The tracking server is typically deployed on cloud instances or Kubernetes pods with attached IAM roles granting read/write access to model artifact stores (S3, GCS, Azure Blob), experiment databases, and frequently secrets backends. An SSRF flaw allows a remote, unauthenticated attacker to supply a URL that the MLflow server itself fetches. The classic exploitation chain looks like this:

  1. Reconnaissance: Attackers scan for exposed MLflow tracking servers — typically on ports 5000 and 5001 — identifiable by their API endpoints (/api/2.0/mlflow/...).
  2. SSRF trigger: The attacker submits a request that causes the MLflow server to issue a server-side HTTP request to an attacker-chosen internal URL.
  3. Metadata theft: The canonical target is the cloud instance metadata service at 169.254.169.254 (AWS, Azure, GCP equivalents like metadata.google.internal). If the instance is running IMDSv1, a plain GET to /latest/meta-data/iam/security-credentials/ returns temporary IAM session credentials.
  4. Credential replay: The attacker exfiltrates these credentials and uses them from their own infrastructure to enumerate and pillage the victim's cloud account — object stores, secrets, model artifacts, and any downstream pivot paths the role permits.

The scanning activity observed by watchTowr and VulnCheck indicates attackers have working exploit paths and are systematically hunting for vulnerable instances. Treat any MLflow server reachable from untrusted networks as compromised until proven otherwise.

The FUXA Vulnerability

Affected product: FUXA open-source web-based SCADA/HMI (Node.js-based, built on a Node-RED-style architecture)

FUXA deployments are common in industrial automation, building management, and manufacturing environments where budget constraints push teams toward open-source HMI solutions. FUXA's web interface communicates with PLCs, Modbus devices, OPC-UA servers, and other OT protocols. A remotely exploitable flaw in the web layer — combined with the reality that many FUXA instances are deployed with default configurations and weak authentication — gives attackers a foothold with direct line-of-sight into OT networks. Exploitation activity observed against FUXA raises the specter of IT-to-OT pivoting: the HMI becomes the beachhead from which attackers map and manipulate industrial processes.

Exploitation Status

  • MLflow SSRF: Active malicious scanning and exploitation attempts confirmed by watchTowr and VulnCheck reporting. Treat as exploited in the wild.
  • FUXA: Active scanning and exploitation attempts confirmed in the same reporting.
  • CISA KEV: At time of writing, verify current KEV status at cisa.gov/known-exploited-vulnerabilities-catalog — if added, federal remediation deadlines apply and private-sector organizations should treat them as their own SLA.

Detection & Response

The highest-fidelity detection for SSRF-driven credential theft is egress monitoring: a Python/MLflow server process has almost no legitimate reason to connect to link-local metadata addresses on an ad-hoc basis from user-influenced code paths. Similarly, your perimeter logs should be hunting for SSRF payloads containing metadata URLs embedded in requests to MLflow endpoints.

Sigma Rules

YAML
---
title: MLflow Process Connecting to Cloud Instance Metadata Service
id: 4b8f2a91-6c3d-4e7a-b512-9d0e1f2a3b4c
status: experimental
description: Detects Python or MLflow server processes initiating network connections to cloud instance metadata endpoints (169.254.169.254 or metadata.google.internal), a hallmark of SSRF-driven cloud credential theft.
references:
  - https://thehackernews.com/2026/08/attackers-exploit-mlflow-ssrf-flaw-to.html
  - https://attack.mitre.org/techniques/T1552/005/
author: Security Arsenal
date: 2026/08/15
tags:
  - attack.credential_access
  - attack.t1552.005
logsource:
  category: network_connection
  product: linux
detection:
  selection_image:
    Image|contains:
      - '/python'
      - '/mlflow'
      - '/gunicorn'
  selection_dest:
    DestinationIp:
      - '169.254.169.254'
      - '100.100.100.200'
    DestinationHostname|contains:
      - 'metadata.google.internal'
  condition: selection_image and selection_dest
falsepositives:
  - Legitimate instance bootstrap scripts querying metadata during provisioning
  - Cloud agent tooling (should run as dedicated binaries, not python/mlflow processes)
level: high
---
title: SSRF Payload in HTTP Request Targeting Cloud Metadata Endpoints
id: 9c1d3e52-7a4b-4f8c-c623-0e1f2a3b4c5d
status: experimental
description: Detects inbound web requests containing cloud metadata service URLs or link-local addresses in request parameters, indicative of SSRF exploitation attempts against web applications such as MLflow.
references:
  - https://thehackernews.com/2026/08/attackers-exploit-mlflow-ssrf-flaw-to.html
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/08/15
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
detection:
  selection:
    c-uri|contains:
      - '169.254.169.254'
      - 'metadata.google.internal'
      - '100.100.100.200'
      - '169.254.170.2'
      - 'latest/meta-data'
  condition: selection
falsepositives:
  - Internal health checks passing metadata URLs (rare; tune by source IP)
  - Security scanner activity from approved assessment ranges
level: high
---
title: FUXA Node.js Process Spawning Shell or Command Interpreter
id: 2e5a7b13-8d5c-4a9d-d734-1f2a3b4c5d6e
status: experimental
description: Detects Node.js processes (the runtime underpinning FUXA SCADA/HMI) spawning shell interpreters or system utilities, a strong indicator of post-exploitation following web-layer compromise of the HMI.
references:
  - https://thehackernews.com/2026/08/attackers-exploit-mlflow-ssrf-flaw-to.html
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/08/15
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/node'
      - '/nodejs'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/python'
      - '/python3'
  condition: selection_parent and selection_child
falsepositives:
  - FUXA plugin or script nodes legitimately invoking system commands (baseline and exclude known flows)
  - Package installation during initial deployment
level: high

KQL — Microsoft Sentinel / Defender

This hunt looks for two behaviors in parallel: server processes reaching cloud metadata endpoints (SSRF credential theft) and inbound web requests carrying SSRF payloads. It assumes network logs are ingested via CommonSecurityLog (firewall/NSG flow) or Defender for Endpoint network events, and Syslog/web logs for request content.

KQL — Microsoft Sentinel / Defender
// Hunt 1: Non-system processes connecting to cloud instance metadata services
// High fidelity for SSRF-driven credential theft from MLflow and similar web apps
let MetadataTargets = dynamic(["169.254.169.254", "100.100.100.200", "169.254.170.2"]);
let Window = 24h;
union
    (CommonSecurityLog
    | where TimeGenerated > ago(Window)
    | where DestinationIP in (MetadataTargets)
    | where ApplicationProtocol !in ("http") or SourceProcessName has_any ("python", "mlflow", "gunicorn", "node")
    | summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Hits=count()
        by DeviceName, SourceIP, SourceProcessName, DestinationIP, DestinationPort),
    (DeviceNetworkEvents
    | where TimeGenerated > ago(Window)
    | where RemoteIP in (MetadataTargets)
    | where InitiatingProcessFileName has_any ("python", "mlflow", "gunicorn", "node", "java")
    | summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Hits=count()
        by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemotePort)
| sort by Hits desc;
// Hunt 2: Inbound requests carrying SSRF payloads to metadata endpoints
// Run against Syslog or web/WAF logs ingested into Sentinel
Syslog
| where TimeGenerated > ago(Window)
| where SyslogMessage has_any ("169.254.169.254", "metadata.google.internal", "latest/meta-data", "169.254.170.2")
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc;

Velociraptor VQL

Use this artifact across Linux fleets (MLflow servers, FUXA hosts) to identify live connections to metadata services from application processes, plus listening services on default MLflow/FUXA ports that may be exposed.

VQL — Velociraptor
-- Hunt for application processes with live connections to cloud metadata
-- services and for exposed MLflow/FUXA listeners on default ports
SELECT Pid, Name AS ProcessName, Exe AS Executable,
       Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
       Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort,
       Status
FROM netstat()
WHERE (Raddr.IP =~ '169\\.254\\.(169\\.254|170\\.2)'
   OR Raddr.IP =~ '100\\.100\\.100\\.200')
  AND (Name =~ '(?i)python|mlflow|gunicorn|node|java')
-- Second clause: flag listeners on default MLflow (5000/5001) and
-- FUXA (1881) ports bound to non-loopback interfaces
   OR (Status = 'LISTEN'
       AND Laddr.Port in (5000, 5001, 1881)
       AND NOT Laddr.IP =~ '^(127\\.|::1$)')

Verification and Hardening Script

The following Bash script audits Linux hosts for exposed MLflow/FUXA services, checks for metadata-service reachability from application users, and applies egress controls blocking application processes from reaching the instance metadata endpoint. Test in a staging environment before production deployment.

Bash / Shell
#!/usr/bin/env bash
# Security Arsenal - MLflow SSRF / FUXA exposure audit and egress hardening
# Run as root on candidate hosts. Review output before applying iptables rules.
set -euo pipefail

echo "=== [1] Listening services on MLflow/FUXA default ports ==="
ss -tlnp | grep -E ':(5000|5001|1881)\b' || echo "No MLflow/FUXA listeners found on default ports."

echo ""
echo "=== [2] Processes matching mlflow/node with external bindings ==="
ps aux | grep -Ei 'mlflow|gunicorn|fuxa|node-red' | grep -v grep || echo "No matching processes."

echo ""
echo "=== [3] Testing metadata service reachability (should be blocked for app users) ==="
if timeout 3 curl -s -o /dev/null -w "%{http_code}" http://169.254.169.254/latest/meta-data/ 2>/dev/null | grep -q "200"; then
    echo "[ALERT] IMDS reachable and responding - SSRF credential theft path is OPEN"
else
    echo "[OK] IMDS not reachable via plain GET (IMDSv2 enforced or egress blocked)"
fi

echo ""
echo "=== [4] Applying egress block: non-root UIDs -> 169.254.169.254 ==="
# Owner-match blocks metadata access for service accounts; cloud-init/root retain access.
iptables -C OUTPUT -d 169.254.169.254 -m owner ! --uid-owner 0 -j REJECT 2>/dev/null \
  || iptables -A OUTPUT -d 169.254.169.254 -m owner ! --uid-owner 0 -j REJECT
echo "Egress rule installed. Persist with iptables-save / netfilter-persistent."

echo ""
echo "=== [5] Recent outbound connections to metadata IP in logs ==="
journalctl -k --since "24 hours ago" 2>/dev/null | grep "169.254.169.254" | tail -20 \
  || echo "No kernel-logged metadata connections (enable iptables LOG rules for visibility)."

echo ""
echo "Audit complete. Remediate: upgrade MLflow/FUXA, enforce IMDSv2 (AWS),"
echo "place tracking servers behind authenticated reverse proxies, and segment OT/HMI networks."

Remediation

Execute these steps in priority order:

  1. Inventory and isolate immediately. Enumerate every MLflow tracking server and FUXA instance in your estate — including shadow-IT deployments stood up by data science teams. Pull any MLflow server off direct internet exposure today. If it must be remotely accessible, place it behind an authenticated reverse proxy (OAuth2-Proxy, mTLS, or your IdP's app gateway).

  2. Patch both platforms. Upgrade MLflow to the latest release from the official project (github.com/mlflow/mlflow — review release notes and the project's security advisories for the SSRF fix) and FUXA to the latest release (github.com/frangoteam/FUXA). Because active exploitation is confirmed, treat this as an emergency change, not a routine patch cycle.

  3. Block the metadata path (defense in depth, survives patching gaps).

    • AWS: Enforce IMDSv2 on every instance running MLflow (HttpTokens=required). IMDSv2's session-oriented token requirement defeats the simple GET-based SSRF pattern.
    • All clouds: Apply egress firewall rules denying application service accounts access to 169.254.169.254, metadata.google.internal, and Alibaba's 100.100.100.200. The script above implements this on Linux via iptables owner matching.
    • Kubernetes: Use NetworkPolicies to deny pod-to-metadata traffic and avoid attaching cloud IAM roles to pods hosting MLflow unless strictly required; prefer scoped, short-lived workload identity credentials.
  4. Constrain SSRF at the application layer. Where MLflow configuration allows, restrict permitted outbound hosts/schemes (allowlist your artifact stores only, deny link-local and RFC1918 ranges from server-side fetches). Terminate TLS at a proxy that can inspect and alert on metadata-URL patterns in request bodies and parameters.

  5. Rotate credentials on any potentially exposed instance. If an MLflow server was internet-reachable before patching, assume the instance role credentials may have been harvested. Rotate IAM access keys, revoke active sessions, and review CloudTrail / Azure Activity Log / GCP Audit Logs for anomalous use of instance role credentials from external IP addresses — this is the single most important IR step.

  6. Segment OT. FUXA and any HMI should never be reachable from the corporate LAN without a jump host or firewall-constrained path, and absolutely never from the internet. Verify Purdue-model segmentation, disable default FUXA credentials, and enable authentication on the FUXA web interface.

  7. Review vendor and researcher guidance. Monitor watchTowr (watchtowr.com) and VulnCheck (vulncheck.com) write-ups for IoCs and exploitation detail, the MLflow GitHub security advisories page, and CISA's KEV catalog for additions that trigger formal remediation deadlines.

If you find evidence of metadata-service access from MLflow processes predating your patch, escalate to incident response: credential theft from an ML platform role frequently means access to training data, model artifacts, and connected secrets stores.

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.