flawopen.com/AI Security/semantic-kernel-inmemory-vector-filter-cve-2026-26030
Semantic Kernel CVE-2026-26030: injeção em filtros
Filtros vetoriais influenciados por prompts contornavam as verificações AST e chegavam ao eval do Python. Atualize para 1.39.4 ou superior.[1], [4]
Imagine uma bibliotecária que recebe um cartão com uma regra de busca, verifica algumas palavras conhecidas e depois manda o computador executar o cartão como um pequeno programa. Quem pode influenciar o cartão pode explorar falhas nessa verificação. A CVE-2026-26030 permitia que um filtro influenciado pelo modelo passasse da consulta de dados à execução de código no processo da aplicação.[4]
Conceitos Centrais e Termos
InMemoryVectorStore- Armazenamento vetorial no processo do Semantic Kernel; a busca pode filtrar registros antes de retornar resultados.[4]
Expressão de filtro- Predicado que decide se um registro pode aparecer nos resultados da busca vetorial. No caminho Python afetado, filtros em texto eram analisados e avaliados como expressões Python.[4]
Árvore Sintática Abstrata (AST)- Representação estruturada do código analisado. Uma validação incompleta pode deixar caminhos para introspecção de objetos Python.[2], [4]
Injeção de prompt- Texto não confiável influencia o modelo a realizar uma ação não prevista. O risco depende de a aplicação expor o filtro vulnerável à entrada controlada pelo modelo.[4]
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-94
Fluxo de Ataque Passo a Paso
Conteúdo não confiável influencia o filtro escolhido pelo modelo
O ataque exige um caminho de injeção de prompt que influencie a entrada do agente e um Search Plugin com o filtro padrão do InMemoryVectorStore. Uma expressão gerada pelo modelo não é confiável só por vir de uma chamada de ferramenta tipada.[4]
O filtro vira código Python
Antes da correção, o filtro era analisado como AST e avaliado sem builtins, mas as verificações não restringiam suficientemente o acesso ao modelo de objetos. A versão 1.39.4 mantém ast.Subscript para acessar campos dos registros e combina a lista de nós permitidos com o bloqueio de atributos perigosos, nomes isolados restritos aos parâmetros lambda e uma lista de chamadas permitidas. O código upstream não rejeita subscritos por si só; eval sem builtins não é um sandbox.[2], [4]
A execução chega ao processo da aplicação
Se a expressão contornar a validação durante a busca, lógica influenciada pelo atacante pode executar no processo Python do agente. O acesso fica limitado às permissões, ambiente, credenciais e alcance de rede desse processo.[4]
Corrija a fronteira do parser e investigue a exposição
Atualize semantic-kernel para 1.39.4 ou superior. O patch verifica atributos perigosos e restringe nomes isolados ao parâmetro lambda; a análise também documenta listas permitidas de nós AST e funções. Investigue anomalias de processos, rede e credenciais no período afetado.[1], [2], [3], [4]
Código-Fonte: Vulnerável vs. Seguro
O painel vulnerável mostra um padrão representativo, não o código literal do produto: um valor controlado pelo modelo é interpolado na sintaxe Python antes de eval. O painel seguro destaca as verificações upstream da versão 1.39.4. A lista de AST configurada inclui ast.Subscript para acessar campos dos registros; o patch combina essa lista com o bloqueio de atributos perigosos, nomes isolados limitados a lambda e chamadas permitidas. Remover builtins não transforma eval em sandbox. Atualize o pacote; não copie este trecho como validador independente.[2], [6], [4]
# Padrão representativo anterior à correção: o texto do modelo altera a expressão.
filter_text = f"lambda x: x.city == '{model_selected_city}'"
tree = ast.parse(filter_text, mode="eval")
code = compile(tree, filename="<filter>", mode="eval")
filter_fn = eval(code, {"__builtins__": {}}, {}) # nosec
def validate_filter(self, tree):
# Verificações upstream 1.39.4 em foco; mensagens de exceção abreviadas.
# Filtros no nível superior devem ser expressões lambda.
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
raise VectorStoreOperationException("Filter must be a lambda expression")
lambda_param_names = {arg.arg for arg in tree.body.args.args}
for node in ast.walk(tree):
if type(node) not in self.allowed_filter_ast_nodes:
raise VectorStoreOperationException("AST node type is not allowed")
if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
raise VectorStoreOperationException("Dangerous attribute is not allowed")
if isinstance(node, ast.Name) and node.id not in lambda_param_names:
raise VectorStoreOperationException("Only lambda parameter names are allowed")
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
func_name = node.func.id
elif isinstance(node.func, ast.Attribute):
func_name = node.func.attr
else:
func_name = None
if func_name and func_name not in self.allowed_filter_functions:
raise VectorStoreOperationException("Function is not allowed")
code = compile(tree, filename="<filter>", mode="eval")
func = eval(code, {"__builtins__": {}}, {}) # nosec
Lista de Verificação de Segurança para Engenharia
- ✓Localize ambientes Python implantados com semantic-kernel e registre a versão resolvida, inclusive em contêineres, notebooks, workers e imagens de CI.[4]
- ✓Atualize instalações afetadas para 1.39.4 ou superior, regenere lockfiles e reconstrua imagens com dependências corrigidas.[1], [3]
- ✓Até atualizar, desative em produção o filtro do InMemoryVectorStore; o fornecedor recomenda evitar esse armazenamento em produção como medida temporária.[1]
- ✓Em todo PR que adicionar ou alterar um filtro de busca vetorial, inclua testes que provem que texto do usuário, conteúdo recuperado e argumentos fornecidos pelo modelo não alteram a estrutura analisada do filtro; rejeite formas não permitidas.[4]
- ✓Adicione teste de regressão que rejeite atributos AST bloqueados e nomes fora do parâmetro lambda, sem payload executável.[2]
- ✓Represente filtros escolhidos pelo modelo como dados tipados, com listas explícitas de campos e operadores permitidos; adicione testes que rejeitem strings de expressão e campos ou operadores desconhecidos.
- ✓Execute agentes com acesso mínimo a arquivos, rede e credenciais para limitar o impacto de futuras falhas.[4]
- ✓Adicione um teste de regressão de detecção no host do agente que gere eventos representativos de processos filhos e conexões externas e confirme que a regra de telemetria implantada alerta para ambos.[4]