
Reproducible lab for CVE-2026-33017, an unauthenticated RCE in Langflow. Includes a Dockerized vulnerable service and a least-harm PoC that demonstrates code execution via the public build endpoint.
CVE-2026-33017 is an Unauthenticated Remote Code Execution (RCE) vulnerability in Langflow where a public build endpoint accepts attacker-controlled flow data, allowing custom component code to be executed on the server.
In this lab, the validation flow is:
PUBLIC flowjob_idThe proof is retrieved directly through the Langflow API events mechanism, making the result observable through the system interface itself.
This document presents a vuln-only lab.
At present, docker compose contains only one service: vuln, because this project follows a approach and avoids patched environments that are not based on an official fixed artifact.
The following behavior has been verified in this lab:
http://localhost:78611.8.1build_public_tmp returns a job_idExample proof object:
{
"canary": "lf33017-c14fc1c9",
"id_output": "uid=1000(user) gid=0(root) groups=0(root)",
"whoami": "user",
"hostname": "155aa3fd5e2a",
"cwd": "/app",
"python_version": "3.12.12"
}
The key evidence is:
id_outputwhoamihostnamecwdpython_versionThe information above shows that attacker-controlled code was actually executed on the server side.
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── README.md
└── .gitignore
7861 -> 7860This vulnerability exists because Langflow’s public build endpoint accepts user-supplied flow definitions, even though the endpoint is already designed for public flows. When an attacker submits a node definition containing custom component code, the system passes that code into the flow build path, which ultimately results in code execution on the server.
The PoC in this project uses a custom component that returns a proof object in its output to demonstrate that attacker-controlled code is actually executed.
The PoC in this project is designed to be least-harm and focuses on clearly observable proof through the API. Its workflow is as follows:
PUBLIC flowjob_idThis PoC does not cover:
docker compose up -d --build
curl -i http://localhost:7861/api/v1/version
python3 poc/poc.py --base-url http://localhost:7861 --artifact-dir ./artifacts/vuln
When the PoC succeeds, the output will look like this:
[+] http://localhost:7861 ready (version=1.8.1)
=== TARGET: vuln ===
Base URL : http://localhost:7861
Version : 1.8.1
Flow ID : <uuid>
HTTP : 200
Job ID : <uuid>
Canary : lf33017-xxxxxxxx
Events : artifacts/vuln/events-<job_id>.ndjson
Polls : 2
[+] Proof observed through the Langflow API events endpoint:
{
"canary": "lf33017-xxxxxxxx",
"id_output": "uid=1000(user) gid=0(root) groups=0(root)",
"whoami": "user",
"hostname": "<container-hostname>",
"cwd": "/app",
"python_version": "3.12.x"
}
[+] Vulnerable behavior observed
The file artifacts/vuln/events-<job_id>.ndjson stores raw event data for additional debugging.
This PoC demonstrates that:
This PoC is not intended to demonstrate persistence or advanced post-exploitation and keeps the impact at the minimum level necessary to validate the vulnerability.
Based on this lab, the demonstrated impact is:
This repository does not include a patched service by design.
Its scope is limited to reproducing the vulnerable behavior on a real upstream artifact. A patched side is only added when there is a clearly verifiable official fixed artifact available from the vendor or upstream project.
For that reason, this repository deliberately avoids:
This keeps the lab narrowly scoped and technically honest. Rather than presenting an artificial side-by-side setup, the repository focuses on three things:
In practice, this makes the repository best suited for:
docker compose down -v
This lab is designed for testing on localhost only.
Usage requirements: