Risky Business: la spiegazione dei pacchetti npm autoeliminanti.

Risky Business: i pacchetti anti-proctoring che si autoeliminano

TL; DR

I pacchetti si eliminano da soli. Nell'arco di quindici giorni ad agosto, un operatore npm ha pubblicato nove pacchetti con nove nomi diversi da sette account e ne ha ritirati personalmente otto. Il tempo in cui ciascun pacchetto è rimasto attivo si è ridotto da tredici ore a diciassette minuti. La tecnica non è esclusiva di questo operatore: altri sette pacchetti, provenienti da operatori non correlati e con contenuti completamente diversi, sono stati ritirati dai rispettivi publisher in un tempo medio di 37.8 minuti. L'artefatto scompare prima che la maggior parte dei processi di difesa venga eseguita e l'installazione è già avvenuta.

Tutto ciò che il registro espone ruota; il payload no. Tutti e nove hanno spedito un byte identico bin/ directory, lo stesso digest SHA-256 su tre nomi di pacchetto e due account, a distanza di quindici giorni. L'identità del contenuto è l'unico segnale di tracciamento che questo operatore non ha violato, e l'unico pacchetto che non ha mai ritirato è il motivo per cui è stato possibile esaminarlo.

Le persone che lo installano non sono vittime e sono comunque molto esposte. Questo strumento non è destinato agli sviluppatori: neutralizza la sorveglianza remota degli esami tramite acquisizione dello schermo nascosta, estrazione del testo sullo schermo e risposte restituite a una sovrapposizione, quindi chiunque corra npm install è il beneficiario designato, non il bersaglio. Inoltre, eseguono un file binario non firmato che decifra i cookie del browser, da un account che si autoelimina entro un'ora. Non possono ricevere una soluzione, non possono verificare in seguito cosa hanno eseguito e non possono segnalare i danni senza rivelare il motivo per cui lo hanno installato.

Ecosistema: npm, stesso schema osservato su PyPI. Periodo: Giugno-agosto 2026.

La misurazione

Il tempo di permanenza è l'intervallo tra la comparsa e la scomparsa di un pacchetto, calcolato a partire dai metadati del registro stesso. Si tratta di misurazioni, non di stime.

CONFEZIONEPubblicato (UTC)Rimasto in piedi
moidev2026-08-16 16:315h 58m
moidevx2026-08-17 03:2413h 23m
moidevz2026-08-26 03:3812h 56m
moideva2026-08-26 18:581h 33m
amicat2026-08-28 20:4817m
bmcat2026-08-28 21:1747m
eyevox2026-08-28 21:4421m
moidevh2026-08-31 03:2247m

Se letti nell'ordine di pubblicazione, i tempi si riducono di oltre quaranta volte, passando da 13 ore e 23 minuti nel caso più ampio a 17 minuti nel caso più ristretto. I primi quattro pacchetti hanno una durata media di otto ore e mezza; gli ultimi quattro di trentatré minuti. Il 28 agosto, tre pacchetti sono stati pubblicati e ritirati nell'arco di soli 77 minuti.

La contrazione non è graduale. Si concentra tra il 26 e il 28 agosto, e ciò che è cambiato è stata la stima dell'operatore sulla durata di conservazione sicura di un pacco.

Ogni ritiro qui è avviato dall'editore. Il documento di registro per ciascuno mostra un elenco di manutentori vuoto accanto a tempo.non pubblicato record — la firma di un non pubblicato piuttosto che di una rimozione. Un nono pacchetto, eyiouss, non è mai stato ritirato del tutto; è il motivo per cui tutto ciò ha potuto essere esaminato.

Esiste un secondo regime di recesso che non deve essere confuso con questo. Dove solo il versione del carico utile viene estratto e il pacchetto sopravvive, la mediana è di circa 73 ore su 31 pacchetti. Queste sostituzioni arrivano in lotti programmati e lasciano un guscio vuoto — un pacchetto.json dichiarando un principale che non invia alcun file — la cui unica funzione è quella di mantenere il nome riservato. Quel regime è una gestione ordinaria programmata. Questo è una finestra di esposizione ottimizzata.

Cosa sopravvive alla cancellazione?

Nove di questi pacchetti appartengono a un unico operatore: moidev, moidevx, moidevz, moideva, moidevh, amico, bmcat, eyevox and eyiouss. I nomi non condividono alcuna convenzione: chiunque tenga traccia del moidev Stem avrebbe perso più della metà di questi messaggi, pubblicati da sette account diversi, quasi tutti registrati su domini di posta elettronica temporanea.

Ciò che hanno in comune è una voce manifesta che non ha ragione di esistere:

"bin" { "": "bin/kalamasha-tool.js" } }

Abbiamo conservato copie di cinque prima della rimozione. In tutti e cinque, l'intero bidone / La directory è identica byte per byte:

Compila il SHA-256
bin/kalamasha-tool.js0c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd
bin/uia_extract.exee2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865
bin/chrome_cookies.ps121b61ec810331850d72423c40c5448e6cd310c4cfad6aed54f92cd7e7cac5f3a
bin/stealth_capture.ps1c9baf5897c03b941c54f736df5af9243ad28794a9e69746d41d4f4a34065589c
bin/uia_extract.pyc20b38c63efd9221930095c54b42cdd5adffa1972c44c4578226cbe1e4dbac3e
bin/uia_get_text.ps14a3f3ada0bdf13aa8e89edb8af817c7816296147dae5be25f169ff960d28a87c

Altri due segnali confermano questa ipotesi. Tre dei pacchetti sono stati pubblicati alle 03:24, 03:38 e 03:22 UTC del 17 agosto, 26 agosto e 31 agosto, in un intervallo di sedici minuti distribuito su quindici giorni e su tre account distinti. Inoltre, due di questi account erano registrati sullo stesso dominio di posta elettronica temporanea, il che li collega indipendentemente dal codice.

I conti

Questi sono gli account degli editori npm che hanno distribuito il payload, con il pacchetto caricato da ciascuno e la durata della sua permanenza:

Account dell'editoreCONFEZIONEDominio emailRimasto in piedi
letol39119moidev:1.0.0hutdot.com (usa e getta)5h 58m
so1d1a7i27moidevx:1.0.0ogzmail.com (usa e getta)13h 23m
lololololol435678eyiouss:3.0.21, 3.0.22, 4.0.1ogzmail.com (usa e getta)ancora pubblicato
tagadob568moidevz:1.0.0ebflyai.com (usa e getta)12h 56m
tayihim489moideva:1.0.0prodbits.com (usa e getta)1h 33m
sahihai123amicat:1.0.0, bmcat:2.0.9, eyevox:1.0.0posta elettronica dei consumatori17m / 47m / 21m
heytoshanmoidevh:1.0.0posta elettronica dei consumatori47m

so1d1a7i27 and lololololol435678 parti del ogzmail.com dominio di registrazione: il collegamento che lega l'account che ospita ancora una copia live all'account che ha pubblicato sotto il dominio moidev stelo due settimane prima. sahihai123 Il 28 agosto, nell'arco di soli 77 minuti, sono stati pubblicati e ritirati tre nomi di pacchetti software distinti. heytoshan registrato, pubblicato moidevhe lo ritirò 47 minuti dopo; rimane l'unica pubblicazione di quell'account.

Ciascuno di questi account non ha un indirizzo email verificato, non contiene alcun link verificato a fonti di controllo versione e non ha pubblicato alcun progetto non correlato. Sei dei sette non ospitano più alcun contenuto.

Un pacco non è mai stato ritirato. eyiouss:4.0.1 È stato pubblicato dopo il 16 agosto ed era ancora risolvibile al momento della stesura di questo testo. Otto artefatti erano irrecuperabili; la campagna è stata ricostruita interamente a partire da quella rimasta. Un operatore che cancella in modo automatico, prima o poi, lascerà comunque qualcosa in piedi.

Cosa fa lo strumento

eyiouss:4.0.1 Su npm si descrive come "un'utilità DOM ad alte prestazioni e un ponte diagnostico per le moderne applicazioni web". Si tratta di uno strumento per l'acquisizione di schermate e il recupero delle risposte, progettato per funzionare in background durante gli esami con sorveglianza remota, come afferma esplicitamente il codice sorgente.

Il programma di avvio copia il runtime di Electron con un nome file falso prima di eseguirlo e specifica cosa sta evitando:

// 🛡️ NOME BINARIO NASCOSTO: NON deve entrare in conflitto con il vero Testpad! const STEALTH_NAME = 'SearchApp.exe';

L'intestazione dello stesso file lo chiama un Anti-Proctor Ghost Watchdog e implementa un ciclo di respawn che si allontana ulteriormente quanto più velocemente viene ucciso. Altrove il processo aumenta la propria priorità per contrastare la limitazione della CPU dovuta al monitoraggio, spinge l'applicazione dell'esame fuori dal primo piano quando prende il focus e termina un processo figlio di Safe Exam Browser con taskkill /F /T.

L'acquisizione avviene tramite uno script PowerShell integrato, richiamato con i criteri di esecuzione disabilitati e la finestra soppressa, con il testo visualizzato sullo schermo raccolto in parallelo tramite l'automazione dell'interfaccia utente di Windows. Le immagini e il testo in coda vengono inviati a una sessione del modello linguistico in un browser incorporato e la risposta viene visualizzata in una sovrapposizione sempre in primo piano. Tale connessione viene volutamente posticipata e il codice ne spiega il motivo: per evitare un'esposizione permanente a NETSTAT.

Il pacco viene spedito anche chrome_cookies.ps1, diretto ESTRATTORE DI BISCOTTI CROMATO, che decifra i cookie di Chrome e Edge tramite DPAPI e legge il database dei cookie da un massimo di quattro profili browser. Dichiarato in precedenzacisely: non abbiamo trovato quello script richiamato per nome da alcun file JavaScript distribuito. Ciò che è presente e raggiungibile è la parte che lo consuma, che inietta i cookie di sessione memorizzati nel browser incorporato.

La posizione delle persone che lo installano

Nessuno installa questo programma per sbaglio. Non ha alcuna funzione al di fuori di un esame monitorato e il suo output è una sovrapposizione di risposte sullo schermo dell'utente. La descrizione ingannevole del pacchetto non è affatto rivolta all'installatore, ma è indirizzata al registro e a chiunque analizzi la macchina in seguito. L'installatore sa cosa sta ottenendo; la descrizione esiste affinché record dell'installazione non lo riflette.

Le parti danneggiate sono terze parti che non hanno mai avuto a che fare con npm: l'istituzione che gestisce l'esame, gli altri candidati e chiunque a valle faccia affidamento sul valore di tale certificazione.

Ma l'installatore non è quindi al sicuro, ed è proprio questo il punto che vale la pena sottolineare, perché è il modello del pacchetto che scompare a creare il rischio.

Stanno eseguendo un file binario non firmato proveniente da nessuno. uia_extract.exe navi compilate, senza sorgente e senza provenienza di build, da un account che non esiste più. Lo stesso file, tramite hash, è stato ripubblicato da letol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123 and heytoshan nell'arco di quindici giorni. Non c'è un manutentore a cui chiedere, nessun repository da consultare e nessuna cronologia da controllare: ogni identità che lo ha distribuito si è cancellata da sola.

Gli hanno conferito esattamente le capacità di cui ha bisogno un malware. Un processo nascosto, in esecuzione con un nome falso, decifra i cookie del browser, legge continuamente lo schermo, termina i software di sicurezza e si riavvia quando viene interrotto. Attualmente la decrittazione dei cookie è limitata ai domini di un singolo fornitore e serve la sessione dell'utente. Questa limitazione si risolve con una sola riga di codice e nessun elemento del modello di distribuzione la renderebbe evidente se cambiasse: un nuovo nome, un nuovo account, un nuovo caricamento.

Non riescono a ricevere una soluzione. Il pacchetto viene rimosso dalla pubblicazione entro un'ora. Non esiste un percorso di aggiornamento, nessun avviso e nessun modo per scoprire in seguito che la versione installata era diversa da quella installata dall'amico. Qualunque cosa sia presente sul computer, lì rimane.

Non possono verificare ciò che hanno eseguito. Il loro file di blocco ora fa riferimento a un pacchetto che non è più risolvibile. Se in seguito volessero stabilire cosa fosse presente sul loro computer, ad esempio dopo un incidente o una controversia, il registro non conterrà alcuna informazione utile.

E non possono denunciare i danni subiti. Un utente compromesso da questo strumento non può presentare una segnalazione di abuso senza rivelare il motivo per cui lo ha installato. Questo non è un dettaglio trascurabile. Le segnalazioni di abuso del registro di sistema sono uno dei principali canali attraverso cui vengono individuati i pacchetti di breve durata, e la base di utenti di questo operatore è strutturalmente incapace di utilizzarle. L'unico avversario rimasto è la scansione automatizzata, per la quale è calibrata una finestra temporale di diciassette minuti.

La struttura delle vittime e il tempo di permanenza rappresentano lo stesso fatto osservato due volte. Ciò spiega anche l'anomalia nella cronologia: se il ritiro fosse stato motivato dalla paura delle lamentele, il pacchetto popolare e di lunga durata sarebbe stato il primo a essere ritirato. Non è successo, perché le lamentele non sono mai arrivate.

Lo stesso schema, un operatore diverso

L'operatore addetto alla sorveglianza non è il solo a trovarsi in questa situazione, e il parallelismo più evidente si basa su un carico utile non correlato.

Tra il 24 e il 27 agosto, sono apparsi quattro pacchetti npm con nomi presi in prestito da strumenti di autenticazione a due fattori. auth-otp, chiave segreta-autenticazione a due fattori, secretkey2fa and Chiave segreta 2FA — che ne trasportavano sedici versioni in totale. Ciascuna veniva pubblicata dal proprio account appena registrato (beayilol, jeanpaul686g, zzzalipay, dluuuuu), tutti senza verifica dell'indirizzo email, nessuno con un link verificato al sistema di controllo della fonte, nessuno con pubblicazioni di altro genere. Ognuno è stato ritirato dal proprio editore.

Il payload non ha nulla a che fare con il software di esame. Legge gli archivi delle credenziali del browser e i token di Discord, e percorre una scala di autenticazione Xbox Live contro il launcher di Minecraft per catturare un token di aggiornamento. Ecco il programma di installazione is la vittima nel senso comune del termine, ed è proprio questo che rende utile il paragone, perché il comportamento di consegna è identico in entrambi i casi.

I quattro cicli si sono svolti nell'ordine di pubblicazione a 274.9, 37.8, 37.6 e 35.7 minuti: un primo tentativo lungo, poi la convergenza su una cifra valida. Altri tre pacchetti appartengono ad altri operatori e mostrano lo stesso comportamento di ritiro.

CONFEZIONEOperatoreRimasto in piedi
octopus-actionfaro di ricognizione2.5 min
mt-ts-serverless-starterfaro di ricognizione9.6 min
2fa-secretkeyNomi di copertura dell'autenticazione a due fattori35.7 min
secretkey2faNomi di copertura dell'autenticazione a due fattori37.6 min
secretkey-2faNomi di copertura dell'autenticazione a due fattori37.8 min
auth-otpNomi di copertura dell'autenticazione a due fattori274.9 min
hex-encode-utilsAltri724.2 min

Sette pacchetti, con una durata media di 37.8 minuti, nessuno dei quali relativo a software per esami.

Tre carichi utili non correlati, tre serie di account non correlate, una tecnica condivisa.

Perché la finestra si sta chiudendo

Qualcosa è cambiato nell'ambiente del registro nel corso del 2026, e il candidato più probabile è che la scansione sia diventata più veloce.

Fino a poco tempo fa, i pacchetti dannosi venivano scoperti principalmente a posteriori: da un utente che notava qualcosa, da una segnalazione successiva o da una scansione periodica. La latenza di rilevamento si misurava in giorni. Questo non è più l'unico regime. Analisi quasi in tempo reale dei pacchetti appena pubblicati — Il sistema di allerta precoce antimalware di Xygeni. Tra i numerosi sistemi di questo tipo presenti nel settore, questo sistema riduce notevolmente il divario tra pubblicazione e ispezione.

Un operatore che si trova di fronte a questa situazione ha due opzioni. Rendere il payload più difficile da riconoscere o ridurre il tempo in cui è disponibile per essere esaminato. La seconda è più economica, non richiede competenze ingegneristiche e il registro fornisce il meccanismo gratuitamente: entro la finestra di 72 ore di annullamento della pubblicazione di npm, un editore può rimuovere unilateralmente un pacchetto e il nome può essere riutilizzato in seguito. Il ritiro non costa nulla all'operatore.

La tempistica è corretta. Entrambi gli operatori di cui sopra convergono su una cifra e la mantengono invece di variare, che è ciò che un parametro calibrato si presenta piuttosto che una questione di convenienza. E il parametro su cui sono convergiti — decine di minuti — si trova primacisely dove dovrebbe posizionarsi per superare un controllo automatizzato, pur mantenendo il pacchetto installabile abbastanza a lungo da raggiungere il suo pubblico.

Questa rimane un'ipotesi. I dati temporali non possono distinguere una risposta alla scansione da una risposta all'applicazione del registro, o dalla normale maturazione operativa man mano che questi operatori imparano gli uni dagli altri. Ciò che si può affermare senza inferenze è più circoscritto e comunque utile: La finestra di esposizione è ora talmente breve che qualsiasi controllo che dipenda dall'ispezione di un imballaggio dopo la pubblicazione si trova a dover fare i conti con un tempo limitato impostato dall'operatore. I controlli che non dipendono dall'ispezione, come la quarantena in base all'età o la disabilitazione degli script di installazione, non sono influenzati da tale dinamica, ed è proprio questo il motivo pratico per preferirli.

Cosa fare al riguardo

Quarantena in base all'età. Nessun elemento nella tabella dei tempi di permanenza è sopravvissuto per tredici ore. Una politica che impedisse l'installazione di qualsiasi versione di dipendenza prima che fosse esistita per 72 ore avrebbe escluso ognuno di essi senza rilevare nulla.

Disabilita gli script di installazione per impostazione predefinita. –Ignore-scripts rimuove il meccanismo di consegna da cui dipendono i pacchetti di furto di credenziali in questo corpus. Non è utile contro uno strumento che l'utente esegue deliberatamente, che è precisely la distinzione che vale la pena comprendere.

Trattare la scomparsa come un evento di sicurezza. Ricevi un avviso quando una dipendenza installata smette di essere risolta. Le prove sono conservate nel file di blocco, non nel registro di sistema.

Monitora i contenuti, non i nomi. I sei digest sopra riportati corrispondono indipendentemente dal nome del pacchetto, dall'account dell'editore o dalla stringa di versione: ogni campo che questo operatore ha dimostrato di modificare. Una regola lato registro che stabilisse che un account appena registrato che ritira il suo unico pacchetto entro un'ora costituisce un modello da segnalare si sarebbe attivata per ogni pacchetto qui, basandosi solo sui metadati.

E se stai pensando di installare qualcosa in questa categoria: Le caratteristiche che rendono difficile l'individuazione da parte di un registro sono le stesse che ti lasciano senza possibilità di ricorso. Non c'è un editore da ritenere responsabile, non c'è un percorso di aggiornamento e non c'è traccia di ciò che hai eseguito.

TipoValore
Compila il bin/kalamasha-tool.js — non-standard punto di ingresso del bidone
SHA-2560c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd
SHA-256e2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865
ProcessoSearchApp.exe scritto accanto a un runtime Electron legittimo
Comportamentopowershell -ExecutionPolicy Bypass -File con windowsHide: true
Comportamentotaskkill /F /T mirare a un processo Safe Exam Browser
MetadatiElenco di manutentori vuoto accanto a un time.unpublished record
contiletol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123, heytoshan
Registrazioneogzmail.com, hutdot.com, ebflyai.com, prodbits.com — domini di posta elettronica usa e getta

Referenze

  • npm unpublish policy — il periodo di 72 ore entro il quale un editore può rimuovere un pacchetto senza intervento.
sca-tools-software-strumenti-di-analisi-della-composizione
Dai priorità, risolvi e proteggi i rischi del tuo software
Crea il tuo account gratuito.
Nessuna carta di credito richiesta.

Proteggi lo sviluppo e la distribuzione del tuo software

con la suite di prodotti Xygeni