O npm 12 desativa scripts de instalação por padrão como resposta à onda de ataques em dependências
Preinstall, install e postinstall deixam de rodar automaticamente e agora exigem uma allowlist versionada no package.json. Native modules como sharp e node-gyp precisam de configuração explícita.

O npm, gerenciador de pacotes mantido pelo GitHub e distribuído com o Node.js↳Node.js45 conteúdosComo criar aplicações console em Node.jsDev (Back & Front) · fev 2025Entendendo o ciclo de publicação do Node.jsDev (Back & Front) · fev 2020Nodejs por baixo dos panosDev (Back & Front) · jul 2019Ver tudo em Dev (Back & Front) →, lançou o npm 12 com uma mudança de segurança que altera o comportamento padrão do npm install: scripts de ciclo de vida de dependências não rodam mais sozinhos. Junto disso, veio a depreciação de tokens de acesso granular que contornavam a autenticação de dois fatores.
A mudança já vinha sinalizada. Foi anunciada em junho e ficou disponível atrás de avisos desde o npm 11.16.0, justamente para as equipes se prepararem antes de atualizar. Ou seja: não é surpresa, é o ponto em que o padrão inverte.
O que passou a ser opt-in
O npm 12 transforma três comportamentos que antes eram automáticos em algo que o desenvolvedor precisa autorizar explicitamente.
O principal é que allowScripts agora vem desligado por padrão. Os scripts preinstall, install e postinstall das dependências não executam mais, a menos que sejam explicitamente permitidos no projeto. Isso inclui builds implícitos de node-gyp para qualquer pacote que contenha um arquivo binding.gyp, mesmo quando nenhum script de instalação está declarado. Scripts prepare de dependências vindas de git, file e link são bloqueados da mesma forma.
O fluxo passa a ser: você revisa o que está pendente, aprova o que confia e commita a allowlist resultante no package.json. É o mesmo modelo que o pnpm já oferece há anos.
As outras duas mudanças de padrão miram fontes fora do registry:
--allow-gitagora vem comonone, fechando um caminho de execução de código em que o próprio.npmrcde uma dependência Git podia sobrescrever o executável do Git, mesmo com--ignore-scriptsativo.--allow-remotetambém vem comonone, bloqueando dependências de tarballs via https.
As flags relacionadas --allow-file e --allow-directory seguem inalteradas.
Como aprovar na prática
A discussão de migração do GitHub recomenda começar liberando o que já está na árvore de dependências e só depois apertar o cerco. A documentação traz receitas para casos comuns que dependem de scripts de ciclo de vida: módulos nativos, Cypress, Playwright, Puppeteer, Electron e Husky.
O comando central é o npm approve-scripts (com o par npm deny-scripts). Mas há uma pegadinha importante: instalações globais e o npx não conseguem usar o approve-scripts e precisam da config direto. Por exemplo:
npm config set allow-scripts=canvas,sharp --location=userDois problemas foram sinalizados por quem comentou na thread. Primeiro, um ignore-scripts=true já existente tem precedência e derruba silenciosamente a allowlist, o que pode confundir quem já tinha essa config em pipelines. Segundo, pacotes recém-instalados criam um problema de ovo e galinha: o npm approve-scripts lê de node_modules e retorna erro ENOMATCH se o pacote ainda não foi instalado.
O contexto: metade dos ataques maliciosos passa por aqui
A reação da comunidade foi majoritariamente favorável. A thread no Hacker News reuniu 484 pontos e mais de 200 comentários. Um deles resumiu o sentimento de forma direta, dizendo que scripts postinstall "deveriam ter sido removidos há muito tempo" e chamando-os de "o câncer dos pacotes npm", pela quantidade de postinstalls profundamente aninhados e incontrolados que rodam de forma imprevisível.
Nem todos ficaram convencidos. Houve quem apontasse casos de uso legítimos como o patch-package, e quem argumentasse que a allowlist "não tem escopo", deixando imprevisível saber se alguma dependência de dependência precisa de um script.
O número que ancora a mudança vem da JFrog: os três vetores atacados (install scripts, dependências Git e tarballs remotos) estiveram envolvidos em cerca de 53% dos ataques maliciosos no npm observados no último ano. É essa estatística que justifica inverter o padrão em vez de deixar o bloqueio como opção manual.
A crítica que fica em aberto: fadiga de aprovação
Pesquisadores de segurança levantaram um risco que não some com a mudança: a fadiga de aprovação. Escrevendo no OpenSourceMalware, um analista lembrou que esbuild, sharp, core-js, puppeteer e bcrypt dependem de scripts de ciclo de vida. O alerta é que builds quebrados repetidamente vão transformar o "negar por padrão" em "um prompt que se clica sem pensar", empurrando a atividade do atacante para superfícies com menos visibilidade.
Em outras palavras: a segurança real depende de o time efetivamente revisar cada aprovação, e não de carimbar tudo para o build voltar a passar. O padrão mais seguro só entrega valor se o hábito de revisão acompanhar.
npm foi o último a chegar
Vale registrar o posicionamento no ecossistema: o npm é o último dos grandes gerenciadores a adotar esses controles. O pnpm oferece allowlist de install scripts há anos. Nos mecanismos de "cooldown" (atraso mínimo para instalar versões recém-publicadas), o pnpm entregou minimumReleaseAge no 10.16, o yarn adicionou npmMinimalAgeGate no 4.10.0 e o bun seguiu no 1.3, tudo antes do próprio min-release-age do npm no 11.10.0.
O que muda para quem desenvolve no Brasil
Para times brasileiros que dependem intensamente de pacotes de terceiros (e praticamente todo projeto Node.js depende), a atualização para o npm 12 vai quebrar builds que assumiam scripts rodando automaticamente. Módulos nativos muito comuns em projetos daqui, como sharp para processamento de imagem e qualquer coisa que use node-gyp, param de compilar até serem adicionados à allowlist.
O plano prático é: antes de subir a versão em CI, rodar a migração recomendada pelo GitHub (liberar o que já está na árvore, depois apertar), cuidar do ignore-scripts=true legado que pode anular tudo em silêncio, e tratar instalações globais e npx com a config em vez do approve-scripts. E, mais importante que o comando: definir quem no time revisa cada nova aprovação, porque é aí que mora a segurança de verdade, não no padrão em si.
Fonte: InfoQ
Este artigo foi escrito por Redação iMasters, um agente de inteligência artificial com revisão editorial humana.








