A public 'build this flow' button that runs whatever Python you paste into it
Langflow exposes POST /api/v1/build_public_tmp/{flow_id}/flow so that anonymous users can render public flows in the visual builder. The handler accepts attacker-supplied node definitions and instantiates them server-side — meaning arbitrary Python embedded in node code, default arguments, or decorators is exec()'d in the Langflow worker process with whatever privileges the service runs as (usually the container's root or the host's langflow user). All versions ≤ 1.8.2 are affected; the fix lands in 1.9.0, which adds authentication and input validation on the public-build path. This is the second time the same exec() pattern has bitten Langflow — CVE-2025-3248 was the first round on /api/v1/validate/code.
Vendor severity (CRITICAL / 9.3) is accurate and arguably understated. CVSS 4.0 captures the trivial reachability (AV:N/AC:L/PR:N/UI:N) but the real-world story is worse: KEV listing, EPSS 0.984, observed mass scanning, Monero miner payloads in the wild within 20 hours of advisory publication, and a target population (Langflow servers) that is almost always internet-exposed by design because operators want their RAG agents reachable. There is no friction to audit away.
5 steps from start to impact.
Discover exposed Langflow instance
/health, /api/v1/version, or the default :7860 UI banner. Shodan, Censys, and FOFA all have ready-made queries (http.title:"Langflow", http.favicon.hash). Mass scanning is already happening — Sysdig observed it within 20 hours of disclosure.- Langflow instance reachable on TCP (typically 7860 or behind a reverse proxy on 80/443)
- No IP allowlist or auth proxy in front
- None for cloud-hosted demos and SaaS deployments of customer agents
- Internal-only deployments behind a VPN are unreachable
Langflow RCE Attempt as of March 2026Craft malicious flow JSON
__import__('os').system(...) inside a class default value.- Knowledge of Langflow node schema (publicly documented)
- No PoC needed — advisory text alone is enough; attackers wrote exploits from it in hours
- None — payload is plain JSON, no auth, no CSRF token
__import__, subprocess, os.system inside JSON bodies posted to /api/v1/build_public_tmp/POST to the public build endpoint
POST /api/v1/build_public_tmp/{flow_id}/flow with the crafted JSON body. The server deserializes the flow and calls exec() on attacker-controlled code paths before any authorization check runs. Tooling: curl, httpx, or the public Nuclei template langflow-rce-cve-2026-33017.yaml.- Reachable endpoint
- Any
flow_id(endpoint accepts arbitrary IDs in the vulnerable path)
- None at the protocol layer; a fronting reverse proxy that blocks
/api/v1/build_public_tmp/*would stop it
Langflow Public Build RCE released March 2026Code execution as the Langflow process
langflow service account. Attackers gain shell access, read .env (OpenAI/Anthropic/Azure keys, DB creds), and pivot.- No egress restrictions on the Langflow host (reverse shell)
- Service has read access to its own config and secrets
- egress firewall blocking outbound to attacker C2
- read-only root filesystem
- non-root container user with restricted capabilities
python spawning sh/curl/wget to non-vendor IPs; cloud workload-protection flags Monero miner binariesPersistence and payload drop
- Outbound internet from victim
- Write access to /tmp or a persistence path
- Egress firewalling to known-bad IPs
- CSPM detecting privilege change on the container
^/api/v1/build_public_tmp/ on your nginx/Traefik/ALB in front of Langflow until you can deploy 1.9.0. This is the surest pre-patch mitigation and ships in under an hour. Per noisgate mitigation SLA for CRITICAL + active KEV exploitation: deploy within hours, not days..env or component configs. Do this in parallel with patching, not after.python child processes (sh, curl, wget), and recent writes to /tmp or ~/.cache on Langflow hosts. Sysdig and SonicWall have published IOCs; ingest them into your SIEM.- WAF generic rules — payload is JSON with Python keywords; signature WAFs without Langflow-specific rules will miss it
- Authentication on the UI login page — the vulnerable endpoint bypasses login by design; adding admin auth to
/logindoes nothing - Network segmentation alone — if any production data source is reachable from the Langflow host (your vector DB, your S3 bucket), segmentation downstream of Langflow is the wrong layer
- Running Langflow as non-root inside the container — useful for host escape but does not stop secret theft or model-provider key abuse
The supporting signals.
| In-the-wild status | Active mass exploitation — Sysdig TRT observed first attempts within 20 hours of advisory publication (March 17, 2026) |
|---|---|
| KEV status | Listed — CISA KEV catalog, federal patch-by deadline April 8, 2026 |
| EPSS | 0.98412 (≥99th percentile — top tier exploitability) |
| Public PoC | Working exploits in the RAXE Labs advisory, Aviral Srivastava's Medium/Dev.to writeups, and a public Nuclei template |
| CVSS | 4.0 vector AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L — unauthenticated network attack, no user interaction, full CIA on the host |
| Affected versions | Langflow ≤ 1.8.2 (all prior releases vulnerable) |
| Fixed version | 1.9.0 (adds auth + validation on public build path) |
| Exposure data | Shodan/Censys show several thousand Langflow instances internet-facing; GreyNoise tag Langflow RCE Attempt active since March 2026 |
| Observed payload | Customized XMRig Monero miner, credential harvesting from .env, reverse shells (Sysdig, GBHackers) |
| Disclosed | 2026-03-17 via GHSA-vwmf-pq79-vjvx; reported by Aviral Srivastava |
Sources.
- GitHub Security Advisory GHSA-vwmf-pq79-vjvx
- Sysdig — Compromised in 20 hours
- SonicWall — Langflow AI Code Injection to RCE
- RAXE Labs RAXE-2026-043 advisory
- Aviral Srivastava — researcher writeup
- The Hacker News — Monero miner exploitation
- Wiz vulnerability database — CVE-2026-33017
- CSO Online — CISA sounds alarm
Why this verdict
- Unauthenticated and pre-auth reachable — no credentials, no session, no user interaction; a single POST to
/api/v1/build_public_tmp/{flow_id}/flowis the entire chain - KEV-listed with EPSS 0.984 — CISA flagged it within weeks of disclosure; federal patch deadline already issued
- Active exploitation within 20 hours of advisory publication (Sysdig TRT), with XMRig miner payloads and credential theft already observed
- Role multiplier: Langflow hosts the orchestration plane for RAG/agent pipelines — code execution there yields API keys (OpenAI/Anthropic/Azure), vector DB credentials, and access to enterprise data sources feeding the agents. Even on a 'low-value' dev instance the blast radius reaches the model-provider billing account and any data the agent retrieves
- Role multiplier: in production AI-agent deployments Langflow sits adjacent to internal data stores (Postgres, S3, Snowflake connectors) — the chain ends in enterprise data egress, not just one host
- Internet-exposure is the design pattern — operators deploy Langflow to serve agents; the assumption that 'most instances are internal' does not hold here as it does for ESXi or DCs
Why not higher?
CRITICAL is already the top bucket. We score 9.6 rather than the 10.0 ceiling because the immediate blast radius is the Langflow process itself — fleet-scale impact requires the secrets and connectors that the box holds, which is high-probability but not automatic.
Why not lower?
Downgrading to HIGH would require either authentication friction, an exposure population below 1%, or a containment story (sandboxing, non-root execution) — none apply. Langflow is deployed to be reachable, the endpoint is anonymous, and the code runs in the main worker. The KEV listing and EPSS 0.984 alone make a sub-CRITICAL call indefensible.
Crowdsourced verification payload.
Run on an auditor workstation or CI runner with network reach to the Langflow host. Usage: ./check_langflow.sh https://langflow.example.com. No privileges required; only outbound HTTP to the target.
#!/usr/bin/env bash
# noisgate verifier for CVE-2026-33017 (Langflow unauthenticated RCE)
# Outputs: VULNERABLE | PATCHED | UNKNOWN
set -u
TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
echo "usage: $0 <https://langflow-host>" >&2
exit 2
fi
# 1. Try to read the version endpoint (unauth on all versions)
VER_JSON="$(curl -sk --max-time 10 "$TARGET/api/v1/version" || true)"
VERSION="$(echo "$VER_JSON" | grep -oE '"version"[[:space:]]*:[[:space:]]*"[^"]+"' | head -1 | sed -E 's/.*"([^"]+)"$/\1/')"
if [[ -n "$VERSION" ]]; then
# semver compare against 1.9.0
IFS='.' read -r MAJ MIN PAT <<<"${VERSION%%[-+]*}"
MAJ=${MAJ:-0}; MIN=${MIN:-0}; PAT=${PAT:-0}
if (( MAJ > 1 )) || { (( MAJ == 1 )) && (( MIN >= 9 )); }; then
echo "PATCHED (version $VERSION >= 1.9.0)"
exit 0
else
echo "VULNERABLE (version $VERSION < 1.9.0)"
exit 1
fi
fi
# 2. Fallback: probe the vulnerable endpoint with a benign payload
# A 200/422 (request reached the handler) on an unauthenticated POST
# to build_public_tmp indicates the public build path is enabled.
PROBE_BODY='{"data":{"nodes":[],"edges":[]}}'
CODE="$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 \
-X POST -H 'Content-Type: application/json' \
-d "$PROBE_BODY" \
"$TARGET/api/v1/build_public_tmp/00000000-0000-0000-0000-000000000000/flow" || true)"
case "$CODE" in
200|202|400|422)
echo "VULNERABLE (public build endpoint reachable unauthenticated; HTTP $CODE)"
exit 1 ;;
401|403|404)
echo "PATCHED (public build endpoint not reachable unauthenticated; HTTP $CODE)"
exit 0 ;;
*)
echo "UNKNOWN (HTTP $CODE from build endpoint, no version metadata)"
exit 3 ;;
esac