O arquivo que ninguém revisa
Em junho de 2026 apareceu um ataque de supply chain que se espalhava pelo registro npm abusando de um arquivo que a maioria das ferramentas de segurança simplesmente não inspeciona: o binding.gyp. Em vez de esconder o payload num preinstall ou postinstall, que hoje são os scripts mais vigiados do ecossistema, o malware embarca um binding.gyp weaponizado. Quando o npm install roda, o node-gyp lê esse arquivo e executa código controlado pelo atacante de forma automática, sem nenhum postinstall no package.json.
E o pior: é um worm auto-propagante. Uma máquina infectada não fica parada. Ela usa as credenciais que encontra para publicar novas versões contaminadas de outros pacotes, que por sua vez contaminam quem instalar. Cada npm install bem-sucedido vira um novo ponto de partida.
Se você constrói SaaS com ajuda de IA e instala dependência nova sem ler o que veio junto, este é exatamente o cenário que te pega.
O que o binding.gyp faz de verdade
binding.gyp é o arquivo de build de addon nativo. Pacotes que têm parte em C ou C++ (drivers de banco, libs de cripto, bindings de sistema) precisam compilar código nativo na hora da instalação. O node-gyp é a ferramenta que lê o binding.gyp, gera os arquivos de projeto e dispara o compilador. Isso é legítimo e roda há anos em milhares de pacotes.
O problema é que o formato .gyp não é um manifesto declarativo inofensivo. Ele descreve steps de build, e steps de build podem invocar comandos. Quando você executa npm install num pacote com addon nativo, o node-gyp age como um mini orquestrador de build que dispara processos externos. Um binding.gyp malicioso só precisa transformar esse momento de compilação em um momento de execução de comando arbitrário.
Pra quem defende, a distinção é cruel: um postinstall malicioso é uma linha suspeita no package.json, fácil de logar e bloquear. Um binding.gyp malicioso parece só mais um arquivo de build de um pacote que legitimamente compila código nativo.
Por que "bloquear postinstall" não pega isso
A defesa que virou padrão nos últimos anos foi mirar nos scripts de ciclo de vida. npm config set ignore-scripts true, políticas de CI que barram preinstall/postinstall, ferramentas que alertam quando um pacote novo tem hook de instalação. Tudo isso ataca o package.json.
O binding.gyp não é um script de ciclo de vida. Ele não aparece no package.json como hook. A execução não passa pelo caminho que essas defesas monitoram. Ela passa pelo node-gyp, que é uma ferramenta de build considerada confiável. Então:
- Scanner que só olha
scriptsnopackage.json: não vê nada. - Política de CI que barra
postinstall: não é acionada. - Revisor humano que confere os hooks de instalação: olha no lugar errado.
A execução acontece de qualquer jeito, durante uma etapa de compilação que parece rotina.
Onde isso te atinge: dev e CI
O gatilho é o mesmo npm install que você roda cem vezes por dia. Dois lugares concentram o risco.
Na máquina do dev, o install roda com as suas credenciais: tokens de npm, chaves de nuvem no ~/.aws, sessões de git, variáveis de ambiente carregadas. Um payload que executa nesse contexto tem acesso a tudo que você tem. E é exatamente esse acesso que alimenta a propagação: o worm precisa de um token de publicação para contaminar o próximo pacote.
No CI, é pior em escala. Pipelines rodam npm install ou npm ci de forma automatizada, muitas vezes com secrets de deploy, tokens de registry e credenciais de nuvem no ambiente. Um build contaminado pode exfiltrar esses secrets e publicar pacotes em nome da sua organização antes de qualquer humano perceber. Runner efêmero não salva você se o payload já rodou e já vazou o token.
Defesas práticas
Não existe bala de prata, mas dá pra reduzir muito a superfície.
1. `--ignore-scripts` onde der
Rodar npm install --ignore-scripts (ou setar ignore-scripts=true no .npmrc) barra os hooks de ciclo de vida. Isso não mata o vetor do binding.gyp sozinho, porque a compilação nativa segue caminho próprio, mas fecha a porta mais comum e força qualquer build nativo a ser explícito. Onde você não depende de addon nativo, deixe scripts desligados por padrão e ligue só quando precisar, de forma consciente.
2. Sandbox e container no CI
Trate o npm install como execução de código não confiável, porque é isso que ele é. Rode a instalação de dependências num container ou sandbox sem acesso aos secrets de produção. Separe a etapa de resolver dependências da etapa que usa credenciais sensíveis. Se o build precisa compilar código nativo, que compile num ambiente isolado, com rede restrita e sem os tokens de deploy no processo.
3. Pin + lockfile com integrity
Use lockfile (package-lock.json) com hashes de integridade e faça npm ci no CI em vez de npm install. Isso garante que você instala exatamente o artefato que revisou, não o que o registry serve hoje. Pin de versão não impede que uma versão maliciosa seja publicada, mas impede que ela entre no seu build sem você atualizar o lockfile de propósito, o que te dá um ponto de revisão.
4. Revise dependência nova, principalmente com código nativo
A presença de binding.gyp e de código C/C++ numa dependência nova é um sinal para olhar com atenção, não um detalhe a ignorar. Antes de adicionar um pacote que compila addon nativo, confira quem publica, o histórico de versões, e o que o build faz. Bump de versão de um pacote que antes não tinha código nativo e de repente tem é uma bandeira vermelha.
5. Vigie o registry, não só o seu repo
O worm se propaga publicando versões novas. Monitorar publicações inesperadas em pacotes que você mantém, e reagir rápido a versões estranhas de dependências, corta a cadeia. A telemetria de quem observa o npm de fora (como as equipes que rastreiam esses ataques) é parte legítima da defesa.
O ângulo de quem constrói com IA
SaaS feito com IA acelera a criação, mas também acelera a instalação de dependência sem revisão humana. Quando o fluxo é "o assistente sugeriu um pacote, adicionei, rodei", ninguém abriu o binding.gyp. Ninguém conferiu se aquela lib de verdade precisava compilar código nativo. O npm install roda, o node-gyp roda, e o payload roda junto.
A lição do worm de junho de 2026 não é sobre um arquivo específico. É sobre onde a execução acontece durante uma instalação. preinstall e postinstall foram fechados porque todo mundo passou a olhar pra eles. O atacante só andou um passo pro lado, pra um arquivo de build que ainda passa por confiável. A defesa que se cola a um único nome de campo sempre vai ficar um passo atrás.
Trate
npm installcomo execução de código não confiável, no dev e no CI, porque em 2026 é exatamente isso que ele é.




