Como proteger dependências NPM? Guia completo de segurança da cadeia de suprimentos para desenvolvedores de API

Ashley Innocent

Ashley Innocent

1 abril 2026

Como proteger dependências NPM? Guia completo de segurança da cadeia de suprimentos para desenvolvedores de API

Resumo

Os ataques à cadeia de suprimentos do NPM aumentaram para mais de 3.000 pacotes maliciosos somente em 2024, e o comprometimento do Axios em março de 2026 provou que nem mesmo os 10 principais pacotes estão seguros. Este guia aborda todas as camadas de defesa que os desenvolvedores de API precisam: imposição de lockfile, bloqueio de scripts postinstall, verificação de proveniência, ferramentas de análise comportamental e escolhas arquitetônicas que diminuem sua superfície de ataque.

Introdução

O ataque à cadeia de suprimentos do Axios em 31 de março de 2026 não foi o primeiro comprometimento do npm. E não será o último. Mas com 83 milhões de downloads semanais e um RAT multiplataforma implantado através de uma única conta de mantenedor sequestrada, foi o mais ruidoso alerta que o ecossistema JavaScript recebeu.

Aqui está o que torna isso diferente do conselho usual de "atualize suas dependências": o ataque do Axios ignorou todas as defesas tradicionais. O código malicioso não estava no próprio Axios. Ele foi injetado através de uma dependência fantasma que acionou um hook `postinstall`. Lockfiles não ajudaram se você executou `npm install` durante a janela de ataque. O fixação de versão não ajudou se você ainda não havia fixado.

Desenvolvedores de API estão especialmente expostos. Seus scripts de teste, pipelines CI/CD, servidores mock e clientes HTTP todos usam o npm. Um único pacote comprometido em sua cadeia de ferramentas pode vazar chaves de API, credenciais de banco de dados e tokens de nuvem de sua máquina de desenvolvimento.

💡
Apidog elimina um grande vetor de ataque fornecendo um cliente HTTP integrado para teste de API, para que você não precise de Axios, node-fetch ou got em sua pilha de testes. Baixe o Apidog gratuitamente para reduzir sua superfície de dependência npm enquanto segue as estratégias de defesa abaixo.
button

Este guia abrange sete camadas de proteção, desde a higiene básica do lockfile até a análise comportamental avançada.

Camada 1: imposição de lockfile

Por que lockfiles importam

Um lockfile registra a versão exata de cada pacote e dependência transitiva no momento da instalação. Sem um lockfile, `npm install` resolve a versão mais recente que corresponde ao seu intervalo semver. Se seu `package.json` diz `"axios": "^1.14.0"` e uma versão maliciosa `1.14.1` existe no registro, você obtém a versão maliciosa.

As regras

Sempre comite seu lockfile. Seja `package-lock.json` (npm), `yarn.lock` (Yarn), `pnpm-lock.yaml` (pnpm) ou `bun.lock` (Bun), ele pertence ao controle de versão.

Use instalações congeladas em CI/CD. Nunca execute `npm install` em ambientes automatizados. Use o equivalente de lockfile congelado:

# npm
npm ci

# yarn
yarn install --frozen-lockfile

# pnpm
pnpm install --frozen-lockfile

# bun
bun install --frozen-lockfile

`npm ci` exclui `node_modules` e instala estritamente a partir do lockfile. Se o lockfile não corresponder ao `package.json`, ele falha. Isso evita surpresas na resolução.

Revise os diffs do lockfile em pull requests. Quando um PR modifica `package-lock.json`, verifique o que mudou. Novas dependências, aumentos de versão e alterações de URL de registro merecem escrutínio. Ferramentas automatizadas como o Socket.dev podem sinalizar alterações suspeitas no lockfile em revisões de PR.

A lacuna do lockfile

Lockfiles protegem contra a resolução inesperada de versões, mas não protegem contra a primeira instalação. Se você inicializar um projeto ou adicionar uma nova dependência durante uma janela de ataque, a versão maliciosa será fixada. É por isso que os lockfiles são a Camada 1, não a única camada.

Camada 2: desativar scripts postinstall

O principal vetor de ataque

O ataque do Axios, o ataque do ua-parser-js, o ataque do event-stream e dezenas de outros usaram o mesmo mecanismo: um script `postinstall` que executa código arbitrário durante o `npm install`. Este hook é executado antes que o código da sua aplicação seja executado, antes que você revise o pacote e antes que qualquer ferramenta de segurança em tempo de execução possa intervir.

Bloquear scripts globalmente

Adicione ao seu `.npmrc`:

ignore-scripts=true

Ou defina via CLI:

npm config set ignore-scripts true

Isso impede que todos os scripts de ciclo de vida (`preinstall`, `install`, `postinstall`, `prepare`) sejam executados durante a instalação do pacote.

Lidar com pacotes que precisam de scripts

Alguns pacotes exigem scripts postinstall para compilação nativa (como `bcrypt`, `sharp` ou `sqlite3`). Você tem duas opções:

Opção 1: Executar scripts seletivamente após a instalação

npm ci --ignore-scripts
npm rebuild bcrypt sharp

Opção 2: Usar uma lista de permissões (npm 10+)

Crie um `.scriptsrc.json` que permita que apenas pacotes confiáveis executem scripts:

{
  "allowScripts": {
    "bcrypt": true,
    "sharp": true
  }
}

Opção 3: Usar binários pré-construídos

Muitos pacotes que anteriormente precisavam de compilação nativa agora oferecem binários pré-construídos. `sharp`, por exemplo, envia binários pré-construídos para a maioria das plataformas, eliminando a necessidade de compilação postinstall. Verifique suas dependências; você pode precisar de menos exceções de script do que pensa.

A ressalva do PackageGate

Em janeiro de 2026, pesquisadores divulgaram seis vulnerabilidades de dia zero chamadas "PackageGate" que afetam npm, pnpm, vlt e Bun. Uma descoberta: dependências baseadas em Git podem conter arquivos de configuração que permitem a execução de código mesmo quando scripts de ciclo de vida estão desativados. Se seu `package.json` referencia URLs Git para dependências, `ignore-scripts` por si só não é suficiente. Fixe essas dependências em hashes de commit específicos e audite o conteúdo do repositório.

Camada 3: fixar versões exatas

Pare de usar intervalos semver

O comportamento padrão de `npm install --save` adiciona pacotes com um prefixo de circunflexo:

{
  "axios": "^1.14.0"
}

O `^` significa "compatível com 1.14.0", que resolve para a última versão 1.x.x. Durante o ataque do Axios, isso significava resolver para 1.14.1.

Fixe versões exatas em vez disso:

{
  "axios": "1.14.0"
}

Configure o npm para salvar versões exatas por padrão:

# .npmrc
save-exact=true
save-prefix=''

Usar substituições para dependências transitivas

Suas dependências diretas têm suas próprias dependências. Se uma dependência transitiva for comprometida, fixar sua dependência direta não ajuda. Use substituições para controlar a resolução transitiva:

{
  "overrides": {
    "axios": "1.14.0",
    "plain-crypto-js": "npm:empty-npm-package@1.0.0"
  }
}

Para Yarn:

{
  "resolutions": {
    "axios": "1.14.0"
  }
}

Para pnpm:

{
  "pnpm": {
    "overrides": {
      "axios": "1.14.0"
    }
  }
}

A troca

A fixação exata significa que você não recebe atualizações de patch automáticas. Você precisará aumentar as versões manualmente, o que gera sobrecarga de manutenção. A troca é deliberada: você está escolhendo atualizações controladas em vez de automáticas. Para projetos sensíveis à segurança, essa troca vale a pena.

Camada 4: verificar a proveniência do pacote

O que proveniência significa

A atestação de proveniência do npm vincula um pacote publicado ao seu código-fonte e ambiente de construção usando assinaturas Sigstore registradas em um livro-razão de transparência público. Quando um pacote é publicado a partir de um pipeline CI/CD com proveniência habilitada, o pacote inclui prova criptográfica de:

Como verificar a proveniência

npm audit signatures

Isso verifica se os pacotes instalados possuem atestações de proveniência válidas. Pacotes publicados manualmente de uma máquina de desenvolvedor não terão proveniência.

As versões maliciosas do Axios não possuíam vínculo de proveniência OIDC e não tinham commits correspondentes no GitHub. Se a verificação automatizada de proveniência fosse uma prática padrão, o ataque teria levantado bandeiras imediatamente.

Habilitar proveniência para seus próprios pacotes

Se você publica pacotes npm, habilite a proveniência em seu CI/CD:

# Exemplo de GitHub Actions
- uses: actions/setup-node@v4
  with:
    node-version: 20
    registry-url: https://registry.npmjs.org
- run: npm publish --provenance
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Adicione ao seu `.npmrc`:

provenance=true

Limitações

A proveniência é opcional. A maioria dos pacotes npm ainda não a possui. E a proveniência apenas prova onde um pacote foi construído. Não prova que o código-fonte é seguro. Um pipeline CI/CD comprometido poderia publicar um pacote malicioso com proveniência válida.

Camada 5: usar ferramentas de análise comportamental

Além da varredura de vulnerabilidades

Ferramentas tradicionais como `npm audit` e Snyk verificam bancos de dados de vulnerabilidades conhecidas (CVEs). Elas capturam problemas reportados, mas perdem ataques de dia zero. O comprometimento do Axios não estava em nenhum banco de dados de CVE quando foi publicado.

Ferramentas de análise comportamental examinam o que os pacotes fazem, não o que foi relatado sobre eles.

Socket.dev

Socket analisa o comportamento do pacote durante a instalação e execução. Ele sinaliza:

Quando integrado ao GitHub, o Socket comenta em PRs quando novas dependências exibem comportamentos suspeitos. A dependência `plain-crypto-js` do ataque do Axios teria acionado múltiplos alertas do Socket: código ofuscado, requisições de rede durante o postinstall e escritas no sistema de arquivos fora do diretório do pacote.

# Instalar Socket CLI
npm install -g @socketsecurity/cli

# Analisar seu projeto
socket scan

Snyk

Snyk fornece gerenciamento de vulnerabilidades com pontuações de risco, dados de maturidade de exploração e orientações de correção. É mais forte para vulnerabilidades conhecidas, mas mais fraco para detecção comportamental de dia zero.

# Instalar Snyk CLI
npm install -g snyk

# Testar seu projeto
snyk test

Abordagem em camadas

Use ambos. Socket detecta anomalias comportamentais que o Snyk perde. Snyk detecta vulnerabilidades conhecidas com um contexto mais rico do que o Socket oferece. Adicione `npm audit` como linha de base:

# Linha de base
npm audit

# Análise comportamental
socket scan

# Gerenciamento de vulnerabilidades
snyk test

Execute todos os três em CI/CD como portões. Qualquer descoberta crítica deve bloquear a construção.

Camada 6: minimizar sua superfície de dependência

A questão mais profunda

Cada pacote em seu `node_modules` é uma decisão de confiança. O ataque do Axios comprometeu um pacote com 83 milhões de downloads semanais. O projeto Node.js médio possui centenas de dependências transitórias. Cada uma é um potencial vetor de ataque.

A defesa mais eficaz é ter menos dependências para defender.

Auditar sua árvore de dependências

# Contar suas dependências totais
npm ls --all | wc -l

# Verificar duplicatas
npm ls --all | sort | uniq -c | sort -rn | head -20

Faça estas perguntas para cada dependência:

Alternativas nativas para pacotes comuns

Pacote Alternativa nativa Disponível desde
axios, node-fetch, got fetch (global) Node.js 18
uuid crypto.randomUUID() Node.js 19
dotenv --env-file flag Node.js 20.6
chalk util.styleText() Node.js 21.7
glob fs.glob() Node.js 22
path-to-regexp Native URL pattern API Node.js 23

Especificamente para testes de API

Fluxos de trabalho de teste de API geralmente dependem de bibliotecas de cliente HTTP, bibliotecas de asserção, executores de teste e servidores mock. Cada dependência é uma superfície de ataque.

Apidog substitui toda a pilha por uma única plataforma:

Mover seu fluxo de trabalho de teste de API para o Apidog elimina dezenas de dependências npm de sua infraestrutura de teste. Menos dependências significam menos decisões de confiança e menos vetores de ataque.

Experimente o Apidog gratuitamente para consolidar sua pilha de testes de API.

button

Camada 7: monitoramento de rede e tempo de execução

Bloquear domínios maliciosos conhecidos

Após qualquer ataque à cadeia de suprimentos, bloqueie a infraestrutura de comando e controle no nível da rede:

# Adicione a /etc/hosts
echo "0.0.0.0 sfrclak.com" | sudo tee -a /etc/hosts

Para ambientes CI/CD, restrinja o acesso à rede de saída a domínios conhecidos e seguros. A maioria dos processos de construção só precisa de acesso ao registro npm, ao seu host git e aos seus destinos de implantação. Todo o resto deve ser bloqueado por padrão.

Usar StepSecurity Harden-Runner para CI/CD

O Harden-Runner do StepSecurity monitora os fluxos de trabalho do GitHub Actions em tempo real. Ele detectou o dropper do Axios contatando o C2 em 1.1 segundos após o início de `npm install`. A ferramenta fornece:

# GitHub Actions
- uses: step-security/harden-runner@v2
  with:
    egress-policy: audit  # ou 'block' para modo estrito

Monitoramento de processo em tempo de execução

Para máquinas de desenvolvimento, considere ferramentas de detecção e resposta de endpoint (EDR) que sinalizam processos filhos suspeitos gerados pelo Node.js. O RAT do Axios gerou `osascript` (macOS), `cscript` (Windows) e `python3` (Linux) a partir do processo de instalação do npm. Esses padrões de processo filho são detectáveis.

Configuração .npmrc recomendada

Aqui está um arquivo `.npmrc` com segurança reforçada, combinando as camadas acima:

# Fixar versões exatas
save-exact=true
save-prefix=

# Desabilitar scripts de ciclo de vida
ignore-scripts=true

# Habilitar proveniência para publicação
provenance=true

# Usar o registro oficial
registry=https://registry.npmjs.org/

# Exigir 2FA para publicação
auth-type=web

# Limiar de nível de auditoria
audit-level=moderate

Comite este arquivo em seu repositório para que cada membro da equipe use as mesmas configurações de segurança.

Exemplo de pipeline de segurança CI/CD

Aqui está um fluxo de trabalho do GitHub Actions que impõe todas as sete camadas:

name: Secure Build
on: [push, pull_request]

jobs:
  security-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: step-security/harden-runner@v2
        with:
          egress-policy: audit

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      # Camada 1+2: Lockfile congelado, sem scripts
      - run: npm ci --ignore-scripts

      # Camada 3: Verificar versões inesperadas
      - run: npm ls --all > deps.txt

      # Camada 4: Verificar proveniência
      - run: npm audit signatures

      # Camada 5: Análise comportamental
      - run: npx socket scan

      # Camada 5: Varredura de vulnerabilidades
      - run: npx snyk test

      # Camada 1: Auditoria de linha de base
      - run: npm audit --audit-level=moderate

      # Reconstruir apenas dependências nativas permitidas
      - run: npm rebuild sharp bcrypt

O que vem a seguir para a segurança do npm

Proveniência obrigatória para pacotes populares

O npm está discutindo a exigência de atestação de proveniência para pacotes acima de um certo limite de download. Isso impediria a publicação manual baseada em token que possibilitou o ataque do Axios.

Aprovação de lançamento por duas pessoas

Assim como transações financeiras que exigem autorização dupla, pacotes com muitos downloads podem exigir um segundo mantenedor para aprovar os lançamentos. Uma única conta comprometida não seria suficiente.

Escopo de permissão em tempo de execução

Deno já restringe o que os scripts podem acessar (rede, sistema de arquivos, variáveis de ambiente) a menos que explicitamente concedido. O Node.js está explorando modelos de permissão semelhantes. Quando isso for lançado, os scripts postinstall precisariam de permissão explícita para fazer requisições de rede ou acessar o sistema de arquivos.

Convergência de gerenciadores de pacotes

O modelo de isolamento estrito do pnpm (os pacotes só podem acessar suas dependências declaradas) previne muitos ataques de confusão de dependências. À medida que o npm adota uma rigidez semelhante, a superfície de ataque diminui.

Perguntas Frequentes

O que é um ataque à cadeia de suprimentos no npm?

Um ataque à cadeia de suprimentos no npm visa a cadeia de dependências de software em vez de sua aplicação diretamente. Atacantes comprometem contas de mantenedores de pacotes, injetam código malicioso em pacotes populares ou publicam pacotes typosquat com nomes semelhantes. Quando você instala ou atualiza dependências, o código malicioso é executado em sua máquina ou em seu pipeline CI/CD, roubando credenciais, instalando backdoors ou exfiltrando dados.

É `npm audit` suficiente para proteger contra ataques à cadeia de suprimentos?

Não. `npm audit` verifica contra um banco de dados de vulnerabilidades conhecidas (CVEs). Ataques de dia zero como o comprometimento do Axios não estão em nenhum banco de dados de CVE quando acontecem. Você precisa de ferramentas de análise comportamental como o Socket.dev que examinam o que os pacotes fazem, não o que foi relatado sobre eles. Use `npm audit` como uma linha de base, não sua única defesa.

Devo parar de usar o npm completamente?

Não. O npm continua sendo o maior ecossistema de pacotes, e a maioria dos pacotes é segura. O objetivo é reduzir sua exposição através da fixação exata de versões, imposição de lockfile, bloqueio de scripts e minimização de dependências. Considere se cada dependência é necessária e use alternativas nativas sempre que possível.

Como o Apidog ajuda a reduzir o risco da cadeia de suprimentos do npm?

Apidog fornece um cliente HTTP integrado, executor de testes, servidor mock e gerador de documentação para desenvolvimento de API. Isso elimina a necessidade de pacotes npm como Axios, node-fetch, Jest, Express (para mocks) e outras dependências de teste. Menos dependências npm significam menos vetores de ataque em seu fluxo de trabalho de desenvolvimento de API.

O que é proveniência de pacote no npm?

A proveniência de pacote usa Sigstore para vincular criptograficamente um pacote publicado ao seu repositório de origem e ambiente de construção CI/CD. Ela prova onde e como um pacote foi construído. Você pode verificar a proveniência com `npm audit signatures`. Pacotes publicados manualmente de máquinas de desenvolvedores não possuem proveniência, o que é um sinal de alerta para pacotes com muitos downloads.

Quantos pacotes npm são maliciosos?

Snyk identificou mais de 3.000 pacotes npm maliciosos em 2024. No Q4 de 2025, a Sonatype bloqueou 120.612 ataques de malware em um único trimestre em npm, PyPI e outros registros. O número está crescendo. A maioria dos pacotes maliciosos são typosquats com poucos downloads, mas comprometimentos de alto perfil como o Axios provam que pacotes populares não estão imunes.

O que é a vulnerabilidade PackageGate?

PackageGate é um conjunto de seis vulnerabilidades de dia zero divulgadas em janeiro de 2026, afetando npm, pnpm, vlt e Bun. Uma descoberta mostra que dependências baseadas em Git podem conter arquivos de configuração que permitem a execução de código mesmo quando scripts de ciclo de vida estão desativados. Isso significa que `ignore-scripts` por si só não é suficiente se suas dependências referenciarem repositórios Git. Fixe as dependências Git em hashes de commit específicos.

Principais conclusões

Toda dependência é uma decisão de confiança. Quanto menos dependências você tiver, menor será sua superfície de ataque. Quanto mais camadas de verificação você aplicar, mais difícil será para um atacante passar. Construa suas defesas em profundidade, não isoladamente.

button

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs