flawopen.com/Teardowns/cve-2026-71433-langgraph-store-namespace-boundary
LangGraph CVE-2026-71433: vazamento de namespace
Consultas com escopo no Postgres e SQLite do LangGraph podiam atravessar limites de namespace e expor dados de outro tenant. Atualize os dois pacotes para 3.1.1.
Vetor CVSS
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:NImagine pedir ao bibliotecário uma pasta cujo nome começa com “equipe”. Se o catálogo buscar apenas o texto inicial, ele pode devolver “equipe2” junto com “equipe”. O LangGraph juntava os rótulos do namespace com pontos e usava um padrão de prefixo sem exigir esse ponto como limite. A correção exige o namespace exato ou um segmento seguinte de verdade, evitando que a pasta de um tenant seja confundida com a de outro.
Conceitos Centrais e Termos
Namespace- Uma tupla de rótulos usada pelo Store do LangGraph para agrupar itens. Uma aplicação pode usá-la como limite entre usuários ou tenants.
Escopo por prefixo- Uma solicitação para ler um namespace e seus descendentes. A correspondência correta respeita o limite do segmento:
fooincluifoo.child, mas não o namespace irmãofoobar. Padrão SQL `LIKE`- Um padrão textual no qual
%corresponde a qualquer sequência e_a um caractere. Esses caracteres devem ser escapados quando os rótulos do namespace são literais. CWE-863- Autorização incorreta: o Store retornou registros fora do namespace que o chamador podia ler.
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-863
Análise de Causa Raiz
Antes da versão 3.1.1, os Stores de checkpoint Postgres e SQLite achatavam tuplas de namespace usando pontos e limitavam a busca com LIKE '<namespace>%'. O LIKE não entende o separador do namespace; por isso, uma consulta por foo também podia corresponder ao namespace irmão foobar. Os rótulos legais % e _ também podiam atuar como curingas. list_namespaces tinha erros relacionados de prefixo e sufixo. Uma leitura normal com escopo já bastava; não era necessário enviar entrada malformada. O problema afeta somente os caminhos de leitura search e listagem de namespaces nos Stores Postgres/SQLite quando a aplicação depende do namespace para separar tenants. get, put e delete usam igualdade exata e não foram afetados; InMemoryStore compara os elementos do namespace e também não foi afetado. A correção exige igualdade exata ou um ponto antes dos descendentes, escapa metacaracteres do LIKE e usa padrões por segmento na listagem. No SQLite, a busca também evita o comportamento do LIKE que ignora diferenças de maiúsculas/minúsculas ASCII. O comunicado não relata exploração conhecida. Os pacotes afetados foram corrigidos na versão 3.1.1.
Matriz de exposição do CVE-2026-71433 por implantação
| Implantação e formato do namespace | Comportamento documentado | Ação de triagem |
|---|---|---|
| PostgresStore / AsyncPostgresStore ou SqliteStore / AsyncSqliteStore anterior à 3.1.1; o isolamento entre tenants depende de namespaces. | Uma busca search ou list_namespaces com escopo pode alcançar um namespace irmão quando os rótulos compartilham um prefixo textual (foo / foobar, 1 / 12) ou contêm % / _. No SQLite, a busca também igualava diferenças apenas de maiúsculas ASCII. | Atualize o pacote checkpoint aplicável para 3.1.1 ou posterior. Teste prefixos irmãos, caracteres curinga, correspondência de sufixo e diferenças de caixa no backend de produção. |
| Store SQLite anterior à 3.1.1 com rótulos de namespace que diferem apenas por caixa ASCII. | A busca vulnerável de descendentes usava LIKE sem distinção de caixa, enquanto operações exatas distinguiam maiúsculas de minúsculas. | Atualize e adicione um teste de regressão para caixa se os rótulos puderem diferir nesse aspecto. |
Rótulos UUID de tamanho fixo sem % nem _. | O aviso diz que esse formato não é afetado: rótulos de tamanho fixo não podem ser prefixos uns dos outros. | Confirme que todos os segmentos seguem essa invariável. Se os rótulos puderem variar ou conter curingas, considere a implantação afetada. |
| InMemoryStore. | Não afetado: compara individualmente os elementos do namespace. | Não é necessário atualizar por este CVE; mantenha verificações de propriedade do tenant no limite da aplicação. |
| Implantação hospedada do LangSmith. | O padrão LANGGRAPH_STORE_BACKEND=python usa AsyncPostgresStore e está no escopo com um pacote afetado. O backend separado grpc recebeu uma correção equivalente. | Verifique o backend configurado e a versão implantada; confirme a versão ou a atualização hospedada em vez de inferir exposição apenas pelo nome do produto. |
Fluxo de Ataque Passo a Paso
Confira o backend e os rótulos
A implantação precisa usar langgraph-checkpoint-postgres ou langgraph-checkpoint-sqlite anterior à 3.1.1 e depender do namespace para separar usuários ou tenants. Rótulos com prefixos em comum ou com % e _ tornam o limite relevante.
Uma leitura normal com escopo é feita
Uma solicitação autenticada da aplicação pesquisa um namespace como foo. O chamador não precisa enviar um payload especial; o namespace comum é a entrada do comparador vulnerável.
O backend achata e compara por padrão
O Store junta os rótulos com pontos e usa um prefixo LIKE terminado em %. Sem exigir o separador, foo pode corresponder a foobar; caracteres de padrão nos rótulos também podem ampliar o resultado.
Itens de um namespace irmão podem aparecer
Quando a aplicação trata namespaces como limites entre tenants, a busca ou a listagem pode retornar itens armazenados de outro usuário. É um problema de confidencialidade em leitura, não SQL injection nem acesso de escrita.
Atualize e teste o isolamento
Atualize os dois pacotes aplicáveis para 3.1.1 ou posterior. Teste prefixos de namespaces irmãos, rótulos literais com % e _, sufixos e a sensibilidade a maiúsculas/minúsculas do SQLite usando tenants de teste separados.
Código-Fonte: Vulnerável vs. Seguro
O predicado vulnerável trata toda string que começa com o namespace achatado como descendente. A correção adiciona uma comparação por igualdade exata e exige um ponto literal antes dos segmentos descendentes; também escapa barra invertida, % e _ no trecho LIKE. O commit upstream também substitui os padrões de prefixo/sufixo de list_namespaces por uma correspondência consciente de segmentos e ajusta a busca SQLite. Este é um trecho do código, não um módulo substituto.
Trecho de origem: libs/checkpoint-postgres/langgraph/store/postgres/base.py
def _prepare_batch_search_queries(op):
ns_condition = "TRUE"
ns_param = None
if op.namespace_prefix:
ns_condition = "store.prefix LIKE %s"
ns_param = (f"{_namespace_to_text(op.namespace_prefix)}%",)
return ns_condition, ns_param
def _escape_like_literal(text: str) -> str:
return text.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
def _namespace_prefix_condition(namespace_prefix: tuple[str, ...]) -> tuple[str, tuple]:
path = _namespace_to_text(namespace_prefix)
condition = r"(store.prefix = %s OR store.prefix LIKE %s ESCAPE '\\')"
return condition, (path, f"{_escape_like_literal(path)}.%")
if op.namespace_prefix:
ns_condition, ns_param = _namespace_prefix_condition(op.namespace_prefix)
Lista de Verificação de Segurança para Engenharia
- ✓Atualize
langgraph-checkpoint-postgreselanggraph-checkpoint-sqlitepara a versão 3.1.1 ou posterior em todas as instalações. - ✓Adicione regressões em que o rótulo de um tenant seja prefixo de outro, como
fooefoobar, e confirme que cada busca retorna apenas o namespace solicitado e seus descendentes. - ✓Teste rótulos com
%,_, barras invertidas e diferenças apenas de caixa usando exatamente o backend de banco de dados de produção. - ✓Teste
list_namespacescom prefixo, sufixo, curinga e caminho vazio; exija que*corresponda a exatamente um segmento, conforme documentado. - ✓Mantenha verificações de autorização no limite da aplicação; IDs de namespace opacos ou de formato fixo não substituem a validação de propriedade do tenant.