🛡️ Executive Summary
- Due versioni beta dei pacchetti @joyfill/layouts e @joyfill/components contengono codice JavaScript malevolo inserito prima della pubblicazione su npm.
- Il payload di @joyfill/layouts si attiva quando Node.js importa il modulo, aggirando la protezione npm install –ignore-scripts.
- La catena usa Tron, Aptos e BNB Smart Chain per recuperare codice modificabile a distanza e installare un RAT collegato a DEV#POPPER.
Due release beta appartenenti al namespace npm di Joyfill sono state compromesse con un impianto JavaScript capace di eseguire codice quando il pacchetto viene importato da Node.js. La versione malevola di @joyfill/layouts avvia una catena ridondante che recupera istruzioni attraverso transazioni su Tron, Aptos e BNB Smart Chain, quindi installa un remote access trojan collegato alla famiglia DEV#POPPER. La seconda release, @joyfill/components, contiene la stessa iniezione nel bundle, ma un problema nel caricamento dinamico limita l’esecuzione nel percorso analizzato. Il vettore iniziale che ha permesso di alterare i pacchetti non è ancora stato identificato.
Cosa leggere
Due release beta Joyfill contengono l’impianto malevolo
Le versioni coinvolte sono @joyfill/[email protected] e @joyfill/[email protected], pubblicate su npm il 28 luglio 2026 a circa nove minuti di distanza. Joyfill sviluppa SDK utilizzati per integrare moduli, documenti e PDF nelle applicazioni web e mobili: @joyfill/components fornisce i componenti React, mentre @joyfill/layouts gestisce pagine, campi e disposizione degli elementi. I due pacchetti registrano approssimativamente 16.000 download settimanali ciascuno, ma il dato non permette di stimare il numero delle infezioni perché le statistiche si sovrappongono e riguardano tutte le versioni, non soltanto le due beta compromesse. Socket ha verificato che le release precedenti @joyfill/[email protected] e @joyfill/[email protected] non contenevano l’impianto e non ha trovato la stessa firma negli altri pacchetti pubblici del namespace esaminati.
Il malware parte quando l’applicazione importa il modulo
La catena non utilizza i tradizionali script npm preinstall, install o postinstall. Il codice malevolo è stato aggiunto all’entry point CommonJS di @joyfill/layouts e viene eseguito nel momento in cui Node.js carica il modulo attraverso require(). La misura npm install --ignore-scripts, spesso applicata per impedire l’esecuzione automatica dei lifecycle hook, non blocca quindi l’attacco quando un’applicazione, una build o un test importa effettivamente la dipendenza. L’impianto può attivarsi all’interno di workstation di sviluppo, runner CI, processi di server-side rendering, strumenti di test e pipeline di compilazione. Il bootstrap espone internamente le primitive require e module, deoffusca un resolver JavaScript e avvia due rami indipendenti: uno rimane nel processo che ha importato la libreria, mentre il secondo crea un processo Node.js separato e scollegato. Quest’ultimo può sopravvivere alla conclusione della build o del comando che ha inizialmente caricato il pacchetto. La tecnica conferma il rischio descritto con AsyncAPI compromessa su npm e la distribuzione di Miasma attraverso pacchetti affidabili, dove la fiducia assegnata alla dipendenza trasferisce l’esecuzione al codice inserito dall’aggressore.
Tre blockchain rendono modificabile il payload
Il primo ramo interroga l’ultima transazione in uscita associata a un indirizzo Tron incorporato nel codice. Il dato recuperato indica l’hash di una transazione su BNB Smart Chain; se la richiesta Tron fallisce, il loader consulta un account Aptos come percorso alternativo. L’input della transazione BSC viene quindi invertito, decodificato e decifrato tramite XOR per ottenere JavaScript eseguibile. Il meccanismo viene ripetuto in un secondo livello prima del recupero del payload finale da circa 77 KB. La blockchain non ospita necessariamente l’intero malware, ma funziona come registro pubblico dal quale l’operatore può pubblicare nuovi puntatori e cambiare codice o server senza distribuire un’altra versione npm. Bloccare un singolo dominio C2 non impedisce quindi la risoluzione iniziale, perché il loader può ricostruire la destinazione partendo da dati permanenti e accessibili attraverso più reti. La stessa architettura era stata osservata in ViteVenom, campagna npm contro l’ecosistema Vite basata su un C2 blockchain, alla quale Socket collega direttamente gli indicatori PolinRider presenti nei pacchetti Joyfill.
Un secondo ramo scarica codice da un server diretto
Parallelamente alla risoluzione blockchain, l’impianto avvia un processo Node.js detached che contatta 23.27.13[.]43/$/boot, invia l’header personalizzato Sec-V: A9-0135-3, decifra la risposta e la passa a eval(). Il ramo dispone anche di profili alternativi verso altri indirizzi e non rappresenta un semplice fallback: può continuare a funzionare indipendentemente dal processo principale e consegnare un payload diverso da quello ottenuto attraverso la blockchain. Socket ha recuperato risposte compatibili con questa infrastruttura contenenti sia il RAT JavaScript sia un infostealer Python, ma precisa di non poter dimostrare che ogni esecuzione Joyfill abbia ricevuto esattamente gli stessi file. La distinzione evita di attribuire automaticamente tutte le capacità osservate a ogni installazione compromessa. La presenza di due canali separati offre comunque resilienza: gli aggressori possono mantenere attivo il ramo blockchain, quello HTTP oppure entrambi, scegliendo payload differenti in base al sistema raggiunto.
DEV#POPPER controlla il computer dello sviluppatore
Il payload principale recuperato è un RAT multipiattaforma scritto per Node.js e collegato alla famiglia DEV#POPPER attraverso sovrapposizioni di codice, comandi Socket.IO, marcatori e tecniche di persistenza. Il malware raccoglie hostname, sistema operativo, processo e indirizzo IP pubblico, quindi apre un canale di controllo remoto. Può eseguire JavaScript o comandi di shell, gestire directory, caricare ed esfiltrare file, scaricare ulteriori script e leggere gli appunti mediante PowerShell su Windows, pbpaste su macOS e xclip o xsel su Linux. Il codice evita alcuni ambienti di analisi e CI riconoscendo nomi come github-runner, buildbot, buildkitsandbox e microsoft-standard-WSL2. Può inoltre inserire blocchi auto-ripristinanti nei file utilizzati da Visual Studio Code, Cursor, GitHub Desktop, Discord Desktop e npm CLI, ottenendo persistenza anche dopo la rimozione della dipendenza iniziale. La relazione tecnica con DEV#POPPER inserisce il caso nell’ecosistema già osservato con Contagious Interview e i falsi colloqui usati per consegnare malware agli sviluppatori, pur senza dimostrare da sola chi abbia compromesso Joyfill.
L’infostealer cerca credenziali, wallet e strumenti Git
Uno dei payload Python recuperati dall’infrastruttura viene valutato da Socket come una possibile variante di OmniStealer. Il codice può raccogliere dati dal Windows Credential Manager e dai secret service Linux, estrarre informazioni dai browser Chromium e Firefox e leggere lo storage delle estensioni dedicate a wallet e password manager. Tra gli obiettivi compaiono anche credenziali Git, configurazioni della GitHub CLI, log di GitHub Desktop e dati conservati da Visual Studio Code. Su macOS il malware gestisce il Keychain, mentre su Linux interagisce con Secret Service o KWallet. Le informazioni vengono raccolte in una directory nascosta, compresse in un archivio ZIP cifrato con AES e caricate sul server dell’attaccante; il codice prevede anche l’invio di documenti tramite Telegram quando il C2 fornisce bot token e chat ID. La selezione degli obiettivi mostra perché gli sviluppatori rappresentino bersagli strategici: un singolo computer può contenere accessi a repository privati, registry, ambienti cloud, pipeline di rilascio e wallet, permettendo di trasformare l’infezione iniziale in una nuova compromissione della supply chain.
La seconda libreria contiene il codice ma incontra un errore
@joyfill/[email protected] contiene la stessa iniezione in dist/index.js, dist/index.esm.js e dist/joyfill.min.js. Nel bundle analizzato, tuttavia, Rollup inserisce uno shim per il require() dinamico che genera un’eccezione e impedisce al loader di risolvere normalmente le dipendenze di rete. La release rimane compromessa e deve essere rimossa, ma non può essere descritta con la stessa certezza come capace di completare la catena osservata in @joyfill/layouts. La presenza del codice in entrambi i pacchetti dimostra però che l’iniezione era già inclusa durante la generazione dei bundle. Le source map attribuiscono infatti il frammento malevolo a un file sorgente e conservano gli identificatori dell’impianto. Non si tratta quindi di una modifica applicata soltanto al tarball dopo la compilazione. Resta aperta la domanda sull’accesso iniziale: workstation di uno sviluppatore, repository, pipeline CI o credenziali npm potrebbero aver permesso la pubblicazione, ma nessuna delle ipotesi è stata confermata.
Socket collega l’operazione al cluster nordcoreano
Socket ritiene che gli indicatori PolinRider, la struttura multi-blockchain e il codice DEV#POPPER colleghino Joyfill e ViteVenom alla stessa operazione continuativa associata ad attori nordcoreani. La valutazione si basa su sovrapposizioni tecniche concrete, ma deve essere formulata con cautela. La stessa società precisa che il riconoscimento delle famiglie malware non equivale, da solo, all’attribuzione della compromissione Joyfill a un gruppo specifico. Non è ancora noto chi abbia ottenuto accesso al processo di pubblicazione, né se l’identità npm sia stata sottratta, utilizzata da una macchina infetta o abusata attraverso la pipeline. L’ipotesi nordcoreana è coerente con le campagne Contagious Interview contro gli sviluppatori, ma rimane una valutazione investigativa e non una prova pubblica definitiva dell’autore dell’incidente.
Rimuovere il pacchetto non elimina la compromissione
Gli sviluppatori devono individuare le due versioni nei file package-lock.json, yarn.lock, pnpm-lock.yaml, nelle cache locali, nei mirror interni, nelle immagini di build e negli artefatti già distribuiti. Occorre sostituuirle con versioni verificate e controllare ogni macchina o runner che abbia importato @joyfill/[email protected]. La sola disinstallazione non è sufficiente, perché il ramo detached può essere rimasto attivo e il RAT può avere modificato file appartenenti agli strumenti di sviluppo. Devono essere ricercati i marcatori di iniezione pubblicati da Socket, processi Node.js anomali, connessioni verso gli IP indicati, modifiche nei moduli di VS Code, GitHub Desktop, Discord e npm, oltre a directory .npm sospette nelle cartelle utente o temporanee. Token npm, credenziali Git e GitHub, chiavi cloud, password manager e wallet accessibili dal processo devono essere ruotati da un sistema pulito. La ricerca tecnica di Socket sulla compromissione Joyfill documenta i due rami, gli indicatori e le differenze operative tra i pacchetti e collega l’incidente alla più ampia attività contro l’ecosistema degli sviluppatori. Il punto critico non è il momento dell’installazione: basta importare la libreria compromessa perché il processo Node.js diventi il primo anello di una catena capace di rubare credenziali e aprire l’accesso remoto.
Iscriviti alla Newsletter
Non perdere le analisi settimanali: Entra nella Matrice Digitale.
Matrice Digitale partecipa al Programma Affiliazione Amazon EU. In qualità di Affiliato Amazon, ricevo un guadagno dagli acquisti idonei. Questo non influenza i prezzi per te.









