flawopen.com/Teardowns/cve-2026-105699-langflow-mcp-cross-project-file-disclosure
CVE-2026-105699: Arquivos MCP no Langflow
O Langflow autenticava a conexão MCP, mas não autorizava cada arquivo solicitado. Um usuário podia ler arquivos de fluxos alheios; a versão 1.9.1 corrige a checagem de propriedade.[1], [2], [5]
Vetor CVSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:NImagine um hotel que confere se você tem uma chave, mas entrega a bagagem de qualquer quarto quando você informa a etiqueta. A chave prova que você pode entrar no hotel, não que a mala de outro hóspede é sua. A leitura MCP do Langflow precisa confirmar o proprietário e o projeto antes de abrir o arquivo.[1]
Conceitos Centrais e Termos
Model Context Protocol (MCP)- Protocolo pelo qual um aplicativo de IA solicita ferramentas e recursos a um servidor. O servidor ainda precisa autorizar cada objeto solicitado.[1]
Endpoint MCP vinculado a projeto- Conexão MCP do Langflow associada a um projeto. Acesso ao endpoint não dá acesso a arquivos de todos os projetos.[1]
resources/read- Operação MCP que solicita ao servidor um recurso identificado por URI.[1]
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-639
Análise de Causa Raiz
Nas versões afetadas do Langflow, de 1.6.8 a 1.9.0, o transporte MCP vinculado a projeto autenticava o acesso ao ID do projeto na URL da conexão. Depois, o handler resources/read recebia uma URI, extraía um ID de fluxo e um nome de arquivo e os passava a storage_service.get_file() sem confirmar que o fluxo pertencia ao usuário autenticado ou ao projeto atual. A camada de armazenamento lê por namespace e nome; ela não conhece as permissões de usuário e projeto do Langflow. Assim, um usuário com conta e acesso ao endpoint MCP do próprio projeto podia solicitar um arquivo no namespace de fluxo de outra pessoa. O comportamento global separado de resources/list e tools/list podia revelar IDs e facilitar a escolha do alvo, mas não era necessário para a leitura. É uma falha autenticada de confidencialidade entre usuários, não acesso anônimo nem execução de código. O registro CVE atribui CVSS 4.0 7.1 High e CWE-639. O Langflow 1.9.1 corrige o caminho: handle_read_resource() obtém o usuário autenticado e resolve o fluxo exigindo Flow.user_id == current_user.id e, em transporte de projeto, Flow.folder_id == project_id; um namespace não autorizado é rejeitado antes do acesso ao armazenamento. O patch também rejeita separadores e sequências de traversal, verifica contenção nos caminhos de leitura/gravação/exclusão e limita listagens globais ao usuário atual. O teste de regressão do mantenedor nega a leitura do fluxo de outra pessoa.[1], [2], [3], [5]
Fluxo de Ataque Passo a Paso
O usuário autentica no próprio endpoint MCP de projeto
O atacante precisa de uma conta Langflow e acesso a pelo menos uma conexão MCP vinculada a projeto. A falha não contorna o login.[1]
O cliente solicita uma URI de recurso
A chamada resources/read inclui uma URI cujos últimos componentes identificam um namespace de fluxo e um arquivo.[1]
O armazenamento lê pelo namespace
storage_service.get_file() retornava o arquivo do namespace informado. O armazenamento não tinha contexto de propriedade do usuário.[1]
Código-Fonte: Vulnerável vs. Seguro
Estes são trechos focados em Python do caminho documentado, não um aplicativo independente. O caminho vulnerável tratava o namespace informado pelo cliente como autoridade suficiente. A correção da versão 1.9.1 resolve primeiro o fluxo dentro do usuário autenticado e, em conexões MCP de projeto, do projeto atual; só então o armazenamento pode lê-lo. O patch também valida nomes de arquivo e impõe contenção de caminho na camada de armazenamento para que outros pontos de leitura/gravação/exclusão não contornem a regra. Mantenha a autorização no serviço que conhece o usuário e o projeto; um adaptador de armazenamento não consegue inferir a propriedade. Escopo do trecho: o handler real também permite arquivo do bucket do usuário somente quando o namespace corresponde ao ID do próprio usuário autenticado e o servidor não tem escopo de projeto. O trecho omite esse ramo separado; ele não deve ser interpretado como acesso a qualquer namespace. A suíte de regressão upstream inclui test_handle_read_resource_denies_other_users_flow, que verifica a negação da leitura entre usuários.[1], [3], [4], [7]
Trecho de origem: mcp_utils.py — trechos selecionados do código
# Trecho do caminho de leitura afetado: os IDs analisados eram enviados diretamente ao armazenamento.
content = await storage_service.get_file(
flow_id=flow_id,
file_name=filename,
)
# Redução, seguindo a estrutura da fonte, do limite de autorização da versão 1.9.1.
current_user = current_user_ctx.get()
query = select(Flow).where(
Flow.id == namespace_id,
Flow.user_id == current_user.id,
)
if project_id is not None:
query = query.where(Flow.folder_id == project_id)
flow = (await session.exec(query)).first()
if flow is None:
raise ValueError("Resource not found or access denied")
content = await storage_service.get_file(
flow_id=namespace_id,
file_name=filename,
)
Lista de Verificação de Segurança para Engenharia
- ✓Atualize o Langflow para 1.9.1 ou posterior e confira o pacote e a imagem de contêiner em execução, não apenas o código-fonte.[5]
- ✓Autorize cada URI
resources/readpelo usuário autenticado e pelo projeto da conexão MCP antes de chamar o armazenamento.[1], [3] - ✓Resolva o identificador para um objeto do banco e exija tanto a propriedade do usuário quanto a associação ao projeto quando o endpoint for específico de projeto.[1], [3]
- ✓Prefira IDs de recurso opacos gerados pelo servidor em vez de aceitar caminhos de armazenamento ou URIs de download arbitrários do cliente.[1], [3]
- ✓Valide nomes após decodificá-los, rejeite separadores e componentes de traversal e imponha contenção de caminho canônico na camada de armazenamento para todas as leituras, gravações e exclusões.[1], [3]
- ✓Limite consultas
resources/listetools/listao usuário autenticado; trate a enumeração de identificadores como exposição distinta que pode ampliar uma falha de autorização.[7] - ✓Adicione teste com dois usuários: o MCP de projeto de um deles deve negar arquivos de fluxos do outro e fluxos de outro projeto.[1]
- ✓Revise os logs de acesso das instalações afetadas e avalie possível exposição; o aviso documenta a falha, não exploração confirmada no mundo real.[7], [3]
- ✓Mantenha o teste upstream
test_handle_read_resource_denies_other_users_flowe adicione um caso de escopo de projeto que comprove a negação de um fluxo do usuário fora do projeto atual.[7], [3]
Fontes
- Langflow maintainer advisory GHSA-4hmc-cfm3-w43c
- CVE Program record CVE-2026-105699
- Upstream fix commit b8fe970
- Upstream pull request #12818 and regression coverage
- Langflow 1.9.1 release
- MITRE CWE-639 — Authorization Bypass Through User-Controlled Key
- Langflow regression tests — MCP resource authorization