Note operative Osservatorio

ChainDrop: il worm npm che sopravvive alla rimozione riscrivendo la configurazione di VS Code e Claude Code

7 min di lettura

Fotografia in bianco e nero di file di catene metalliche affiancate, con gli anelli agganciati uno all’altro
Ogni pacchetto compromesso ne aggancia un altro: è la stessa logica con cui ChainDrop si propaga.

Il 5 agosto 2026 il CSIRT Italia (ACN) pubblica il bollettino BL01/260805/CSIRT-ITA su «ChainDrop: campagna worm auto-propagante nell’ecosistema npm», criticità dichiarata «Medio (64.97)». La sintesi: oltre 400 pacchetti npm compromessi, di maintainer e organizzazioni diverse. Fra i nomi coinvolti: keyv 6.0.0, flat-cache 6.1.24, file-entry-cache 11.1.6, cache-manager 7.2.10, cacheable 2.5.1, cacheable-request 13.0.20, @cacheable/memory 2.2.1, @cacheable/node-cache 3.1.2, @cacheable/utils 2.5.1, @cacheable/net 2.1.1, ecto 5.0.1. Il bollettino è in fonti, in fondo: qui non lo traduciamo, lo leggiamo per chi deve decidere che fare.

Il confine di fiducia non è il modello: è il pacchetto

Chi si preoccupa di quale intelligenza artificiale adottare, e non di che cosa esegue un npm install, sta sorvegliando la porta sbagliata. Le release compromesse introducono uno script preinstall che avvia setup.mjs, il quale carica il payload Math_Symbol.js (o varianti equivalenti). Il bollettino è netto sul momento in cui questo accade: «L’esecuzione del contenuto malevolo avviene durante la fase di installazione del pacchetto, prima del completamento della procedura npm.» Non c’è un istante in cui qualcuno decide se fidarsi: l’esecuzione precede la decisione.

Il payload, poi, non si comporta allo stesso modo ovunque: distingue una workstation di sviluppo da un runner di integrazione continua, e sui secondi «può mantenersi agganciato al processo di build per accedere ai secret, ai token temporanei e alle credenziali disponibili nel contesto della pipeline stessa». L’attacco non punta al singolo laptop: punta dove le credenziali sono più concentrate e meno sorvegliate, la pipeline che gira senza che nessuno la guardi. Un ciclo che precede la sorveglianza umana lo avevamo già documentato, lì con un agente offensivo senza operatore passo dopo passo; qui l’operatore non ha nemmeno la possibilità di intervenire, perché il pacchetto non ha ancora finito di installarsi.

La persistenza colpisce anche la configurazione dell’agente

Il punto più utile del bollettino, per chi fa girare strumenti di sviluppo assistiti da AI, è nella sezione dedicata a persistenza ed evasione: il malware modifica «file di configurazione associati ad ambienti di sviluppo e repository GitHub, inclusi componenti collegati a Visual Studio Code e Claude Code, al fine di mantenere la persistenza sui sistemi e favorire ulteriori esecuzioni anche successivamente alla rimozione della dipendenza originaria». A questo si aggiungono offuscamento avanzato ed esfiltrazione cifrata delle informazioni raccolte.

Va letto con freddezza tecnica, senza allarmismo e senza attribuire colpe a Microsoft o ad Anthropic: il difetto non è nei loro prodotti. È che un processo non fidato — lo script preinstall di un pacchetto compromesso — ha potuto scrivere la configurazione di uno strumento fidato. La configurazione di un editor o di un agente è un file come gli altri: chi la controlla decide che cosa lo strumento esegue al riavvio, anche dopo che la dipendenza è stata rimossa dal progetto — disinstallare il pacchetto non tocca ciò che quel pacchetto ha già scritto altrove sul disco. È esattamente la superficie in più di chi fa girare agenti di sviluppo sui propri sistemi: non perché l’agente sia vulnerabile in sé, ma perché la sua configurazione è raggiungibile da qualunque processo con permessi sufficienti sulla stessa macchina.

Le credenziali rubate pubblicano altri pacchetti

Quello che il malware raccoglie non è generico: «variabili d’ambiente, token npm, token GitHub, chiavi SSH, credenziali cloud e segreti utilizzati nelle pipeline di automazione». Ed è l’uso che ne fa a rendere ChainDrop un worm, non un semplice furto: le credenziali ottenute servono «per accedere a repository, servizi cloud e account npm, consentendo la pubblicazione automatizzata di ulteriori pacchetti compromessi». È una catena di fornitura che si mangia da sola — ogni maintainer compromesso diventa il vettore verso il maintainer successivo.

Per questo l’elenco di undici pacchetti riportato sopra è un’istantanea, non un perimetro, ed è l’ACN stessa ad avvertirlo: «a causa del meccanismo auto-propagante, il perimetro delle versioni impattate risulta estremamente dinamico. Si raccomanda di non limitare la verifica ai soli numeri di versione sopra indicati, ma di estendere il controllo a qualsiasi release pubblicata nella finestra temporale della campagna.» Un controllo fatto oggi contro undici nomi precisi rassicura e basta: la domanda che tiene, fra tre settimane, è un’altra.

La domanda giusta non è «quali pacchetti», è «quale token»

Chiedersi «siamo esposti a questi undici pacchetti?» è la domanda sbagliata, perché la risposta scade nel momento stesso in cui la si ottiene. Quella che tiene è: quale token, presente su quale macchina, potrebbe pubblicare a nome della nostra organizzazione? E se lo revocassimo oggi, sappiamo dire con certezza che cosa smette di funzionare? Se la seconda risposta non c’è — se nessuno in azienda sa quali build, quali deploy, quali automazioni dipendono da quel token — il problema non è ChainDrop: è che l’inventario delle credenziali non esiste, e ChainDrop lo ha solo reso visibile.

Le mitigazioni del bollettino vanno lette in quest’ottica, non come una casella da spuntare una volta. Il primo passo è bloccare l’esecuzione automatica: --ignore-scripts in fase di analisi o bonifica impedisce agli hook preinstall e postinstall di partire da soli; aggiornare npm — valutando min-release-age — riduce il rischio di scaricare in automatico una release appena pubblicata, ancora nella finestra in cui nessuno l’ha segnalata. Il secondo è cercare: dentro package-lock.json, yarn.lock e pnpm-lock.yaml, per verificare se nomi e versioni compromesse sono già nella base di codice, e sul filesystem, per file come setup.mjs, Math_Symbol.js o math_init.js. Il terzo è bloccare le versioni buone note con overrides o resolutions, così un aggiornamento automatico non reintroduce ciò che si è appena escluso.

Poi viene la parte che costa di più, e che per questo si rimanda più spesso: revocare e rigenerare token npm, credenziali GitHub, chiavi cloud e segreti CI/CD accessibili dall’host coinvolto; svuotare le cache; verificare gli artefatti prodotti nella finestra di esposizione; ricostruire immagini e runner CI/CD da sorgenti affidabili, non da un backup che potrebbe già contenere il payload. E infine controllare, non presumere, che le modifiche a repository, workflow automatizzati e file di configurazione degli strumenti di sviluppo — «es. estensioni e impostazioni di VS Code e Claude Code» — siano quelle che avete autorizzato voi.

Come lo risolviamo noi

Un inventario aggiornato delle dipendenze, con gli hash dei lockfile, è esattamente il tipo di controllo di cui scrivevamo a proposito del Cyber Resilience Act e dell’obbligo di SBOM: applicato a ChainDrop, diventa il modo per rispondere in ore, non in settimane, a «questa versione ci ha toccato?». L’adempimento prende una forma precisa: un registro di quale credenziale ha accesso a che cosa e su quale macchina vive, la prova documentata — con data ed esito — di ogni rotazione di token, e la rilevazione delle modifiche non autorizzate ai file di configurazione degli strumenti di sviluppo. Non un audit fatto una volta e archiviato: la traccia da esibire a un’ispezione, aggiornata perché il controllo gira sul serio.

Lo stesso impianto che tiene quel registro è quello che, un livello più su, tiene insieme i dati sparsi dell’organizzazione — repository, pipeline, inventario, log, documenti, gestionali — in un modello operativo unico, su cui agenti AI eseguono decisioni con un operatore al comando: per grandi imprese, difesa, pubblica amministrazione e sanità, dove una valutazione documentata dei fornitori ICT non è un esercizio burocratico ma la base su cui si autorizza un acquisto.

Va detta per intero, ed è una precisazione che rafforza la nostra credibilità invece di indebolirla: avere il modello nel proprio perimetro, con pesi propri, non mette al riparo da questo. Possedere il modello non significa possedere i pacchetti che lo fanno girare: la catena di fornitura del software — npm, PyPI, i registri di ogni linguaggio — va governata comunque, a prescindere da dove gira il modello. Lo facciamo in entrambe le modalità: on-premise, su macchine autonome che non richiedono un’integrazione profonda nella rete del cliente, oppure su cloud dedicato con data center in Italia — sempre con la gestione tenuta insieme a voi.

Sapete quale token, su quale macchina, potrebbe pubblicare a nome della vostra organizzazione — e che cosa smette di funzionare se lo revocate? Parliamone in una sessione senza costi: verifichiamo insieme l’inventario delle credenziali e delle dipendenze che avete oggi in esercizio.

Fonti