Access the english version here: Click Here
Olá pessoal.
Hoje quero trazer um pouquinho a mais de conhecimento a respeito de um tipo de ataque que tem se tornado cada vez mais frequente. O Supply Chain Attack, ou ataque de cadeia de suprimentos.
Bora lá ver como isso funciona no ecossistema npm e o que podemos fazer para mitigar esse risco.
Lembrando que aqui eu trouxe o npm apenas como exemplo, mas esse tipo de ataque pode ocorrer em outros gerenciadores de pacotes também!
Aqui você encontra uma ferramenta que eu desenvolvi para mitigar esse tipo de ataque: Safeinstall
Caso queira ver como a ferramenta funciona, dá uma olhada aqui SafeInstall
Introdução
Quantas vezes por dia você executa npm install? Para a maioria dos desenvolvedores JavaScript e Node.js, a resposta é: várias. Essa rotina aparentemente inocente — instalar uma dependência para resolver um problema — esconde um vetor de ataque cada vez mais explorado por cibercriminosos: o ataque de supply chain (ou ataque de cadeia de suprimentos).
Neste artigo, exploramos o que são esses ataques, como funcionam na prática usando um projeto de demonstração real, quais seriam as consequências em ambientes de produção e como você pode se proteger.
O projeto utilizado no artigo pode ser encontrado aqui: Projeto Exemplo
O que é um Supply Chain Attack?
Um ataque de supply chain ocorre quando um atacante compromete algum componente que faz parte da cadeia de suprimentos de software — ou seja, algo que os desenvolvedores ou sistemas confiam e utilizam sem questionar. No ecossistema npm, isso se materializa principalmente através de:
- Pacotes maliciosos criados do zero para parecerem legítimos
- Pacotes legítimos comprometidos (manutenção abandonada, conta hackeada, typosquatting)
-
Scripts de lifecycle que executam automaticamente durante
npm install
O ponto crítico é que o desenvolvedor não precisa fazer nada além de instalar o pacote. Não é necessário abrir um arquivo suspeito, clicar em um link ou executar um binário desconhecido. O simples ato de adicionar uma dependência ao package.json e rodar npm install pode ser suficiente para comprometer a máquina, o repositório ou a infraestrutura.
Scripts de Lifecycle: A Porta de Entrada
O npm define diversos scripts que são executados em momentos específicos do ciclo de vida de um pacote:
| Script | Momento de execução |
|---|---|
preinstall |
Antes do pacote ser instalado |
install |
Durante a instalação |
postinstall |
Imediatamente após a instalação — alvo preferido de ataques |
preuninstall |
Antes de desinstalar |
postuninstall |
Após desinstalar |
prepublish |
Antes de publicar no registro npm |
Qualquer pessoa que execute npm install rodará esses scripts automaticamente, sem avisos claros. É aí que reside o perigo.
Projeto de Demonstração: Estrutura e Código
Para ilustrar o vetor de ataque, criamos um projeto educacional composto por:
- Pacote “malicioso” — um pacote que parece útil, mas executa código nas fases de instalação
- Projeto vítima — um projeto que simplesmente depende desse pacote
Estrutura do Pacote Malicioso
O package.json do pacote define os scripts que serão executados:
{
"name": "utilidades-uteis",
"version": "1.0.0",
"description": "Pacote útil que parece legítimo mas executa código no post-install",
"main": "index.js",
"scripts": {
"postinstall": "node postinstall.js",
"preinstall": "node preinstall.js"
},
"keywords": ["utility", "helper"],
"author": "Atacante Anônimo",
"license": "MIT"
}
Note que postinstall e preinstall apontam para scripts Node.js. Esses scripts rodam automaticamente durante a instalação.
Script preinstall.js
Este script executa antes da instalação do pacote:
/**
* PREINSTALL - Roda ANTES da instalação do pacote
* Outra fase onde código malicioso pode executar
*/
console.log('\u001b[35m[preinstall]\u001b[0m Este script roda antes mesmo do pacote ser instalado!');
Em um ataque real, aqui poderia haver coleta inicial de dados ou preparação do ambiente.
Script postinstall.js — O Coração do Ataque
Aqui está o script que simula a exfiltração de dados sensíveis:
const fs = require('fs');
const path = require('path');
const os = require('os');
// Simula o que um atacante PODERIA coletar (apenas mostra, não envia)
const dadosSensiveis = {
executadoEm: new Date().toISOString(),
usuario: os.userInfo().username,
diretorioAtual: process.cwd(),
platform: process.platform,
nodeVersion: process.version,
// Um atacante real tentaria ler:
// env: process.env, // Tokens, senhas, API keys
// arquivos: fs.readdirSync(process.env.HOME)
};
// Cria arquivo de "prova" - em ataque real seria enviado para servidor
const arquivoProva = path.join(process.cwd(), 'PROVA_ATAQUE_SUPPLY_CHAIN.json');
fs.writeFileSync(arquivoProva, JSON.stringify(dadosSensiveis, null, 2), 'utf8');
console.log(`\u001b[31m[ATAQUE SIMULADO]\u001b[0m Dados coletados salvos em: ${arquivoProva}`);
console.log('\nEm um ataque REAL, isso seria enviado para o servidor do atacante.\n');
Exemplo de arquivo criado após o script executar
E ao executar a aplicação o usuário nem percebe o que aconteceu
Em uma versão maliciosa real, o atacante trocaria fs.writeFileSync por uma chamada HTTP (por exemplo, com https.request) para enviar esses dados a um servidor sob seu controle. O pacote também expõe um módulo legítimo (index.js) que faz algo útil — tornando o pacote plausível e reduzindo a suspeita.
Fluxo do Ataque
1. Desenvolvedor: npm install utilidades-uteis
2. npm baixa o pacote
3. npm executa preinstall → código malicioso #1
4. npm executa postinstall → código malicioso #2 (coleta dados)
5. Pacote instalado normalmente
6. Desenvolvedor não percebe que foi comprometido
Consequências em Ambientes Reais
O que poderia acontecer se esse fosse um ataque real? As consequências variam conforme o contexto da vítima.
1. Exfiltração de Credenciais e Segredos
-
Variáveis de ambiente (
process.env): tokens de API (AWS, GitHub, Stripe), chaves de banco de dados, senhas -
Arquivos
.env: credenciais em texto plano em vários projetos -
Arquivos de configuração:
~/.npmrc,~/.aws/credentials,~/.ssh/config
Impacto: Acesso a contas cloud, bancos de dados, repositórios privados e sistemas de terceiros.
2. Roubo de Chaves SSH e Certificados
- Leitura de
~/.ssh/(chaves privadas,known_hosts) - Uso das chaves para acessar servidores, GitHub, repositórios privados
Impacto: Invasão de servidores, clonagem de repositórios privados, commit de código malicioso em nome da vítima.
3. Cryptojacking
- Execução de minerador de criptomoeda em segundo plano
- Uso de CPU e energia da máquina ou servidor da vítima
Impacto: Custos elevados de infraestrutura, degradação de desempenho, possível violação de políticas de uso de cloud.
4. Backdoors e Persistência
- Instalação de ferramentas de acesso remoto
- Adição de tarefas agendadas ou scripts de inicialização
Impacto: Controle prolongado da máquina, espionagem, preparação para ataques futuros.
5. Modificação de Outros Pacotes
- Alteração de código em
node_modulesde outras dependências - Injeção de backdoors em bibliotecas usadas em produção
Impacto: Comprometimento em escala, propagação do ataque para todos os usuários da aplicação.
6. Em Ambientes CI/CD
- Acesso a secrets de pipelines (tokens, credenciais)
- Possibilidade de modificar artefatos de build ou imagens Docker
- Deploy de versões comprometidas em produção
Impacto: Comprometimento de toda a cadeia de entrega, desde o build até produção.
Casos Reais Documentados
| Caso | Ano | Descrição |
|---|---|---|
| event-stream | 2018 | Pacote com ~2M downloads/semana. Código malicioso adicionado para roubar carteiras Bitcoin. |
| ua-parser-js | 2021 | Biblioteca popular comprometida; executava minerador de criptomoeda. |
| coa e rc | 2021 | Typosquatting; pacotes roubavam variáveis de ambiente e as enviavam para servidor remoto. |
| node-ipc | 2022 | Adicionou código que alterava arquivos em máquinas de desenvolvedores de certas regiões geográficas. |
Medidas de Proteção
-
Use
--ignore-scriptsquando possível:npm install --ignore-scripts -
Audite dependências:
npm audit,npm audit fix -
Verifique scripts:
npm view nome-do-pacoteantes de instalar - Ferramentas especializadas: Socket.dev, Snyk para detecção de comportamentos suspeitos
-
Mantenha
package-lock.jsonversionado e revise mudanças - Verifique procedência: downloads, manutenção ativa, repositório aberto
Conclusão
O ecossistema npm é extremamente conveniente, mas essa conveniência traz riscos. O ato aparentemente trivial de npm install pode executar código arbitrário na sua máquina. A consciência sobre supply chain attacks e a adoção de boas práticas de segurança são fundamentais para reduzir a superfície de ataque e proteger projetos e infraestrutura.
O projeto de demonstração está disponível para que você possa testar o fluxo em um ambiente controlado e entender na prática como esses ataques funcionam.


Top comments (2)
Supply chain attacks on npm are genuinely underappreciated as a threat vector. The typosquatting problem alone is huge — most teams don't audit their dependency tree beyond direct dependencies. The transitive dependency problem is where real exposure lives. Running
npm auditcatches known CVEs but doesn't help with a newly published malicious package that hasn't been flagged yet. Lock files and a private registry mirror are about the best defense available today.Yes, unfortunately, the vulnerabilities that haven't yet been classified are even worse, unfortunately.
Until they are properly classified and a CVE (Critical Vulnerability Level) is established, many projects end up being contaminated 🙁