Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/securest8/npm-incident-response
Scanner di VulnerabilitàMeccanismi di PersistenzaAnalisi MalwareDigital ForensicsSicurezza della Supply ChainRisposta agli Incidenti
GitHubsecurest8/npm-incident-response

npm-incident-response

Scanner per l'attacco alla supply chain keyv/cacheable: rileva pacchetti npm compromessi, verifica gli hash dei payload e individua implant di persistenza in modalità repo e host.

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository
2113 giorni faNon ancora revisionato

npm-incident-response

English | Português

Scanner autonomo per l'incidente della supply chain keyv/cacheable ("Shai-Hulud: Here We Go Again", 4 agosto 2026) — oltre 440 pacchetti npm compromessi da un worm auto-propagante che ruba le credenziali cloud/CI e impianta la persistenza con un dead-man's switch.

Rileva, in pochi minuti e senza installare nulla:

  • Pacchetti compromessi in package-lock.json, npm-shrinkwrap.json, yarn.lock (v1 e Berry), pnpm-lock.yaml e bun.lock — incluse le dipendenze transitive, con l'intera catena (es. eslint → file-entry-cache → flat-cache → [email protected]);
  • Payload installati in node_modules (nome + hash SHA-256 degli artefatti noti);
  • Varianti non ancora presenti nelle liste IOC (euristica: script di lifecycle sospetti, file con i nomi del worm) — sempre marcate come SUSPECT, mai confermate senza hash;
  • Impianti di persistenza sull'host: LaunchAgent (macOS), servizio utente systemd + linger (Linux), hook in .claude/settings.json e .vscode/tasks.json, artefatti temporanei (bun-dl-*);
  • Il dead-man's switch: l'impianto monitora un token GitHub ed esegue un comando remoto quando la revoca restituisce 4xx. Ruotare le credenziali prima di pulire l'host fa scattare la trappola — il report ti avvisa e l'ordine di risposta qui sotto evita l'errore.

Comprendere l'attacco

  1. L'account del maintainer delle famiglie keyv/cacheable è stato compromesso; l'attaccante ha pubblicato nuove versioni con un hook "preinstall": "node setup.mjs" — codice che viene eseguito prima dell'installazione del pacchetto, con i privilegi di chi ha lanciato npm install.
  2. setup.mjs scarica il runtime Bun da GitHub ed esegue il payload al suo interno — evasione contro gli strumenti che monitorano solo i processi node.
  3. Math_Symbol.js (~728 KB, offuscato) ruba le credenziali: metadati delle istanze AWS, chiavi AWS/GCP/Azure, token Vault, service account Kubernetes, segreti di GitHub Actions, token npm, più una scansione generica con regex per chiavi private e bearer token su disco.
  4. È un worm: con il token npm rubato, inietta lo stesso hook in altri pacchetti che quell'identità può pubblicare, ricalcola gli hash di integrità e ripubblica. È così che è passato da ~10 a centinaia di pacchetti.
  5. Esfiltra senza un C2 fisso (repository GitHub creati al volo, DNS) e lascia una trappola dietro di sé — vedi sotto.

I due vettori (il secondo è più sottile)

  • Vettore A — installazione: chiunque abbia eseguito npm install/npm ci con gli script di lifecycle abilitati dal 2026-08-04 09:35 UTC. Con --ignore-scripts, l'hook non è stato eseguito.
  • Vettore B — clone: il repository sorgente è stato dotato di hook di avvio automatico in .claude/settings.json (SessionStart) e .vscode/tasks.json (folderOpen) che eseguono il loader quando la cartella clonata viene aperta — niente npm install, nulla installato. Questo include chi ha clonato il repo per investigare l'incidente e gli agenti AI di coding che hanno aperto la directory — uno dei primi casi pubblici di hook di agenti AI (.claude/) usati come vettore di supply chain.

La trappola (dead-man's switch)

L'impianto installa un "watcher" (gh-token-monitor) mantenuto attivo da un LaunchAgent (macOS) o da un servizio utente systemd + loginctl enable-linger (Linux). Ogni 60 secondi valida il token GitHub rubato contro l'API. Finché il token funziona, non succede nulla. Quando la risposta diventa 4xx — cioè nel momento in cui revochi il token — esegue, via eval, il contenuto di ~/.config/gh-token-monitor/handler: un comando arbitrario definito da remoto dall'attaccante. Le analisi pubbliche non sanno cosa contenga — potrebbe essere distruzione di dati, re-impianto, ransomware o nulla. Il rischio non è valutabile; è per questo che l'ordine di risposta è assoluto.

Tre proprietà che cambiano la risposta:

  • Isolare la rete è sicuro: senza connettività non c'è risposta HTTP, quindi niente 4xx — la trappola non scatta e l'exfiltrazione si ferma. Isola prima, non spegnere (la memoria volatile è una prova).
  • È a colpo singolo e si auto-ripulisce dopo lo scatto — il comportamento diventa inspiegabile, senza alcun artefatto da investigare.
  • TTL ~24h: il watcher si autodistrugge dopo un giorno. L'assenza di artefatti non dimostra che la macchina fosse pulita — lo scanner avvisa di questo in modalità host.

Perché le difese abituali generalmente non lo individuano

  • "La firma era valida" — [email protected] è stato distribuito con un'attestazione SLSA che ha superato i controlli. La provenienza attesta l'integrità della build, non della sorgente: il workflow legittimo ha compilato codice già trojanizzato.
  • "Il diff del codice non è cambiato" — corretto: la libreria in sé non è stata modificata. La malizia sta in package.json (l'hook preinstall) e in due nuovi file aggiunti al pacchetto (setup.mjs, Math_Symbol.js).
  • "Non usiamo keyv" — in realtà sì, indirettamente: la catena più comune è eslint → file-entry-cache → flat-cache → keyv. È per questo che lo scanner mostra la catena in ogni riscontro.
  • "Nessuno ha eseguito npm install" — non basta: vedi Vettore B.

Cos'è lo script in questo repository

scan.mjs ha le seguenti proprietà — importanti per chiunque stia rispondendo a un incidente di supply chain:

  • Un singolo file, ~880 righe leggibili, zero dipendenze. Niente npm install. Fai l'audit dell'intero scan.mjs in 15 minuti prima di eseguirlo.
  • Zero egress. Nessun dato lascia la tua macchina. Nessuna telemetria, nessun "invio del risultato per l'analisi". L'unica operazione di rete è --update (scarica un manifest IOC aggiornato), esplicita e opzionale.
  • Sola lettura. Lo scanner non modifica, rimuove o esegue nulla di ciò che trova.
  • Funziona offline. docker run --network=none o una macchina isolata: basta copiare scan.mjs + iocs.json.

Come usarlo nella tua azienda

Requisito: Node.js ≥ 18 (qualsiasi macchina con npm ce l'ha già). Scarica i due file — scan.mjs + iocs.json — e basta: nessuna installazione.

Attenzione: se hai clonato l'intero repository, la cartella fixtures/ contiene IOC inerti usati nei test (nomi e versioni reali, contenuto fittizio — nessun malware). Lo scanner la salta automaticamente e lo segnala nell'output; i riscontri da essa compaiono solo se la scannerizzi apposta.

Ci sono due modalità di esecuzione che rispondono a domande diverse, ed è questo che decide dove eseguirlo:

  • La modalità repo legge i lockfile e node_modules — e i lockfile vivono in git, quindi può essere centralizzata: una persona scansiona tutti i repository dell'azienda.
  • La modalità host cerca l'impianto (watcher, LaunchAgent/systemd, hook IDE), che vive sulla macchina dove il codice è stato eseguito — non è in git e non può essere centralizzata.

Passo 1 — AppSec scansiona tutti i repository (una persona, una macchina)

root@kitploit:~
node scan.mjs repo /folder/with/all/the/repos --json=result.json --html=report.html

Risponde alla domanda "quali progetti sono esposti" in pochi minuti, senza coinvolgere nessuno. Accetta più percorsi; percorre le sottodirectory (monorepo e workspace inclusi).

Passo 2 — chi ha lavorato sui progetti colpiti scansiona la propria macchina

Per ogni progetto con un riscontro, identifica chi lo ha toccato dal 2026-08-04 09:35 UTC (git log, log CI). Queste persone eseguono, sulla propria macchina:

root@kitploit:~
node scan.mjs        # current directory + host, in ~30 seconds

Nel perimetro: chiunque abbia (a) eseguito npm install/npm ci nella finestra; oppure (b) semplicemente clonato e aperto la cartella in VS Code o in un agente AI — il Vettore B non richiede installazione.

Poiché il costo è di ~30 secondi e l'imbuto può perdere (un clone vagante, un progetto personale), il messaggio interno più sicuro è: ogni sviluppatore esegue node scan.mjs una volta e invia il --json/--html ad AppSec. L'invio è manuale per design — lo scanner non ha telemetria (zero egress).

Passo 3 — runner CI e server di build

Priorità massima: è qui che vivono le credenziali più preziose. Qui lo scanner ha due ruoli diversi — uno per il passato, uno per il futuro:

Triaging del passato — NON scansionare il runner per decidere. Alla domanda "questo runner è stato colpito?" non risponde una scansione: se un job ha installato una versione compromessa senza --ignore-scripts dal 08-04, le credenziali sono già state rubate in quel momento, e l'host del runner raramente conserva prove (i runner effimeri distruggono il container alla fine del job; il watcher si auto-ripulisce in ~24h). A rispondere sono i lockfile del Passo 1 e i log CI. Se la risposta è "sì, ha installato": ricostruisci il runner e ruota i suoi segreti — i runner sono effimeri, non c'è motivo di pulirli.

Prevenzione per il futuro — SÌ, eseguilo nella pipeline. Aggiungi lo scanner come step di build, in modalità repo, dopo il checkout e prima di npm install. Non esamina l'host del runner — esamina il codice che sta per essere installato, e il codice di uscita fa fallire la build prima che il preinstall malevolo abbia la possibilità di essere eseguito:

root@kitploit:~
# example (GitHub Actions / GitLab CI — adapt):
- run: node scan.mjs repo . --json    # exit 0 clean · 1 findings · 2 COMPROMISED
- run: npm ci --ignore-scripts         # only runs if the previous step passed

Riferimento rapido

root@kitploit:~
node scan.mjs                     # scan the current directory + the host
node scan.mjs repo /path/a /path/b
node scan.mjs host                # persistence/implants on the machine only
node scan.mjs repo . --json=result.json --html=report.html
node scan.mjs --update            # update iocs.json (the only network operation)

Triage

Report come prova

--html produce un report autonomo con timestamp, hostname, versione del manifest IOC e lo SHA-256 dello scanner stesso — utilizzabile come allegato a una notifica di incidente e come traccia di audit.

Se lo scanner ha segnalato COMPROMISED: l'ordine di risposta

Non revocare o ruotare ancora alcuna credenziale — è il grilletto della trappola. La sequenza:

1. ISOLA — stacca la macchina dalla rete. È sicuro: senza risposta HTTP non c'è 4xx, la trappola non scatta e l'exfiltrazione si ferma. Non spegnere (la memoria volatile è una prova).

2. PRESERVA — prima di eliminare qualsiasi cosa (il watcher si autodistrugge in ~24h):

root@kitploit:~
mkdir -p /tmp/evidence && cp -r ~/.config/gh-token-monitor /tmp/evidence/ 2>/dev/null
cp /tmp/gh-token-monitor.*.log /tmp/evidence/ 2>/dev/null
shasum -a 256 /tmp/evidence/* 2>/dev/null

Il file handler è il comando dell'attaccante che verrebbe eseguito — non eseguirlo, non incollarlo in una shell; trattalo come testo inerte. Il file started_at delimita la finestra di esposizione (l'auditor e il regolatore te lo chiederanno).

3. ERADICA — uccidi prima il processo del watcher, poi:

root@kitploit:~
# macOS
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
rm -f ~/Library/LaunchAgents/com.user.gh-token-monitor.plist

# Linux
systemctl --user disable --now gh-token-monitor.service
loginctl disable-linger "$USER"
rm -f ~/.config/systemd/user/gh-token-monitor.service

# both
rm -rf ~/.config/gh-token-monitor ~/.local/bin/gh-token-monitor.sh /tmp/bun-dl-*

Rimuovi anche gli hook malevoli da .claude/settings.json e .vscode/tasks.json, i file setup.mjs/Math_Symbol.js/math_init.js, e svuota le cache (~/.npm/_cacache, pnpm, yarn). Esegui di nuovo node scan.mjs host finché non torna pulito.

4. RUOTA — solo quando ogni host colpito è stato pulito e verificato (un singolo watcher attivo è sufficiente a far scattare il grilletto). Revoca prima il token npm (ferma la propagazione del worm); poi GitHub (PAT, deploy key), AWS/GCP/Azure, Vault, Kubernetes, i segreti CI — e qualsiasi segreto presente su disco, perché c'è stata una scansione con regex.

5. AUDIT — il worm agisce a tuo nome: cerca nelle tue organizzazioni repository descritti come Shai-Hulud: Here We Go Again, versioni npm pubblicate inaspettatamente dal 08-04 (deprecale e notifica i consumatori), e l'uso delle credenziali in CloudTrail/Audit Logs all'interno della finestra di started_at.

Dopodiché: elimina node_modules, reinstalla da un lockfile pulito con --ignore-scripts. Runner CI e host con esecuzione confermata: ricostruisci da zero, sempre — è stato eseguito codice arbitrario e l'elenco degli artefatti noti non è una garanzia di completezza.

Istituzioni regolamentate (BR): una compromissione confermata con accesso alle credenziali può far scattare obblighi di segnalazione (Res. CMN 4.893/2021, Res. BCB 85/2021; LGPD art. 48 se sono coinvolti dati personali). Documenta la timeline in UTC — started_at, rilevazione, contenimento, eradicazione, rotazione — e conferma le scadenze con legal/compliance.

Aggiornare gli IOC (utenti)

L'incidente è attivo e l'elenco cresce. Per scaricare il manifest più recente:

root@kitploit:~
node scan.mjs --update          # the only operation that touches the network

--update scarica iocs.json da questo repository (securest8/npm-incident-response), mai da terze parti — Securest8 è il gate di curation. Ottieni ciò che è stato pubblicato qui per ultimo.

Manutenzione degli IOC (manutentori)

L'elenco dei pacchetti proviene dal feed pubblico Wiz; gli hash, i domini C2, gli IOC di persistenza e le versioni sicure sono statici e curati in tools/gen-iocs.mjs. Uno snapshot del CSV di Wiz è conservato in tools/keyv-packages.csv per riproducibilità ed esecuzioni offline.

root@kitploit:~
node tools/gen-iocs.mjs               # fetch the latest Wiz CSV, regenerate iocs.json + refresh the snapshot
node tools/gen-iocs.mjs --offline     # regenerate from the committed snapshot, no network
node tools/gen-iocs.mjs --allow-shrink # allow a package count lower than the snapshot (guarded by default)

Il generatore è idempotente: mantiene il manifest_version esistente e non riscrive il file quando non è cambiato nulla di sostanziale, e rifiuta di scrivere un manifest vuoto o ridotto (proteggendosi da un feed a monte troncato o modificato).

Automazione: .github/workflows/update-iocs.yml esegue il generatore quotidianamente (e su richiesta) e committa su main solo quando gli IOC cambiano davvero — così --update degli utenti segue il feed Wiz entro circa un giorno, con l'intera cronologia verificabile nei commit. Trasformalo in uno step a pull request (come indicato nel workflow) quando l'incidente si raffredda e preferisci un merge manuale.

Test

root@kitploit:~
node test/run-tests.mjs         # 15 assertions against fixtures/demo-repo

fixtures/demo-repo è un repository di test con IOC inerti (nomi e versioni reali, contenuto fittizio — nessun malware). Quando si scansiona il repository dello scanner stesso, la cartella fixtures/ viene saltata automaticamente (con un avviso nell'output); i test la scansionano passando esplicitamente il percorso.

Ambito e crediti

Uno strumento per un singolo incidente, costruito per un triage rapido durante la finestra attiva dell'attacco — non un sostituto di Socket, Snyk o simili. Ricerca e IOC: Socket.dev, Wiz Research (CSV pubblico), Kodem Security.

Mantenuto da Securest8. Licenza MIT.

Scarica lo strumento
LivelloSignificatoAzione
COMPROMISEDVersione malevola installata in node_modules, payload confermato dall'hash, o trovato un impianto di persistenzaTratta l'host come compromesso; segui l'ordine di risposta — pulisci l'impianto prima di ruotare le credenziali
EXPOSEDVersione malevola fissata in un lockfile, nessuna prova di esecuzioneFissa una versione sicura, elimina node_modules, reinstalla con --ignore-scripts
AT_RISKIntervallo (^/~) in package.json che ammette una versione malevolaFissa una versione esatta o bloccala al proxy del registry
SUSPECTEuristica (nome di file del worm con hash non corrispondente, script di lifecycle sospetto)Ispeziona manualmente — potrebbe essere una nuova variante o un falso positivo
INFOVettore presente ma nessun IOC (es. un task folderOpen generico)Rivedi