npm install também executa código: como reduzir o risco antes de confiar em um pacote

O comando npm install parece uma operação de download. Na prática, ele resolve versões, monta uma árvore de dependências e pode executar scripts definidos por pacotes que você nunca escolheu diretamente. É uma diferença importante: instalar não significa apenas colocar arquivos em node_modules. Em determinadas configurações, significa permitir que código de terceiros rode na máquina.

Isso não transforma todo postinstall em malware. Pacotes usam scripts para compilar módulos nativos, baixar binários ou preparar artefatos. O problema é a confiança implícita, especialmente quando uma dependência transitiva consegue herdar o mesmo ambiente que contém tokens, chaves SSH, credenciais de registry e acesso ao filesystem.

A árvore é maior do que o package.json

Um projeto com vinte dependências diretas pode instalar centenas ou milhares de pacotes transitivos. O arquivo de lock registra versões e integridade dos artefatos, o que é essencial para repetibilidade, mas não afirma que aquele código é seguro. Um pacote malicioso pode ter hash perfeitamente válido; o lock apenas garante que você recebeu exatamente o conteúdo registrado.

npm audit também resolve outro problema. Ele compara a árvore com vulnerabilidades conhecidas. Isso ajuda a encontrar versões afetadas, mas não é um detector geral de malware, abandono, troca suspeita de mantenedor ou script inesperado recém-publicado.

Comece sem executar scripts

Quando você está avaliando uma dependência nova ou revisando uma atualização relevante, instalar primeiro com scripts desativados reduz a superfície imediata. A opção existe na CLI e pode ser adotada como política do projeto.

npm install --ignore-scripts
npm audit
npm ls --depth=0

Depois, verifique se algum pacote realmente depende de uma etapa de instalação. A documentação atual do npm também oferece controles explícitos para permitir ou negar scripts por dependência. A ideia é trocar “todo mundo pode executar” por uma lista consciente do que precisa dessa permissão.

Atrasar novidade pode ser uma defesa

A opção min-release-age impede que a resolução escolha versões publicadas há menos de determinado número de dias. Não é uma cura, mas cria uma janela para que versões comprometidas sejam denunciadas ou removidas antes de chegarem automaticamente ao seu CI. Correções urgentes podem precisar de exceção, e a própria CLI avisa quando a janela bloqueia uma versão que corrigiria uma vulnerabilidade.

# .npmrc
min-release-age=2
ignore-scripts=true

Dois dias não são um número mágico. Um time pode escolher uma janela maior para aplicações estáveis e abrir exceções específicas quando necessário. O valor está em impedir que “publicado agora” vire “executado em produção agora” sem nenhuma pausa humana.

Revise a mudança, não só o nome

  • Leia o diff do lockfile e confirme por que novas dependências entraram.
  • Inspecione scripts de lifecycle, binários e arquivos publicados no pacote.
  • Observe mudanças de mantenedor, repositório e padrão de releases.
  • Prefira versões exatas e use npm ci no CI para respeitar o lockfile.
  • Execute builds de pull requests sem segredos de produção e com permissões mínimas.

Proveniência e publicação confiável ajudam a verificar de onde um pacote veio, mas não substituem a análise do que ele faz. Uma release legitimamente publicada por uma conta comprometida ainda pode ser perigosa. Segurança de supply chain funciona em camadas: identidade, revisão, atraso, isolamento e capacidade de responder.

O CI não deve carregar as chaves da cidade

Mesmo com todas as verificações, trate a instalação como execução de código não totalmente confiável. Separe o job que instala e testa de etapas com credenciais de deploy, restrinja tokens por escopo e duração e evite expor segredos a contribuições externas. Se um pacote escapar da triagem, o estrago possível deve continuar limitado.

O objetivo não é auditar manualmente cada linha de cada dependência. Isso seria impraticável. É retirar a confiança automática dos pontos de maior risco e tornar exceções visíveis. Um npm install seguro continua sendo conveniente, só deixa de ser uma caixa-preta com passe livre.

Fontes