Ponto Cego de Segurança.
Assistentes de IA produzem código funcional que silenciosamente omite os controles de segurança que um humano adicionaria por hábito — validação de entrada, autorização, codificação de saída, tratamento de segredos — porque "compila e retorna 200" parece estar pronto.
##Signs and Symptoms
Um revisor identifica um Ponto Cego de Segurança quando o código funciona no caminho feliz, mas os controles que um humano consciente de segurança adiciona por reflexo simplesmente não estão presentes. O modelo demonstra a funcionalidade, não a defesa. Sinais reveladores:
- Consultas / comandos concatenados como strings em vez de parametrizados (pontos de injeção de SQL/comando/LDAP).
- Entrada do usuário flui para a saída sem codificação (XSS refletido/armazenado) ou para
fs/child_process/fetchsem allow-list (path traversal, SSRF). - O endpoint autentica mas nunca autoriza — ele verifica quem você é, nunca se você pode acessar este registro (IDOR / autorização quebrada em nível de objeto).
- Segredos embutidos no código — chaves de API, tokens, senhas de banco de dados inline "para fazer funcionar."
- Controles ausentes por omissão: sem token CSRF, sem cabeçalhos de segurança, sem limite de taxa, criptografia fraca/legada (MD5, SHA-1,
Math.random()para tokens). - Teatro de comentários: um comentário
// validate inputou// TODO: add authocupa o lugar onde a verificação real deveria estar — a OX encontrou comentários redundantes em 90–100% do código de IA, muitas vezes substituindo a lógica ausente.
// Handler Express gerado por IA — parece completo, entrega três brechas
app.get("/api/orders/:id", authMiddleware, async (req, res) => {
const apiKey = "sk_live_8f3b2a91c7d44e0f"; // 1. segredo embutido no código
const order = await db.query(
`SELECT * FROM orders WHERE id = ${req.params.id}` // 2. injeção de SQL
);
res.send(`<h1>Order for ${order.customerName}</h1>`); // 3. XSS refletido
// nota: authMiddleware comprova o login, nunca verifica order.userId === req.user.id (IDOR)
});
Quatro vulnerabilidades distintas, zero testes falhando — o smell é o que não está ali.
##Reasons for the Problem
Por que os modelos produzem isso
- O alvo do treinamento é a plausibilidade, não a segurança. A previsão do próximo token otimiza para a maneira mais comum de escrever código, e os corpora públicos estão saturados de trechos de nível tutorial, com consultas concatenadas e sem autorização. A OX Security observa que os modelos "recorrem por padrão a abordagens inseguras porque são as mais frequentes nos dados de treinamento." A Carnegie Mellon constatou que 61% dos trechos de IA funcionam, mas apenas ~10,5% passam na revisão de segurança.
- "Pronto" é definido pelo caminho feliz. Um LLM otimiza para fazer a requisição visível ter sucesso. Controles de segurança não produzem nenhum sinal positivo em uma execução rápida, então são descartados — o que a OX chama de "inseguro por ignorância": código funcional com salvaguardas ausentes porque ninguém envolvido sabia o que era necessário.
- Sem contexto do repositório. O modelo não consegue ver seu helper
authorize(), seu esquema de validação ou seu gerenciador de segredos, então ele insere uma chave literal no código ou pula a verificação em vez de reutilizar um controle existente. - Bajulação + velocidade. Ele retorna exatamente o que você pediu ("adicione um endpoint de pedidos"), não o modelo de ameaças em torno disso, e gargalos como revisão e modelagem de ameaças são justamente o que o desenvolvimento em velocidade de IA elimina — a principal constatação da OX é que a velocidade, e não a taxa de defeitos por linha, é o que leva código vulnerável para produção.
- Defasagem do corte de treinamento. Os modelos recorrem a padrões de criptografia e de bibliotecas que eram adequados anos atrás (MD5, SHA-1, opções de TLS descontinuadas, fluxos de autenticação antigos).
Por que isso é prejudicial
- Explorabilidade direta. Estudos independentes citados pela OX: ~62% do código gerado por IA é entregue com uma vulnerabilidade; 86% falharam nas defesas contra XSS (CSET/Georgetown); a CodeRabbit mediu 2,74× mais XSS do que código humano; a Tenzai constatou que 0 de 15 aplicações criadas por IA definiam cabeçalhos de segurança ou proteção CSRF; a Escape.tech encontrou mais de 400 segredos expostos em 5.600 aplicações feitas por vibe coding.
- Invisível para testes e para leitores. Uma verificação de autorização ausente não tem teste que falhe nem diff para apontar, então passa direto pela revisão — e o volume de saída da IA significa que a revisão não consegue escalar para detectá-la.
- Dívida técnica que se acumula. Os dados da GitClear (refatoração caindo de 25% para <10% das linhas alteradas, copiar/colar em alta e agora superando as linhas movidas, blocos duplicados ~8× maiores) significam que o mesmo padrão inseguro é clonado por toda a base de código, multiplicando o raio de impacto de qualquer ponto cego isolado.
##Treatment
Táticas de revisão e de prompting
- Nomeie o modelo de ameaças no prompt. "Escreva este endpoint assumindo que o
idé controlado por um atacante; imponha autorização em nível de objeto, parametrize todas as consultas, codifique toda a saída e leia os segredos deprocess.env." Especificar o adversário inverte o padrão. - Force a reutilização de controles existentes. "Use nosso helper
authorize(user, 'order', id)e o validadororderSchema— não escreva uma nova validação." Isso combate diretamente a causa da falta de contexto do repositório (e o smell relacionado Código Duplicado). - Faça o modelo executar as ferramentas. Exija que ele rode
semgrep --config p/owasp-top-ten,gitleaks detect,npm audite sua configuração deeslint-plugin-security, e então corrija o que for sinalizado, antes de declarar concluído. - Peça os negativos explicitamente. "Liste as preocupações de autenticação, autorização, validação de entrada, codificação de saída e segredos para este handler e mostre onde cada uma é aplicada." Um espaço em branco nessa lista é o bug.
- Modele ameaças sobre o diff, não sobre a linha. As brechas perigosas são omissões, então revise perguntando "qual controle deveria estar aqui e não está?" em vez de procurar por linhas ruins.
A refatoração — parametrize a consulta (elimina a injeção), codifique a saída (elimina o XSS), adicione uma verificação de autorização em nível de objeto (elimina o IDOR) e Extraia o segredo embutido para a configuração:
// DEPOIS
app.get("/api/orders/:id",
authMiddleware,
validate(orderParamsSchema), // validação de entrada
async (req, res) => {
const order = await db.query(
"SELECT * FROM orders WHERE id = $1", [req.params.id] // parametrizado
);
if (!order || order.userId !== req.user.id) { // autorização em nível de objeto
return res.sendStatus(404);
}
res.json({ customerName: order.customerName }); // saída estruturada, codificada automaticamente
}
);
// segredo: process.env.STRIPE_API_KEY, carregado uma vez na inicialização, nunca inline
Onde o smell se espalhou por clonagem, corrija uma vez e faça Extrair Função do controle (requireOrderOwnership, escapeHtml) para que cada ponto de chamada compartilhe uma única implementação auditada em vez de N cópias.
##Detected by
- Gitleaks hardcoded secrets / generic-api-key
- Semgrep p/owasp-top-ten (e.g. sql-injection, xss, dangerous formatstring sinks)
- GitHub CodeQL js/sql-injection, js/xss, js/hardcoded-credentials, js/path-injection
- eslint-plugin-security detect-non-literal-fs-filename, detect-child-process, detect-eval-with-expression, detect-object-injection
- Bandit (Python) B105 hardcoded_password_string, B608 hardcoded_sql_expressions, B324 weak hashlib
- SonarQube / SonarSource Security Hotspots & Vulnerability rules (injection, weak cryptography, hardcoded credentials)
- npm audit / OWASP Dependency-Check known-vulnerable dependency detection