Langflow fixed a critical RCE last year. Attackers just found the same unsandboxed exec() call on a different endpoint, and exploited it in 20 hours flat, with no public proof-of-concept code. CVE-2026-33017 (CVSS 9.3, Critical) is an unauthenticated remote code execution vulnerability affecting all Langflow versions through 1.8.1, fixed in 1.9.0. Within 20 hours of the advisory going public on March 17, 2026, attackers built working exploits from the advisory text alone and began harvesting API keys for OpenAI, Anthropic, and AWS from compromised instances. The important part for anyone running AI orchestration tools: the fix for the first vulnerability (CVE-2025-3248) was structurally incapable of preventing this one, because the vulnerable endpoint is designed to be unauthenticated. This is a case study in why AI orchestration tools demand security review at the architecture level, not just the endpoint level. From HTTP request to arbitrary code execution in 10 steps ​ The vulnerable endpoint is POST /api/v1/build_public_tmp/{flow_id}/flow , located in src/backend/base/langflow/api/v1/chat.py at line 580. This endpoint exists to let unauthenticated users interact with public flows, the mechanism that powers most Langflow-based chatbots in production. A user visits a shared link, chats with the bot, and the server builds and executes the flow behind the scenes. No login required. That is by design. The problem is a single parameter. The endpoint accepts an optional data field in the request body. When data is None , the server loads the flow definition from its database, the safe path. When data is provided, the server uses the caller's flow definition instead. This convenience feature, intended for the authenticated build endpoint at line 138 where logged-in users test modified flows, was copied to the public endpoint without restriction. An unauthenticated attacker can submit a fabricated flow definition containing arbitrary Python code in node definitions, and the server will compile and execute it. The code execution chain traverses 10 function calls from HTTP request to shell access: start_flow_build(data=attacker_data) calls generate_flow_events() in build.py:81 create_graph() calls build_graph_from_data(payload=data.model_dump()) in build.py:298 Graph.from_payload(payload) parses attacker-supplied nodes in base.py:1168 add_nodes_and_edges() → initialize() → _build_graph() in base.py:270,527 _instantiate_components_in_vertices() iterates each node in base.py:1323 vertex.instantiate_component() calls instantiate_class(vertex) in loading.py:28 code = custom_params.pop("code") extracts the attacker's Python from the node template in loading.py:43 eval_custom_component_code(code) calls create_class(code, class_name) in eval.py:9 prepare_global_scope(module) processes the code's AST in validate.py:323 exec(compiled_code, exec_globals) executes arbitrary code at validate.py:397 The critical function is prepare_global_scope in src/lfx/src/lfx/custom/validate.py . It copies the current globals() , resolves imports via importlib.import_module() (any module, unrestricted), then collects all top-level AST definitions, including ast.Assign , ast.ClassDef , and ast.FunctionDef , compiles them into a single ast.Module , and passes that to exec() . The key detail: ast.Assign nodes are executed during graph building, before the flow ever "runs." An attacker payload like _x = os.system("id") is an assignment statement. It executes the moment prepare_global_scope processes the node definitions. There is zero sandboxing, zero AST filtering, and zero restriction on which modules can be imported. Three CWE classifications apply: CWE-94 (Code Injection), CWE-95 (Eval Injection), and CWE-306 (Missing Authentication for Critical Function). CISA's ADP Vulnrichment assessment classifies the technical impact as "total" and confirms the vulnerability is automatable . Prerequisites for exploitation are minimal. The target instance needs at least one public flow (standard for any Langflow deployment serving a chatbot). The attacker needs that flow's UUID, discoverable from shared URLs. When AUTO_LOGIN=true , which is the default , an attacker can call GET /api/v1/auto_login to get a superuser token, create their own public flow, and then exploit it. As researcher Aviral Srivastava told The Hacker News: "One HTTP POST request with malicious Python code in the JSON payload is enough to achieve immediate remote code execution." Why Langflow got hit with the same vulnerability class twice ​ CVE-2026-33017 is the architectural sequel to CVE-2025-3248 , a CVSS 9.8 unauthenticated RCE disclosed in early 2025 that was actively exploited by the Flodrix botnet and added to CISA's Known Exploited Vulnerabilities catalog on May 5, 2025. That vulnerability lived on a different endpoint, POST /api/v1/validate/code , which accepted arbitrary Python and passed it to exec() without authentication. The fix was straightforward: the Langflow team a...
A critical, unauthenticated remote code execution vulnerability (CVE-2026-33017, CVSS 9.3) exists in Langflow, allowing attackers to execute arbitrary code via a crafted `data` parameter to the public `/api/v1/build_public_tmp/{flow_id}/flow` endpoint. The vulnerability affects all Langflow versions through 1.8.1 and is fixed in version 1.9.0. This incident underscores the necessity of architectural-level security reviews for AI orchestration tools, as the flaw stemmed from an inherently unauthenticated endpoint design that reused a vulnerable `exec()` call pattern previously patched in CVE-2025-3248.