
Um Scanner de Pacotes Público para a Comunidade
Scanner de cadeia de suprimentos npm extremamente simples, focado em Docker. Um único arquivo compose executa:
Esta é a edição somente contêiner. O projeto pode ser construído para escalar usando EC2, SQS e RDS. A maior parte já está configurada no conjunto de ferramentas.
scan.yml (listas de permissão, limites, YARA)scan_runs) pronto para uso~/.aws)docker-compose.yml – serviços: db, enumerator, fetcher, analyzer, dashboard, init-dbenumerator/ – Worker Node que constrói a fila NDJSONfetcher/ – Worker Node que baixa tarballs (+ envia para S3 se ativado)analyzer/ – Analisador estático Python (+ YARA inline opcional)dashboard/ – Aplicativo Streamlit (porta 8501)infra/migrations.sql – esquema principal do banco de dados (packages, versions, findings, scores, indexes)infra/20251106_scan_runs.sql – tabela de histórico de varredurasscan.yml – configuração de análise (regras, pontuação, listas de permissão, YARA)scripts/run_pipeline.sh – executa enumerate → fetch → analyzescripts/init_db.sh – inicializa o esquema do banco de dadosscripts/test_setup.sh – validação automatizada da instalaçãoSCANNING_GUIDE.md – estratégias de varredura detalhadas e exemplosPré-requisitos: Docker Desktop (ou engine) com Compose v2.
curl -fsSL https://raw.githubusercontent.com/MHaggis/Package-Inferno/main/install.sh | bash
Isso clona o repositório para ~/package-inferno e fornece instruções para começar.
Baixe e execute contêineres pré-construídos do GitHub Container Registry:
# Clone o repositório (para arquivos de configuração e scripts)
git clone https://github.com/MHaggis/Package-Inferno.git
cd Package-Inferno
# Execute com imagens pré-construídas
docker compose -f docker-compose.ghcr.yml up -d db
./scripts/init_db.sh
SEEDS="lodash,express" docker compose -f docker-compose.ghcr.yml run --rm enumerator
docker compose -f docker-compose.ghcr.yml run --rm fetcher
docker compose -f docker-compose.ghcr.yml run --rm analyzer
Imagens disponíveis:
ghcr.io/mhaggis/package-inferno/enumerator:mainghcr.io/mhaggis/package-inferno/fetcher:mainghcr.io/mhaggis/package-inferno/analyzer:mainExecute o script de teste para validar sua instalação:
./scripts/test_setup.sh
Isso irá:
docker compose up -d db
./scripts/init_db.sh
./scripts/run_pipeline.sh
docker compose up -d dashboard
# abra http://localhost:8501
Os resultados são salvos em ./out/findings/*.findings.json e na tabela findings quando o banco de dados está ativado.
O PackageInferno suporta múltiplas estratégias de varredura dependendo dos seus objetivos:
| Modo | Caso de Uso | Velocidade | Cobertura | Comando |
|---|---|---|---|---|
| Sementes Específicas | Testar/investigar pacotes conhecidos | Mais rápido | Direcionada | SEEDS="pkg1,pkg2" |
| Lote Pequeno | Validar configuração, varredura de amostra | Rápido | 10-100 pkgs | MAX_CHUNKS=2 CHUNK_LIMIT=10 |
| Registro Completo | Auditoria abrangente da cadeia de suprimentos | Horas-Dias | 2M+ pkgs | MAX_CHUNKS=0 CHUNK_LIMIT=100 |
| Feed de Alterações | Monitorar novas versões (incluído automaticamente) | Tempo real | Atualizações recentes | Integrado |
Direcione pacotes específicos que deseja analisar:
# Comando único com sementes
export SEEDS="lodash,express,axios"
./scripts/run_pipeline.sh
# Ou a partir de um arquivo
echo -e "react\nvue\nangular" > packages.txt
export SEEDS_FILE=packages.txt
./scripts/run_pipeline.sh
Como testei inicialmente: Usei SEEDS="is-odd,is-even" para validação rápida.
Varra pacotes paginados do registro npm:
# Limpe execuções anteriores
rm -rf downloads/* out/*
# Varra 2 páginas de 10 pacotes cada (20 pacotes)
export MAX_CHUNKS=2 # Número de páginas
export CHUNK_LIMIT=10 # Pacotes por página
unset SEEDS # Importante: desativar modo de sementes
# Execute etapas individualmente para melhor visibilidade
docker compose run --rm enumerator # Descobre e enfileira
docker compose run --rm fetcher # Baixa tarballs
docker compose run --rm analyzer # Varre ameaças
Exemplo de saída:
config: chunkLimit=10, maxChunks=2
checking recent changes feed...
changes feed: enqueued 2 new versions
enumerating via _all_docs (fresh scan)
page 1/2 count: 10
page 2/2 count: 10
done, enqueued 22 (22 new versions)
Varra todo o registro npm:
export MAX_CHUNKS=0 # 0 = ilimitado
export CHUNK_LIMIT=100 # Lotes maiores para eficiência
./scripts/run_pipeline.sh
Aviso: Isso será executado por horas/dias e varrerá centenas de milhares de pacotes. Monitore o espaço em disco e o tamanho do banco de dados.
O enumerator salva o estado em ./out/enumerator_state.json com a posição do cursor:
{
"last_seq": "0",
"last_startkey": "nome-do-pacote",
"last_run": "2025-11-23T19:24:49.123Z",
"last_processed": 22,
"last_new": 22
}
Simplesmente execute o pipeline novamente e ele retomará do último cursor:
./scripts/run_pipeline.sh # Retoma automaticamente
Para forçar uma nova varredura:
rm -f out/enumerator_state.json
./scripts/run_pipeline.sh
A partir de uma varredura de 2 páginas com 22 pacotes, aqui está o que o PackageInferno detectou:
-- Pacotes mais suspeitos por pontuação
SELECT p.name, s.score, s.label, COUNT(f.id) as findings
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN scores s ON v.id = s.version_id
LEFT JOIN findings f ON v.id = f.version_id
GROUP BY p.name, s.score, s.label
ORDER BY s.score DESC;
-- Resultados:
name | score | label | findings
-----------------------+-------+------------+----------
rendition | 606 | malicious | 153
vs-deploy | 454 | malicious | 119
--123hoodmane-pyodide | 213 | malicious | 46
O que tornou rendition tão suspeito?
url_outside_allowlist - Domínios não permitidossuspicious_pattern - Padrões Shell/evaladvanced_obfuscation - Codificação hex, XOR, arrays de stringbig_base64_blob - Payloads grandes codificados em base64url_in_code - URLs embutidas