Pitch: Fiz um "segurança de balada" pros pacotes que o agente de IA instala
Eu construo a Prumo, uma plataforma de estudos pra ENEM e concursos, quase toda com Claude Code. Um dia abri o package-lock.json e tinha 660 pacotes. Eu tinha escolhido uns 20.
O agente roda npm install e pip install sozinho, e qualquer pacote pode executar código na sua máquina no momento da instalação, pelo script de postinstall. O npm audit não ajuda nesse caso, porque só conhece ataque que alguém já reportou. Uma versão envenenada publicada há dez minutos passa limpa.
Então fiz o bouncer, um hook de PreToolUse do Claude Code que analisa o pacote antes da instalação acontecer.
Como funciona
O hook lê o comando que o agente vai rodar (npm i, npx, pnpm add, pip install, uv add, curl | sh, claude mcp add...) e baixa exatamente o arquivo que o gerenciador de pacotes instalaria. Ele descompacta em memória e nunca executa nada.
Cada arquivo recebe um papel: instalação (scripts de lifecycle, setup.py), entrada (o que roda no import), runtime ou auxiliar (testes, docs, CI). O mesmo padrão pesa muito mais num postinstall do que num arquivo de teste. Combinação também pesa mais que sinal isolado. O SDK da AWS ler ~/.aws/credentials é normal. Um postinstall ler o mesmo arquivo do lado de uma chamada HTTP não é.
Ele procura:
- roubo de credencial (segredo e rede lado a lado em código de instalação)
- código ofuscado, incluindo base64 que decodifica pra um comando
- typosquat (reqeusts, expres) e nome que não existe no registro
- prompt injection em descrição de ferramenta MCP e em skills
- script que mexe na config do agente (~/.claude/settings.json, .cursor/mcp.json)
- arquivo .pth que roda código toda vez que o Python abre
Detonação
Análise estática dá pra burlar, então tem um modo que roda o pacote num container Docker sem rede. O usuário é falso e a home dele está cheia de credencial de isca: chave AWS, token do npm e do GitHub, chave SSH. Um DNS falso responde tudo com 127.0.0.1, e os listeners descriptografam HTTPS com uma CA que só existe dentro da imagem. Dá pra ver o pacote mandando o token falso pro servidor do atacante.
Números
-
Os 149 pacotes mais usados de npm e PyPI saem limpos (next, typescript, torch, numpy, prisma...).
-
No dataset de malware real da DataDog, só a análise estática pega 59% no npm e 65% no PyPI. O que escapa é quase
-
Os 149 pacotes mais usados de npm e PyPI saem limpos (next, typescript, torch, numpy, prisma...).
-
No dataset de malware real da DataDog, só a análise estática pega 59% no npm e 65% no PyPI. O que escapa é quase sempre pacote que é só binário compilado, ou versão comprometida de biblioteca real com poucas linhas escondidas num bundle minificado.
-
Rodei na Prumo: 660 pacotes e 31.809 arquivos em 25 segundos, tudo limpo. O teste achou dois falsos positivos no próprio bouncer, um deles com o AGENTS.md que o create-next-app gera, e corrigi no mesmo dia.
O benchmark com malware real roda no GitHub Actions, numa máquina descartável, e nunca executa as amostras.
É open source (MIT) e não tem dependências. Funciona como plugin do Claude Code:
/plugin marketplace add burnoutscript/bouncer
/plugin install bouncer@bouncer
Se achar falso positivo ou um pacote malicioso que passou, abre uma issue com o nome e a versão.