Il malware npm attivato in fase di esecuzione aggira le protezioni sugli script di installazione
Scoperta una campagna npm che nasconde il malware nel runtime: il pacchetto indexed-btree elude gli script di installazione e usa payload cifrati.
Testo generato da intelligenza artificiale, pubblicato senza revisione umana. Trasparenza IA
Immagine illustrativa generata con AI
Una campagna malevola contro npm ha spostato la logica di esecuzione dagli hook di installazione al normale funzionamento della libreria, consentendo ai pacchetti di superare i controlli progettati per bloccare gli script del ciclo di vita potenzialmente pericolosi.
I ricercatori di Checkmarx hanno concentrato l’indagine su indexed-btree, un pacchetto realizzato per assomigliare alla libreria legittima sorted-btree. Secondo quanto riportato sulle scoperte dei ricercatori, indexed-btree ha raggiunto circa due milioni di download settimanali, creando un’esposizione significativa negli ambienti di sviluppo.
Il pacchetto non utilizza preinstall, install o postinstall. Il suo loader è invece nascosto all’interno di BTree.prototype.set(), una normale operazione su un B-tree, e si attiva durante l’esecuzione dell’applicazione quando riceve uno specifico valore come chiave.
Questo approccio sfrutta il divario tra la sicurezza dell’installazione e il monitoraggio in fase di esecuzione. Un pacchetto npm può installarsi senza chiedere l’autorizzazione a eseguire uno script del ciclo di vita, per poi eseguire codice malevolo quando un’applicazione richiama le funzioni che esporta.
Il percorso malevolo inizia all’interno di un normale metodo della libreria
L’installazione iniziale di indexed-btree sembra pulita perché il pacchetto non usa gli script del ciclo di vita delle dipendenze per avviare il payload. Il comportamento malevolo inizia solo quando il software che utilizza la libreria chiama BTree.prototype.set() fornendo il valore di attivazione richiesto.
La chiave esatta che attiva il comportamento non è stata divulgata. Neppure le versioni interessate del pacchetto sono state rese note, rendendo più difficile definire l’ambito dell’indagine per le organizzazioni che conservano più release nelle cache dei pacchetti o nei lockfile.
Una volta attivato, il metodo richiama sharedLoad.min.js, che contiene un payload offuscato di primo stadio. Nascondere questo loader all’interno di un’operazione su una struttura dati utilizzata di frequente aiuta a confonderlo tra codice apparentemente coerente con la funzione dichiarata del pacchetto.
Secondo la valutazione di Checkmarx, la tecnica è in grado di eludere molti scanner statici e i sistemi convenzionali di taint analysis. Questi strumenti possono esaminare gli hook di installazione, la creazione sospetta di subprocessi o flussi evidenti dagli input non attendibili alle funzioni pericolose. In questo caso, invece, il ramo malevolo è nascosto all’interno di un’API apparentemente legittima e rimane inattivo finché non vengono soddisfatte determinate condizioni di esecuzione.
Gli operatori hanno inoltre costruito attorno al pacchetto un’apparenza più ampia di legittimità. Hanno creato un repository GitHub convincente, lo hanno arricchito con una cronologia di commit progettata per sembrare autentica e hanno mantenuto un account sviluppatore curato. Questi segnali possono influenzare sia i sistemi automatizzati di reputazione sia gli sviluppatori che effettuano una rapida verifica manuale.
I controlli di npm v12 non coprono la normale esecuzione in fase di runtime
Nel giugno 2026, GitHub ha annunciato misure di sicurezza per npm pensate per contrastare gli attacchi alla supply chain che, dalla fine del 2025, avevano colpito ripetutamente gli ecosistemi open source. Tra queste misure, npm v12 blocca gli script del ciclo di vita delle dipendenze, a meno che l’utente non li autorizzi esplicitamente.
Le protezioni limitano inoltre il recupero automatico delle dipendenze da repository Git o URL remoti senza autorizzazione. Queste modifiche riducono l’efficacia dei pacchetti che eseguono codice immediatamente durante l’installazione o recuperano codice esterno tramite le dichiarazioni delle dipendenze.
indexed-btree evita del tutto questo confine di sicurezza.
Poiché il loader malevolo fa parte del normale percorso di esecuzione del pacchetto, npm non rileva uno script di installazione che richieda approvazione. L’installazione può quindi concludersi senza generare l’avviso o la richiesta di autorizzazione che i difensori potrebbero aspettarsi da un pacchetto malevolo convenzionale.
Questo non indica un bypass di npm v12 dovuto a una vulnerabilità del software. Piuttosto, mette in luce i limiti di un controllo incentrato su una sola fase di esecuzione. Le restrizioni sugli script del ciclo di vita possono bloccare comportamenti non autorizzati durante l’installazione, ma non possono stabilire se ogni funzione richiamabile di una dipendenza sia sicura.
Un’installazione completata senza avvisi non costituisce quindi una prova dell’innocuità del codice installato.
La ricognizione conduce a un payload blockchain cifrato
Dopo l’attivazione, il malware raccoglie informazioni sull’host. I dati acquisiti includono:
- Architettura del sistema
- Nome host
- Dettagli della CPU
- Informazioni sulla memoria
- Tempo di attività del sistema
Esfiltra questi dati attraverso canali Slack e Telegram hardcoded. Gli identificativi specifici dei canali, le destinazioni e gli indicatori di rete non sono stati divulgati.
Per il command and control, l’operazione interroga uno smart contract Ethereum distribuito sulla rete di test Sepolia. Questa architettura consente agli operatori di archiviare o distribuire il materiale del payload tramite un’infrastruttura blockchain, invece di dipendere esclusivamente da un server di command and control convenzionale.
Il malware utilizza lo scambio di chiavi X25519 per derivare una chiave AES. In seguito decritta un payload di secondo stadio recuperato dallo smart contract. I contenuti e le funzionalità complete del secondo stadio non sono stati divulgati; l’impatto confermato non dovrebbe quindi essere esteso oltre il meccanismo osservato di distribuzione ed esecuzione.
Gli investigatori hanno inoltre individuato un wallet Ethereum collegato all’operazione, contenente 109 ETH. Non esistono prove consolidate che quei fondi provengano da un furto di criptovalute o da sistemi compromessi tramite questi pacchetti.
Il malware include anche una funzione di pulizia controllata dall’operatore. Quando viene attivata, può eliminare i propri file e rimuovere il trigger malevolo dal codice sorgente del pacchetto. Questa capacità può far apparire pulito un ambiente precedentemente interessato durante un’ispezione successiva, soprattutto se non sono stati conservati i dati di telemetria relativi a processi, rete e file system.
Nove pacchetti correlati hanno ampliato la portata della campagna
Checkmarx ha collegato alla stessa operazione altri nove pacchetti npm. Tutti e nove sono stati rimossi da npm dopo la scoperta.
| Pacchetto | Download riportati |
|---|---|
ordered-kv-index |
448.184 |
btree-leaderboard |
493.685 |
priority-slot-queue |
402.860 |
btree-range-store |
468.092 |
btree-core |
1.951.274 |
btree-time-index |
425.312 |
btree-lru-cache |
372.185 |
neighbor-key-map |
366.019 |
sliding-score-window |
448.024 |
Lo stato della rimozione di indexed-btree non è stato specificato. Anche la cifra riportata di circa due milioni di download settimanali non dovrebbe essere confrontata direttamente con i conteggi degli altri pacchetti né sommata a essi, perché questi ultimi sono presentati come conteggi dei download riportati, senza la stessa qualificazione settimanale.
Le statistiche sui download indicano la distribuzione, non la compromissione. Non rivelano quanti download abbiano prodotto installazioni, quante applicazioni abbiano chiamato il metodo modificato o quante esecuzioni abbiano fornito la chiave di attivazione richiesta.
Tuttavia, i nomi dei pacchetti suggeriscono un targeting di casi d’uso nello sviluppo software che coinvolgono indici, code, cache, mappe e sistemi di punteggio. La potenziale esposizione comprende workstation degli sviluppatori, runner CI, server di build e altri sistemi in cui le dipendenze npm vengono eseguite con accesso al codice sorgente o alle credenziali.
Il rischio principale va oltre la semplice profilazione dell’host
Non è stato assegnato alcun punteggio CVSS né alcuna valutazione di gravità da parte di un vendor. Si tratta di una campagna basata su pacchetti malevoli, non di una vulnerabilità convenzionale con un identificativo CVE pubblicato.
Dal punto di vista operativo, il rischio è elevato perché il codice combina un’ampia distribuzione, un’attivazione ritardata in fase di runtime, la ricognizione dell’host, la distribuzione cifrata di un payload di secondo stadio e la rimozione delle tracce. Un ambiente di sviluppo compromesso può esporre più delle sole informazioni di sistema raccolte direttamente dal primo stadio.
A seconda delle autorizzazioni locali, un secondo stadio malevolo potrebbe potenzialmente raggiungere token per la pubblicazione dei pacchetti, credenziali per il controllo del codice sorgente, chiavi cloud, segreti CI, materiale per la firma o configurazioni dell’applicazione. L’accesso a queste risorse non è stato confermato, ma le organizzazioni dovrebbero includerle nella valutazione di ciò che era disponibile al processo interessato.
La funzione di autodistruzione complica inoltre la definizione dell’ambito dell’incidente. L’assenza di file malevoli durante l’esame non dimostra che l’esecuzione non sia mai avvenuta.
Le organizzazioni interessate dovrebbero preservare le prove prima di ricostruire i sistemi
Le organizzazioni dovrebbero cercare indexed-btree e tutti e nove i nomi collegati negli inventari delle dipendenze, nei lockfile, nei registry interni, nelle cache di build, nei layer dei container e nelle distinte del software (SBOM). Poiché gli intervalli di versioni interessati non sono noti, gli investigatori non dovrebbero presumere che una release specifica sia sicura senza averne verificato autonomamente i contenuti.
Prima di ricostruire i sistemi, i responsabili della risposta agli incidenti dovrebbero preservare gli artefatti dei pacchetti disponibili, la telemetria dei processi, le cronologie dei comandi, i log di rete, i record CI e le evidenze del file system. In caso contrario, il meccanismo di pulizia potrebbe cancellare le informazioni necessarie per stabilire se il trigger di runtime sia entrato in funzione.
Le misure di risposta consigliate includono:
- Isolare i sistemi di sviluppo e build potenzialmente interessati.
- Ruotare tutti i segreti accessibili da quegli ambienti, comprese le credenziali per il controllo del codice sorgente, i registry, il cloud, il deployment e la CI.
- Ripristinare da un backup noto come sicuro o da un’immagine pulita, invece di affidarsi al comportamento di rimozione del malware.
- Analizzare le connessioni in fase di runtime verso Slack, Telegram e l’infrastruttura Sepolia, tenendo presente che anche strumenti legittimi possono utilizzare questi servizi.
- Cercare attività inattese di scambio di chiavi X25519 e decrittazione AES associate a Node.js o ai processi di build interessati.
- Esaminare l’esecuzione delle applicazioni, non solo l’installazione dei pacchetti, cercando chiamate ai metodi alterati della libreria e il caricamento di
sharedLoad.min.js. - Aggiungere l’analisi del runtime in sandbox allo screening dei pacchetti, soprattutto quando le dipendenze contengono codice offuscato o modificano percorsi API comuni.
Bloccare gli script del ciclo di vita resta utile, ma interviene soltanto in un punto della catena di esecuzione di una dipendenza. Questa campagna dimostra che i maintainer malevoli possono spostare l’attivazione all’interno dell’applicazione stessa, dove il codice del pacchetto eredita la fiducia e gli accessi già concessi al normale software.
Fonti
Questo articolo è una rielaborazione originale basata sulle fonti seguenti.
