04Detalhamento · audit
Uma auditoria de segurança do meu próprio código com 134 agentes
Soltei um monte de caçador, aí botei céticos pra derrubar cada achado, e fiquei com o que sobrou de pé. 41 achados na entrada, 20 na saída — e por que os que morreram importam tanto quanto.
O problema
São 162 mil linhas e nenhum segundo par de olhos nelas. Eu dirijo a construção, escrevo as provas e reviso o resultado — tudo com a mesma cabeça, então o que não me passou pela cabeça antes também não passa depois. Não tinha um time de segurança pra revisar por mim, então montei um: dezenas de agentes varrendo o código ao mesmo tempo, cada um por um ângulo, e outros tantos tentando derrubar tudo que os primeiros achassem.
As restrições
- 01Adversarial por padrão. Verificador com a função de confirmar achado confirma ruído. A função de cada um era refutar, e na dúvida o veredito é "não é bug".
- 02Largura sem um ponto de vista só. Um prompt revisando tudo enxerga tudo do mesmo jeito. Vários caçadores, cada um com uma lente.
- 03Nenhum crítico falso. Um "CRÍTICO" errado queima confiança e um dia de trabalho de alguém.
- 04Reproduzível o bastante pra agir. Achado que eu não consigo amarrar num arquivo e num cenário de falha é boato.
A arquitetura
dimensões
divide o código em lentes de revisão (authz, injeção, segredos, RLS…)
caçadores, em paralelo
muitos agentes, cada um numa lente, cegos entre si
painel de céticos
cada achado verificado por refutadores — veredito padrão: não é bug
sobreviventes, ranqueados
41 achados na entrada → 20 confirmados na saída, por severidade
A forma importa mais do que a contagem de agentes: espalha pra achar, verifica cada afirmação de forma adversarial, guarda só o que sobrevive à maioria dos céticos. Os 134 agentes são o que essa forma custa num código deste tamanho. A disciplina é que nada entra no relatório sem passar por um painel que ganha ponto jogando o achado fora.
A parte difícil
Os achados interessantes foram os que morreram. Um caçador levantou o que parecia vulnerabilidade de verdade: uma query com service role furando o row-level security. Plausível, bem argumentada, errada. Um cético foi seguir a chamada na mão e achou a checagem de visibilidade que rodava antes.
Se eu tivesse acreditado nos caçadores, teria consertado um código que não estava quebrado — e mexer em autorização sem precisar é como se abre buraco novo. Entraram 41 achados e saíram 20. Os 21 que morreram são a razão de eu levar os outros a sério: auditoria que reporta tudo que suspeita me entrega uma lista de tarefa, não um diagnóstico.
Trade-offs
- Muito agente custa token de verdade. Subir um CRÍTICO falso, ou deixar passar um real, custa mais do que o processamento.
- Verificar de forma adversarial é mais lento do que acreditar no caçador. É essa lentidão que transforma 41 suspeitas em 20 fatos.
- Isso complementa análise estática e revisão humana, não substitui nenhuma das duas. A auditoria é forte em lógica e autorização, que é justo onde o linter é cego.
O que eu faria diferente
Eu fecharia o ciclo. Todo achado confirmado devia virar teste de regressão ou caso de eval, pra um buraco corrigido não reabrir em silêncio daqui a seis meses, quando alguém refatorar ali do lado. A auditoria achou os bugs uma vez; ela devia deixar para trás o alarme que pega eles na segunda.