Saída Executada Sem Validação (Unvalidated Executed Output) é um smell de IA, ou seja, um sinal de problema em sistemas com LLM, do grupo Segurança. Código, SQL ou comandos gerados pelo modelo rodam direto, sem checagem nem sandbox.
O teste rodou no diretório real do repositório, na máquina do CI, com acesso de escrita. A pasta de fixtures, usada por todos os outros testes, sumiu.
Ninguém atacou nada. O modelo escreveu um código plausível, com uma intenção razoável (“limpar”), e o sistema executou sem olhar. O OWASP Top 10 for LLM Applications de 2025 trata isso como manuseio inadequado de saída (LLM05): a saída do modelo vai direto para um interpretador, um banco ou um shell, como se fosse código revisado.
Sinais de Saída Executada Sem Validação:
Código, SQL, comandos de shell ou consultas gerados pelo modelo rodam direto.
A execução acontece no ambiente real: servidor da aplicação, repositório, banco de produção.
Não há checagem do que foi gerado antes de rodar (parser, lista de permissões, análise estática).
O processo que executa tem acesso a rede, segredos ou arquivos que não precisa.
Não existe limite de tempo, memória ou de sistema de arquivos.
flowchart LR
M(["1. Modelo gera código"]):::llm --> X["2. Executa direto"]:::tool
X --> R[("3. Repositório, banco, rede, segredos")]:::store
O modelo gera algo executável.
O código roda sem passar por nenhuma checagem.
Tem acesso a tudo que o processo que o executou tem.
Por que acontece
Executar é a forma de checar. Para saber se o teste funciona, é preciso rodar. O passo de isolar fica para depois.
O código gerado parece inofensivo. Na maioria das vezes, é.
Sandbox dá trabalho. Containers, permissões e limites exigem infraestrutura que o protótipo não tinha.
O ambiente de CI parece descartável. Até que ele tenha segredos de deploy.
Duas camadas, dois trabalhos
A proteção tem duas partes, e cada uma cobre o que a outra deixa passar:
Camada
Pergunta que responde
Exemplos
Validação
O que pode rodar?
Parser de SQL, lista de comandos permitidos, análise estática do código
Isolamento
Onde roda e com que acesso?
Container sem rede, sistema de arquivos só leitura, limites de CPU, memória e tempo
O erro comum é escolher uma só. Pior ainda é a validação por lista negra: um regex que bloqueia rm -rf não pega shutil.rmtree, os.remove em loop ou find . -delete. Lista de permissões diz o que pode; tudo o mais é recusado.
Quanto custa ignorar
Dano local: arquivos apagados, dados alterados, processos derrubados.
Vazamento: código gerado que lê variáveis de ambiente e envia para fora.
Injeção: uma instrução num arquivo lido pelo agente vira código executado com o acesso do sistema.
Recursos: loops infinitos ou consumo de memória derrubam a máquina.
Sempre. Checar o que foi gerado (parser, lista de permissões, análise estática) e rodar num ambiente isolado, descartável, sem rede e sem segredos, com limites.
Exemplo trabalhado: SQL gerado
Num text-to-SQL, a validação lê o SQL como árvore, não como texto. Este trecho usa a biblioteca sqlglot e aceita só um SELECT sobre as visões aprovadas:
import sqlglotfrom sqlglot import expALLOWED = {"vendas_por_mes", "pedidos_resumo"}def check_sql(sql: str) -> str: statements = sqlglot.parse(sql, read="postgres") if len(statements) != 1 or not isinstance(statements[0], exp.Select): raise ValueError("Envie um único SELECT.") tree = statements[0] ctes = {cte.alias for cte in tree.find_all(exp.CTE)} tables = {t.name for t in tree.find_all(exp.Table)} - ctes if not tables <= ALLOWED: raise ValueError(f"Tabelas fora da lista: {sorted(tables - ALLOWED)}") return tree.sql(dialect="postgres")
Veja o que acontece com três saídas do modelo:
SQL gerado
Resultado
SELECT mes, total FROM vendas_por_mes WHERE ano = 2026
Passa
SELECT 1; DROP TABLE customers
Recusado: mais de um comando
WITH d AS (DELETE FROM customers RETURNING *) SELECT * FROM d
Recusado: tabela fora da lista
O terceiro caso mostra por que a árvore importa: o comando começa com SELECT, mas carrega um DELETE dentro. Mesmo assim, a validação não substitui o isolamento. O SQL aprovado ainda roda com um usuário só de leitura, numa réplica, com tempo máximo.
Exemplo trabalhado: código gerado
Para o gerador de testes, o isolamento é um container descartável por execução:
Com isso, a fixture do exemplo falha com erro de permissão em vez de apagar a pasta. O erro volta para o modelo, que corrige o teste. O resultado sai pelo diretório /out, o único com escrita.
O que você ganha
O pior caso de um código ruim é um container destruído.
Comandos fora da lista nunca rodam.
Segredos e rede fora do alcance do código gerado.
Erros de validação viram informação para o modelo corrigir.
Quando ignorar
Ambiente já isolado. Um serviço de execução de código do provedor, ou um container sem rede criado para cada sessão, já é a proteção. Confira o que ele permite.
Revisão humana antes de cada execução. Um desenvolvedor que lê e aprova cada comando no terminal. Funciona enquanto a pessoa lê de verdade.
Fora desses casos, trate a saída do modelo como trataria um formulário preenchido por um desconhecido.
É esse smell?
Perguntas rápidas
O que é Saída Executada Sem Validação?
Saída Executada Sem Validação (Unvalidated Executed Output) é um smell de IA, ou seja, um sinal de problema em sistemas com LLM, do grupo Segurança. Código, SQL ou comandos gerados pelo modelo rodam direto, sem checagem nem sandbox.
Como corrigir Saída Executada Sem Validação?
Com Validar Antes de Executar. Cada refatoração traz o passo a passo seguro, com eval antes e depois.
Onde Saída Executada Sem Validação aparece na prática?