cd /news/ai-safety/cve-2026-17633-authenticated-rce-in-… · home topics ai-safety article
[ARTICLE · art-136452] src=dev.to ↗ pub= topic=ai-safety verified=true sentiment=↓ negative

CVE-2026–17633 - Authenticated RCE in Langflow OSS via /api/v1/custom_component

A security researcher detailed CVE-2026-17633, a high-severity authenticated remote code execution flaw in Langflow OSS versions 1.0.0 through 1.10.3, disclosed in an IBM security advisory published August 5, 2026. The vulnerability in the POST /api/v1/custom_component endpoint allows any authenticated user to execute arbitrary Python when custom components are enabled, because the endpoint's only gate checks whether the feature is turned on rather than inspecting code content, and its prepare_global_scope() function drops module-level expressions from the AST while executing statements placed inside a class body. The researcher noted the exploit requires no filter bypass, only placing the payload inside the class definition.

by read3 min views3 publishedSep 21, 2026
Field Value
CVE ID CVE-2026-17633
CVSS 8.5 (HIGH)
CWE CWE-94 (Improper Control of Generation of Code)
Affected Langflow OSS 1.0.0 – 1.10.3
Preconditions Any authenticated user + LANGFLOW_ALLOW_CUSTOM_COMPONENTS=true
Vulnerable endpoint POST /api/v1/custom_component

Langflow is an open-source low-code platform for building LLM applications and agent workflows visually. One of its features, Custom Components, lets users define a component's behavior directly in Python. That feature is the attack surface for this vulnerability.

IBM's security advisory (published August 5, 2026) disclosed a cluster of issues in Langflow OSS 1.0.0–1.10.3. CVE-2026–17633 is the authenticated RCE reachable through /api/v1/custom_component.

From langflow/api/v1/endpoints.py (around line 1271):

@router.post("/custom_component", status_code=HTTPStatus.OK, include_in_schema=False)
async def custom_component(
 raw_code: CustomComponentRequest,
 user: CurrentActiveUser,
 request: Request,
) -> CustomComponentResponse:
 …
 if not settings.allow_custom_components and not code_hash_matches_any_template(raw_code.code, all_known):
 raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, …)
 component = Component(_code=effective_code)
 built_frontend_node, component_instance = build_custom_component_template(component, user_id=user.id)

The important detail isn't that there's "no validation" - it's that the validation checks the wrong thing. allow_custom_components answers "is this user allowed to create custom components," not "is this code's content safe." In production, LANGFLOW_ALLOW_CUSTOM_COMPONENTS=true is a common setting, and once it's on, this check passes trivially and the code flows through with zero content inspection.

Langflow does ship a separate AST-based scanner, scan_code_security() (covered in section 5), but this endpoint's execution path never calls it.

prepare_global_scope() custom_component() calls build_custom_component_template(), which flows into create_class() in lfx/custom/validate.py. That function calls prepare_global_scope(), and the submitted code is exec()'d shortly after.

def prepare_global_scope(module):
 exec_globals = globals().copy()
 …
 for node in module.body:
 if isinstance(node, ast.Import | ast.ImportFrom):
 imports.append(node)
 elif isinstance(node, ast.ClassDef | ast.FunctionDef | ast.Assign | ast.AnnAssign):
 definitions.append(node)
 …
 if definitions:
 compiled_code = compile(combined_module, "<string>", "exec")
 exec(compiled_code, exec_globals) # ← exec() happens here

This function walks the submitted code's AST and only collects import statements and class/ def/assignment nodes into definitions. That's the trap.

os.system(…) is, at the AST level, an ast.Expr node.isinstance allow-list above → it's ClassDef node - so when the class is defined (i.e., when exec() runs), that code executes right along with it.

import os
os.system("id > /tmp/pwned.txt")
class PocComponent(Component):
 …
class PocComponent(Component):
 os.system("id > /tmp/pwned.txt") # ← executes at class-definition time
 …

So the entire trick an attacker needs is: put the payload inside the class body, not at module level. No encoding tricks, no filter bypass gymnastics - just a simple, and simply devastating, design flaw.

The diagram below traces the full path from request to command execution.

In short:

Authenticated user (any privilege level)
 │
 ▼
POST /api/v1/custom_component { "code": "<malicious Python class>" }
 │
 ▼
build_custom_component_template() → create_class()
 │
 ▼
prepare_global_scope() - only ClassDef nodes get collected into definitions/exec target
 │
 ▼
compile_class_code() → exec(compiled_class, exec_globals)
 │
 ▼
Class body executes at definition time → RCE achieved

No LLM involvement, no scanner to evade. One HTTP request is enough.

Langflow ships a separate AST-based scanner, scan_code_security(), in langflow/agentic/helpers/code_security.py. But it's wired only into the Agentic Assistant path (validating LLM-generated component code) - it's never called from /api/v1/custom_component at all.

So CVE-2026–17633 isn't really a scanner bypass; it's exploiting a code path the scanner was never attached to in the first place. The scanner's own detection logic has a separate weakness (missing vars() coverage leading to a false is_safe: True verdict, tracked as CVE-2026–17632), which surfaced from analyzing the same codebase but is a distinct issue.

custom_component endpointLANGFLOW_ALLOW_CUSTOM_COMPONENTS set to false in production unless the feature is genuinely neededgid=0 membership) to reduce lateral-movement / container-escape surface

── more in #ai-safety 4 stories · sorted by recency
── more on @langflow 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/cve-2026-17633-authe…] indexed:0 read:3min 2026-09-21 ·