
Uno scanner di pacchetti pubblico per la comunità
Scanner della supply chain npm incredibilmente semplice, Docker‑first. Un solo file compose esegue:
Questa è l'edizione solo contenitori. Il progetto può essere realizzato per scalare utilizzando EC2, SQS e RDS. La maggior parte è già predisposta nel toolset.
scan.yml (allowlist, soglie, YARA)scan_runs) pronto all'uso~/.aws)docker-compose.yml – servizi: db, enumerator, fetcher, analyzer, dashboard, init-dbenumerator/ – worker Node che crea la coda NDJSONfetcher/ – worker Node che scarica i tarball (+ caricamento su S3 se abilitato)analyzer/ – analizzatore statico Python (+ YARA inline opzionale)dashboard/ – app Streamlit (porta 8501)infra/migrations.sql – schema DB core (packages, versions, findings, scores, indexes)infra/20251106_scan_runs.sql – tabella della cronologia delle scansioniscan.yml – configurazione dell'analisi (regole, punteggi, allowlist, YARA)scripts/run_pipeline.sh – esegui enumerate → fetch → analyzescripts/init_db.sh – bootstrap dello schema DBscripts/test_setup.sh – validazione automatica dell'installazioneSCANNING_GUIDE.md – strategie di scansione dettagliate ed esempiPrerequisiti: Docker Desktop (o engine) con Compose v2.
curl -fsSL https://raw.githubusercontent.com/MHaggis/Package-Inferno/main/install.sh | bash
Questo clona il repo in ~/package-inferno e ti fornisce le istruzioni per iniziare.
Scarica ed esegui i contenitori precompilati da GitHub Container Registry:
# Clone the repo (for config files and scripts)
git clone https://github.com/MHaggis/Package-Inferno.git
cd Package-Inferno
# Run with pre-built images
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
Immagini disponibili:
ghcr.io/mhaggis/package-inferno/enumerator:mainghcr.io/mhaggis/package-inferno/fetcher:mainghcr.io/mhaggis/package-inferno/analyzer:mainEsegui lo script di test per validare la tua installazione:
./scripts/test_setup.sh
Questo script:
docker compose up -d db
./scripts/init_db.sh
./scripts/run_pipeline.sh
docker compose up -d dashboard
# open http://localhost:8501
I risultati finiscono in ./out/findings/*.findings.json e nella tabella findings quando il DB è abilitato.
PackageInferno supporta diverse strategie di scansione in base ai tuoi obiettivi:
| Modalità | Caso d'uso | Velocità | Copertura | Comando |
|---|---|---|---|---|
| Seeds specifici | Test/indagine su pacchetti noti | Massima | Mirata | SEEDS="pkg1,pkg2" |
| Piccolo lotto | Validazione del setup, scansione campione | Alta | 10-100 pkg | MAX_CHUNKS=2 CHUNK_LIMIT=10 |
| Registry completo | Audit completo della supply chain | Ore-Giorni | 2M+ pkg | MAX_CHUNKS=0 CHUNK_LIMIT=100 |
| Changes Feed | Monitora le nuove release (incluso automaticamente) | In tempo reale | Aggiornamenti recenti | Integrato |
Seleziona i pacchetti specifici che vuoi analizzare:
# Single command with seeds
export SEEDS="lodash,express,axios"
./scripts/run_pipeline.sh
# Or from a file
echo -e "react\nvue\nangular" > packages.txt
export SEEDS_FILE=packages.txt
./scripts/run_pipeline.sh
Come ho testato inizialmente: ho usato SEEDS="is-odd,is-even" per una validazione rapida.
Scansiona i pacchetti paginando il registry di npm:
# Clean previous runs
rm -rf downloads/* out/*
# Scan 2 pages of 10 packages each (20 packages)
export MAX_CHUNKS=2 # Number of pages
export CHUNK_LIMIT=10 # Packages per page
unset SEEDS # Important: disable seeds mode
# Run individual steps for better visibility
docker compose run --rm enumerator # Discovers and queues
docker compose run --rm fetcher # Downloads tarballs
docker compose run --rm analyzer # Scans for threats
Esempio di output:
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)
Scansiona l'intero registry npm:
export MAX_CHUNKS=0 # 0 = unbounded
export CHUNK_LIMIT=100 # Larger batches for efficiency
./scripts/run_pipeline.sh
Avviso: questa operazione richiederà ore/giorni e scansionerà centinaia di migliaia di pacchetti. Monitora lo spazio su disco e la dimensione del database.
L'enumerator salva lo stato in ./out/enumerator_state.json con la posizione del cursore:
{
"last_seq": "0",
"last_startkey": "package-name",
"last_run": "2025-11-23T19:24:49.123Z",
"last_processed": 22,
"last_new": 22
}
È sufficiente eseguire di nuovo la pipeline e riprenderà dall'ultimo cursore:
./scripts/run_pipeline.sh # Automatically resumes
Per forzare una nuova scansione:
rm -f out/enumerator_state.json
./scripts/run_pipeline.sh
Da una scansione di 2 pagine di 22 pacchetti, ecco cosa ha rilevato PackageInferno:
-- Top suspicious packages by score
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;
-- Results:
name | score | label | findings
-----------------------+-------+------------+----------
rendition | 606 | malicious | 153
vs-deploy | 454 | malicious | 119
--123hoodmane-pyodide | 213 | malicious | 46
Cosa rendeva rendition così sospetto?
url_outside_allowlist – domini non in allowlistsuspicious_pattern – pattern shell/evaladvanced_obfuscation – codifica hex, XOR, array di stringhebig_base64_blob – payload codificati di grandi dimensioniurl_in_code – URL incorporatiIl sistema di punteggio (configurato in scan.yml) aggrega questi risultati per produrre un punteggio di rischio e un'etichetta (clean, suspicious o malicious).