ConstructiCat Logo
CodeBust.
Browse section ▾

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/fetch sem 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 input ou // TODO: add auth ocupa 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 de process.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 validador orderSchema — 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 audit e sua configuração de eslint-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