Executive Summary
CVE-2026-33017 is a critical unauthenticated remote code execution (RCE) vulnerability in Langflow, the popular open-source framework used for building AI agent and RAG pipelines. The flaw allows a remote, unauthenticated attacker to execute arbitrary Python code on any exposed Langflow instance with a single HTTP request. Active exploitation was observed within 20 hours of public disclosure, and CISA has added the CVE to its Known Exploited Vulnerabilities catalog — making immediate patching to version 1.9.0 (not 1.8.2) urgent.
1. What Is This Vulnerability?
Langflow exposes a public API endpoint designed to let unauthenticated users "build" shared flows:
POST /api/v1/build_public_tmp/{flow_id}/flow
This endpoint is intended for publicly shared flows that guests can execute without logging in. The bug lies in how optional request body data is handled: when a caller supplies a data parameter in the JSON body, Langflow substitutes the attacker-supplied flow definition for the stored one. That flow definition can contain arbitrary Python code embedded in node configurations — and Langflow passes it directly to exec() with zero sandboxing.
# Simplified vulnerable pattern (pseudocode from patched diff)
flow_data = request.json.get("data") or db.get_flow(flow_id)
# ...
exec(flow_data["nodes"][n]["data"]["code"]) # ← no sandbox, no validation
Because no authentication check guards the data override path, any internet-reachable Langflow instance is exploitable.
Attack Vector
- Attacker enumerates (or guesses) any valid
flow_id— or uses a dummy UUID accepted by some versions. - A single
POSTrequest is sent containing a flow payload whose node code is a reverse shell or credential-harvesting script. - The server executes the Python payload with the privileges of the Langflow process (often root inside Docker containers).
- Full server-side code execution is achieved, typically within milliseconds.
No CVE PoC was publicly available at the time of the first attacks. Threat actors reverse-engineered the advisory description alone to build working exploits.
Real-World Impact
The Sysdig Threat Research Team observed exploitation from six unique source IPs within 48 hours of disclosure. The attack lifecycle unfolded in three phases:
- Phase 1 (hours 0–20): Mass automated scanning from four IPs delivering identical payloads.
- Phase 2 (hours 20–36): Active reconnaissance with pre-staged attacker infrastructure, likely targeting high-value AI/ML deployments.
- Phase 3 (hours 36–48): Data exfiltration — environment variables, API keys, database credentials, and LLM provider tokens were siphoned to attacker-controlled hosts.
Compromised Langflow instances expose not only the host server but every downstream service connected to the AI pipeline: vector databases, LLM API accounts, cloud credentials, and potentially software supply chains.
2. Who Is Affected?
| Component | Affected Versions |
|---|---|
| Langflow (open-source) | ≤ 1.8.1 and 1.8.2 (incomplete patch) |
| Langflow Cloud (SaaS) | Patched by vendor — no user action required |
| Self-hosted Docker deployments | Affected if image tag is not 1.9.0+ |
| Kubernetes deployments | Affected if Helm chart image is not 1.9.0+ |
⚠️ Version 1.8.2 is still vulnerable. The patch in 1.8.2 was incomplete — JFrog Security Research confirmed the exploit path remains open. Only version 1.9.0 or later fully closes the vulnerability.
Instances are particularly at risk if:
- The Langflow UI/API port (default 7860) is internet-facing without authentication.
- A reverse proxy or API gateway does not enforce authentication on the
/api/v1/build_public_tmp/path. - The process runs with elevated privileges (e.g., as root in Docker).
3. How to Detect It (Testing)
Manual Testing Steps
-
Identify exposure: Confirm whether
/api/v1/build_public_tmp/is reachable from untrusted networks.curl -I https://<your-langflow-host>/api/v1/build_public_tmp/test-id/flowA
404or422(not401/403) without credentials confirms the endpoint is unauthenticated. -
Attempt a benign code injection: Send a controlled payload that writes a marker file (in a non-production environment only):
curl -X POST https://<host>/api/v1/build_public_tmp/test/flow \ -H "Content-Type: application/json" \ -d '{"data":{"nodes":[{"data":{"code":"import os; open('/tmp/pwned.txt','w').write('vuln')"}}]}}'Check for
/tmp/pwned.txton the server. Its presence confirms vulnerability. -
Check the running version:
curl https://<host>/api/v1/version # Look for "version" field — anything below 1.9.0 is vulnerable
Automated Scanning
-
Tool: Nuclei (ProjectDiscovery)
-
Template: Search for community template tagged
CVE-2026-33017in the nuclei-templates repository.nuclei -u https://<host> -t cves/2026/CVE-2026-33017.yaml -
Expected output:
[critical] [CVE-2026-33017] [http] https://<host>/api/v1/build_public_tmp/...confirms vulnerable instance. -
Tool: Grype or Trivy (for image scanning)
trivy image langflowai/langflow:1.8.1 # Reports CVE-2026-33017 under HIGH/CRITICAL findings
Code Review Checklist
- Verify the
build_public_tmpendpoint enforces strict input validation and does not passrequest.datato anyexec()oreval()call. - Confirm flow node
codefields are validated against an allowlist before execution. - Check that public endpoints require the
flow_idto match a database-stored record (no arbitrary UUIDs accepted). - Ensure sandboxing (e.g.,
RestrictedPythonor subprocess isolation) is applied to all user-defined code paths.
4. How to Fix It (Mitigation)
Step-by-Step Remediation
-
Update Langflow to version 1.9.0 or later — the only version with a complete fix.
pip install langflow==1.9.0 # or for Docker: docker pull langflowai/langflow:1.9.0 -
Do NOT stop at 1.8.2 — confirm your installed version is exactly 1.9.0+:
python -c "import langflow; print(langflow.__version__)" -
Rotate all secrets immediately if the instance was internet-accessible at any time on a vulnerable version:
- LLM API keys (OpenAI, Anthropic, etc.)
- Vector database credentials
- Cloud provider credentials (AWS, GCP, Azure)
- Any database connection strings stored in environment variables
-
Audit logs for signs of exploitation:
- Unexpected outbound connections from the Langflow process
POSTrequests to/api/v1/build_public_tmp/from external IPs- Unusual files written to
/tmpor the application working directory
-
Deploy the instance behind authentication — even after patching, the public build endpoint should not be world-accessible unless your use case explicitly requires it.
Network-Level Mitigation (Immediate, Pre-Patch)
If you cannot patch immediately, block or authenticate the vulnerable path at the reverse proxy level:
# nginx example: require basic auth for the vulnerable path
location /api/v1/build_public_tmp/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://langflow:7860;
}
Or block it entirely if public flows are not required:
location /api/v1/build_public_tmp/ {
return 403;
}
Code Fix Example
The fix in version 1.9.0 removes the ability to supply arbitrary data overrides from unauthenticated requests and adds input validation before any code execution:
# BEFORE (vulnerable — 1.8.1 and 1.8.2)
flow_data = request.json.get("data") or await get_flow_from_db(flow_id)
nodes = flow_data["nodes"]
for node in nodes:
exec(node["data"]["code"]) # arbitrary code execution
# AFTER (patched — 1.9.0)
# Unauthenticated endpoint no longer accepts caller-supplied flow data
flow_data = await get_flow_from_db(flow_id) # DB record only, no override
if flow_data is None or not flow_data.is_public:
raise HTTPException(status_code=403)
# Code fields validated against allowlist before execution
validated_code = validate_node_code(node["data"]["code"])
sandbox_exec(validated_code)
Configuration Hardening
- Set
LANGFLOW_AUTO_LOGIN=falseand configure proper user authentication. - Run Langflow as a non-root user inside containers (
USER langflowin Dockerfile). - Mount the application directory read-only where possible.
- Use network policies (Kubernetes) to restrict Langflow's egress to known endpoints only.
5. How to Test the Fix (Validation)
Regression Test Scenarios
- Scenario A: Verify the patch is applied —
GET /api/v1/versionreturns1.9.0or higher. - Scenario B: Replay the exploit payload against the patched instance and confirm a
403 Forbiddenor422 Unprocessable Entityresponse — no code execution occurs. - Scenario C: Confirm legitimate public flow execution still works for flows explicitly marked public in the database.
Security Test Cases
Test Case 1: Verify RCE no longer possible via data override
- Precondition: Langflow 1.9.0 installed; a valid public
flow_idexists in the DB. - Steps: Send
POST /api/v1/build_public_tmp/{flow_id}/flowwith adatabody containing malicious Python code. - Expected Result: Server returns
403or ignores thedatafield; no code is executed; no marker file created.
Test Case 2: Confirm unauthenticated endpoint still serves legitimate public flows
- Precondition: A flow is explicitly set as public in the database.
- Steps: Send
POST /api/v1/build_public_tmp/{flow_id}/flowwith nodatabody. - Expected Result: Flow executes using only the DB-stored definition; response
200 OK.
Test Case 3: Confirm the endpoint rejects unknown flow IDs
- Precondition: Use a random UUID as
flow_id. - Steps: Send the POST request.
- Expected Result:
404 Not Found— no code path reached.
Automated Test
import requests, pytest
BASE_URL = "https://your-langflow-host"
VALID_PUBLIC_FLOW_ID = "your-known-public-flow-id"
MALICIOUS_PAYLOAD = {
"data": {
"nodes": [{
"data": {
"code": "import os; os.system('touch /tmp/cve_2026_33017_pwned')"
}
}]
}
}
def test_rce_not_exploitable():
r = requests.post(
f"{BASE_URL}/api/v1/build_public_tmp/{VALID_PUBLIC_FLOW_ID}/flow",
json=MALICIOUS_PAYLOAD,
timeout=10
)
assert r.status_code in (403, 422), f"Unexpected status: {r.status_code}"
# Verify no marker file was created (requires server-side check or OOB callback)
def test_version_is_patched():
r = requests.get(f"{BASE_URL}/api/v1/version", timeout=10)
version = r.json().get("version", "0.0.0")
major, minor, patch = map(int, version.split(".")[:3])
assert (major, minor, patch) >= (1, 9, 0), f"Unpatched version: {version}"
6. Prevention & Hardening
Best Practices
- Never expose AI orchestration frameworks directly to the internet. Place Langflow, Flowise, and similar tools behind an authenticated reverse proxy or VPN.
- Audit public endpoints after every upgrade. Any endpoint that accepts unauthenticated input and processes code (even indirectly) is a high-risk target.
- Implement secrets management. Store LLM API keys and DB credentials in a vault (HashiCorp Vault, AWS Secrets Manager) rather than environment variables — this limits blast radius if an RCE occurs.
- Apply the principle of least privilege to the Langflow process: restrict filesystem writes, outbound network access, and system calls.
- Pin dependency versions in Docker images and CI/CD pipelines; subscribe to Langflow's GitHub security advisories to be notified of future patches.
Monitoring & Detection
- SIEM rule: Alert on unexpected
POSTrequests to/api/v1/build_public_tmp/from external IPs, especially with aContent-Type: application/jsonbody larger than your typical flow payloads. - Egress monitoring: Alert on outbound connections from the Langflow process to IPs not in your approved LLM/cloud provider list.
- File Integrity Monitoring (FIM): Monitor
/tmpand the application directory for unexpected file creation — a common attacker beachhead indicator. - Container runtime security: Tools like Falco or Sysdig can detect anomalous
exec()calls spawning shells from a Python process.
# Falco rule example
- rule: Langflow RCE Indicator
desc: Detect shell spawned from Langflow Python process
condition: >
spawned_process and
proc.pname = "python3" and
proc.name in (shell_binaries) and
container.image.repository contains "langflow"
output: >
Shell spawned inside Langflow container (cmd=%proc.cmdline container=%container.id)
priority: CRITICAL
References
- CVE Link: CVE-2026-33017 — NVD
- CISA KEV: CISA Known Exploited Vulnerabilities Catalog
- Sysdig Analysis: CVE-2026-33017: How attackers compromised Langflow AI pipelines in 20 hours
- The Hacker News: Critical Langflow Flaw CVE-2026-33017 Triggers Attacks within 20 Hours of Disclosure
- JFrog Research: Langflow CVE-2026-33017: Latest 'fixed' version is still exploitable
- SecurityWeek: Critical Langflow Vulnerability Exploited Hours After Public Disclosure
- SecPod Blog: CVE-2026-33017: Critical Langflow Vulnerability Exploited Within 20 Hours
- Help Net Security: CISA sounds alarm on Langflow RCE after rapid exploitation
- Patch Download: Langflow 1.9.0 Release