Illustrazione tecnica astratta su un campo blu navy scuro: un piccolo cubo di pacchetto in vettoriale piatto al centro-sinistra, con una sottile linea ambra che scende ad angolo verso una rappresentazione compatta di una workstation per sviluppatori; un ventaglio di sottili filamenti ciano e blu acciaio si dirama verso destra dalla workstation in direzione di molti piccoli nodi circolari su una griglia rada, due dei quali si curvano di nuovo verso l'alto fino al cubo del pacchetto, e un nodo all'estrema destra resta isolato e scollegato. Non compaiono persone, loghi o testo. Il logo OrcaRouter è sovrapposto nell'angolo in basso a destra.
AI Safety Incidents

L'SDK npm di Tensorlake è stato avvelenato per rubare le credenziali degli AI agent — e per cancellare la tua directory home se revocavi il token

Autore

Alistair Wren

Data di pubblicazione

Ultimi modelli · 20Vedi tutti i modelli →
Benchmark: Artificial Analysis · aggiornato ogni giorno
Torna a tutti gli articoli

L'8 ottobre 2026, una release compromessa di tensorlake — l'SDK npm per la piattaforma di Tensorlake, che esegue codice non attendibile generato da LLM all'interno di sandbox isolate — ha raggiunto il registro npm. La versione 0.5.144 è stata pubblicata alle 01:12:07 UTC; i ricercatori di Socket affermano di averla segnalata circa undici minuti dopo. Non era una release autorizzata. Tensorlake dichiara che l'attaccante ha inserito il codice direttamente nel repository GitHub dell'azienda e l'ha pubblicato tramite il flusso di rilascio del progetto stesso, quindi il pacchetto portava provenienza npm valida — un'attestazione firmata che mostra dove è stato creato, per un codice sorgente che era già stato compromesso. L'azienda afferma che la versione è rimasta attiva per circa 1 ora e 40 minuti, dalle 01:12 alle 02:54 UTC, prima che npm la rimuovesse.

Il payload non richiedeva alcun import né alcun agente in esecuzione. Un preinstall hook nel manifest del pacchetto eseguiva node lib/setup.mjs, un loader offuscato che depositava il runtime Bun sulla macchina e lo usava per eseguire lib/Math_Symbol.js, un ladro di credenziali e worm auto-propagante da 856.501 byte. Chiunque abbia eseguito una semplice installazione di quella versione lo ha eseguito. Poiché era il tag latest del pacchetto, quella versione era quella a cui puntava un'installazione predefinita mentre era attiva.

Ciò che rende questo record degno di essere conservato non è la dimensione del payload — la famiglia Shai-Hulud è già stata documentata. È la lista degli obiettivi. Accanto ai token npm e GitHub, alle credenziali AWS, ai segreti Kubernetes e Vault, alle chiavi SSH, .env file, password del browser e portafogli di criptovalute, questa build ha raccolto specificamente configurazione degli strumenti di sviluppo AI e file MCP — quelli associati a Claude Code, Cursor, Kiro, Windsurf e Zed, secondo Socket. Ha anche scritto i propri .claude/settings.json e .vscode/tasks.json nei repository che riusciva a raggiungere, così che il codice sarebbe stato eseguito di nuovo la volta successiva che uno sviluppatore avesse aperto quel progetto in Claude Code o VS Code. È un attacco alla supply chain mirato direttamente alle macchine su cui le persone costruiscono agenti.

Come la release è uscita dall'account di un maintainer

Socket, SafeDep e Aikido hanno pubblicato ciascuno la propria analisi l'8 ottobre, e le loro descrizioni del meccanismo concordano. Il grado di attendibilità dell'archivio per questo record è A, non è contrassegnato come contestato, e nulla di quanto trovato nelle fonti contraddice alcuna di esse.

L'articolo di SafeDep traccia otto commit al main branch tra le 01:20 e le 03:57 UTC del 7 ottobre, attribuiti a un account amministratore del repository e realizzati tramite l'interfaccia web di GitHub. Il commit che l'archivio cita come il primo non autorizzato è 41b38f0, una revisione di quattro file del 7 ottobre alle 03:44:48 UTC il cui messaggio è "Add files via upload" e che porta la firma di GitHub verified — GitHub firma i commit creati nel proprio editor web, quindi "verified" indica la superficie di modifica, non la persona. Quel commit non ha toccato file oltre a typescript/lib/Math_Symbol.js e typescript/lib/setup.mjs, secondo l'API di GitHub: il payload, e nient'altro.

SafeDep offre una lettura del comportamento dell'operatore, etichettata come propria inferenza: la prima modifica dell'hook di preinstall ha rotto la sintassi JSON del file e un commit di riparazione è seguito diciannove minuti dopo, che descrive come coerente con una persona che modifica file in un browser anziché con una pipeline automatizzata. Nulla di quanto pubblicato da Socket, SafeDep, Aikido, StepSecurity o Tensorlake indica il metodo con cui è stato preso il controllo dell'account del manutentore.

L'attaccante non aveva bisogno di un token npm. SafeDep riferisce che l'account ha avviato il workflow publish_npm.yaml del progetto manualmente l'8 ottobre alle 00:08 UTC; il log di build mostra i file del payload all'interno del tarball pubblicato. La release utilizzava npm trusted publishing, e i pacchetti sibling tensorlake-native-* pubblicati dalla stessa esecuzione riportano una provenienza SLSA valida — una provenienza autenticamente valida per una build di codice sorgente avvelenato. La release è stata pubblicata dodici minuti dopo l'avvio del workflow.

L'archivio registra che il repository è stato compromesso per circa 20 ore prima che scattasse la pubblicazione — l'intervallo che la cronologia di seguito illustra commit per commit — il che è coerente con la dichiarazione di Tensorlake stessa secondo cui l'attaccante ha pubblicato "attraverso il nostro stesso flusso di rilascio".

Cosa ha fatto il payload una volta eseguito

A screenshot of a card titled 'A credential stealer with an AI-tooling list', kicked 'tensorlake@0.5.144 · what the payload collected', subtitled 'Per Socket, SafeDep and Tensorlake's advisory — grouped by what each collector reached for'. Three columns of paired labels sit side by side. 'Publishing and source control' lists npm tokens from .npmrc, the token API and the OIDC exchange; GitHub tokens with a repository and workflow permission check; GitHub Actions secrets read from Runner.Worker memory; and cryptocurrency browser wallets across 14 extensions. 'AI agent tooling' lists ~/.claude.json for Claude Code settings; ~/.kiro/settings/mcp.json for Kiro MCP config; .cursor, Windsurf and Zed config and MCP files; and .claude/settings.json and .vscode/tasks.json written back into reachable repositories. 'Cloud, cluster and endpoint' lists AWS via STS, SSM Parameter Store and Secrets Manager; Kubernetes service-account tokens and kubeconfigs; HashiCorp Vault at 127.0.0.1:8200; SSH and GPG keys, .env files and Docker and CLI files; the Wallets row, wallet.dat, Exodus, Electrum and MetaMask; and saved passwords via a downloaded HackBrowserData binary. A footer reads 'Collector list per Socket's initial assessment, SafeDep's decoded payload analysis and the Tensorlake advisory (GHSA-8g63-53c9-65j2). Socket flags AI development tooling for Claude Code, Cursor, Kiro, Windsurf and Zed by name.'

La valutazione di Socket identifica l'harvesting attraverso file locali, ambienti CI, Kubernetes e fonti Vault, oltre a esfiltrazione, persistenza ed esecuzione di codice fornito da remoto. SafeDep ha riprodotto il payload decodificato: lib/setup.mjs scarica Bun 1.3.13 dalla release ufficiale su GitHub e lo usa per eseguire il worm, e esce sui runner CI — l'obiettivo è una macchina di sviluppatore, non un build agent. SafeDep ha anche scoperto che il payload contiene una copia in chiaro di quello stesso loader, che inserisce in altri pacchetti e repository.

Il payload applica tre livelli di offuscamento, che SafeDep ha decodificato senza eseguire il campione: un array di stringhe dell'offuscatore, un cifrario personalizzato che usa il salt svksjrhjkcejg — identico a quello segnalato nella precedente compromissione di keyv — e AES-256-GCM su undici file incorporati, inclusi script, hook e due chiavi pubbliche RSA. La sua prima riga contiene il tag di build WORMTAG='tensrlake', scritto in modo errato, ed è così che SafeDep distingue questa build da una reinfezione in corso.

Oltre alla configurazione degli strumenti AI, l'elenco delle raccolte è ampio e specifico: ~/.claude.json e ~/.kiro/settings/mcp.json per le impostazioni dell'agente; chiavi SSH, file delle CLI cloud, .npmrc, .env, file Docker e Kubernetes e cronologia della shell; wallet.dat più i dati di Exodus, Electrum e Ledger Live e le estensioni wallet del browser come MetaMask e Phantom; AWS STS, SSM Parameter Store e Secrets Manager; segreti di GitHub Actions letti da Runner.Worker nella memoria del processo; e token degli account di servizio Kubernetes e token Vault. Ha scaricato un binario specifico per piattaforma da iseekaigogo[.]com/hbd/<platform> e lo ha eseguito con gli argomenti "dump -b all -c password -f json" — argomenti che corrispondono allo strumento HackBrowserData, sebbene SafeDep osservi che il binario stesso non è stato recuperato e definisca l'identificazione come un'inferenza. Il worm, aggiunge SafeDep, termina sui locale russi.

A screenshot of a card titled 'Persistence, resolution, and the wipe trigger', kicked 'tensorlake@0.5.144 · staying power', subtitled 'The release was removed in under two hours; the implant it installed was built to outlive that.' Three columns sit side by side. 'Persistence: gh-token-monitor' lists a systemd user service on Linux, a LaunchAgent com.user.gh-token-monitor on macOS, a scheduled task with a PowerShell monitor on Windows, and files left behind in ~/.local/bin, ~/.config and %LOCALAPPDATA%. 'Endpoint resolution order' lists, in numbered order, the primary endpoint iseekaigogo[.]com:443/router; an Ethereum contract 0xb614155Fd88...1Df091B9; the public RPC endpoints that contract is read through, given as ~30 by Socket and 35 by SafeDep; signed GitHub commits found by the string thebeautifulmarchoftime; and public dead-drop repositories described as 'Shai-Hulud: Here We Go Again'. 'The dead-man switch' lists a poll of api.github.com/user every 60s, for 24 hours, firing on a 40x response to that token, with the effect rm -rf ~/ (advisory: home dir), armed only if the account has no orgs, and the order that matters: remove monitor, then revoke. A footer reads 'Per Socket's blog and SafeDep's analysis, with the C2 endpoint, the contract and the gh-token-monitor service confirmed in Tensorlake's advisory. Socket and SafeDep give different counts of the public RPC endpoints the contract is read through.'

La persistenza è deliberata. Socket ha scritto a proposito del payload: "Tale combinazione estende il rischio oltre una singola chiave API rubata", aggiungendo che "la persistenza può mantenere l'accesso dell'attaccante dopo la rimozione della dipendenza interessata". SafeDep riferisce che il worm esegue il commit dei file hook di Claude Code e VS Code con l'autore git claude, e inserisce un workflow "Run Copilot" che estrae tutti i segreti del repository e poi elimina l'esecuzione e il branch. L'avviso di Tensorlake invita gli sviluppatori che controllano i propri log a cercare un branch denominato dependabot/github_actions/format/setup-formatter e i commit attribuiti a quella stessa identità.

Spread si basa su token rubati anziché su una seconda vulnerabilità. Socket afferma che il worm enumera i pacchetti associati all'identità di pubblicazione di una vittima, costruisce la provenienza Sigstore e ripubblica versioni avvelenate. SafeDep aggiunge il dettaglio che all'interno della CI aggiunge una dipendenza git e firma il proprio output con Fulcio e Rekor — così la provenienza del pacchetto che pubblica successivamente è valida quanto lo era quella su 0.5.144.

Le venti ore prima della pubblicazione

L'intervallo tra il primo commit malevolo e la release è la parte della cronologia che spiega come un pacchetto avvelenato sia arrivato a portare una provenienza valida. Tutti gli orari sono in UTC; gli orari dei commit sono di SafeDep e dell'API di GitHub, mentre gli orari di pubblicazione, rimozione e dell'advisory sono di Tensorlake.

A screenshot of a card titled 'Compromised source in the repo, then one manual publish', kicked 'tensorlake@0.5.144 · the ~20-hour window', subtitled 'All times UTC. Commit times per SafeDep's timeline and the GitHub API; publish and removal times per the Tensorlake advisory.' Three columns sit side by side. '7 October 2026 — source, main branch' lists 01:20 setup.mjs and Math_Symbol.js added; 01:24 the preinstall script added; 01:43 package.json JSON repaired; 02:13 to 03:44 four loader and payload revisions; 03:44 commit 41b38f0, the payload commit; 03:57 the version set to 0.5.144. '8 October 2026 — release and removal' lists 00:08 publish_npm.yaml started by hand; 01:12:07 version 0.5.144 published to npm; 01:22:02 issue #1014 opened by StepSecurity; 01:23:10 flagged by Socket, about eleven minutes in; 02:54 the version removed, after roughly 1h 40m live; 20:24 version 0.5.145 published next. '9 October 2026 — disclosure closed' lists advisory GHSA-8g63-53c9-65j2; pull request #1016, source reverted and 0.5.145 cut; issue #1014 closed as completed; 0.5.143 as the last version stated unaffected; and no usage seen, per Tensorlake's user-agent telemetry. A footer reads 'The ~20-hour gap between the first rogue commit and the publish is SafeDep's commit timeline, and matches the archive's own upstream record.'

Leggi di seguito: i file payload sono arrivati nel branch principale del repository il 7 ottobre, la versione è stata impostata su 0.5.144 alle 03:57 di quella mattina, e nulla è stato pubblicato fino a quando un account ha avviato manualmente il flusso di rilascio alle 00:08 del giorno successivo. Il codice sorgente compromesso è rimasto nel branch per circa venti ore prima che la pipeline del progetto stesso lo compilasse. Questo è tutto l'attacco al percorso di rilascio — nessuna attestazione falsificata, nessun tarball ripubblicato. La provenienza era accurata riguardo a una build di codice che non sarebbe mai dovuto essere nel branch.

L'interruttore dell'uomo morto

La parte di questo incidente che non ha precedenti nelle precedenti compromissioni di npm è ciò che accade dopo che una vittima reagisce correttamente. Se il token GitHub rubato appartiene a un account senza organizzazioni, riferisce SafeDep, il worm installa gh-token-monitor: un servizio che esegue il polling di api.github.com/user con quel token rubato ogni 60 secondi, per 24 ore. Quando GitHub restituisce un 40x — come fa nel momento in cui il token viene revocato — il monitor esegue un handler fornito dall'attaccante ed elimina la directory home dell'utente.

Socket descrive la stessa componente come l'impiego di un monitor PowerShell che persiste tramite un'attività pianificata ONLOGON, eseguendo un handler fornito dall'attaccante tramite Invoke-Expression, e osserva che il codice contiene la stringa letterale "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner", vista nelle precedenti ondate di Shai-Hulud. SafeDep identifica l'handler come rm -rf ~/. Le parole di Socket sono esplicite sul fatto che questo si attiva indipendentemente da dove avvenga la revoca; il monitor è locale, mentre la revoca non lo è. Tutte e quattro le fonti — Socket, SafeDep, StepSecurity e l'avviso di sicurezza della stessa Tensorlake — indicano lo stesso ordine di operazioni: rimuovere prima il monitor, poi revocare.

Che cosa è stabilito e che cosa è soltanto dedotto

L'archivio registra che non vi è alcun danno confermato per questa voce, e le fonti lo sostengono anziché limitarsi a non contraddirlo.

• Tensorlake dichiara che non viene fatto alcun utilizzo della versione. Il suo avviso afferma che la società monitora l'utilizzo dell'SDK tramite gli header user-agent e "non ha visto alcun utilizzo di questa versione da quando è stata rilasciata". Si tratta di una dichiarazione del fornitore sulla propria telemetria, non di un conteggio verificato.

• Il numero di download non è un conteggio delle infezioni. Socket riporta il pacchetto a circa 12.000 download settimanali e osserva che questo descrive l'utilizzo complessivo del pacchetto, non i download della versione dannosa; SafeDep cita circa 106.000 download mensili dello stesso pacchetto. Nessuno dei due è prova che la 0.5.144 sia stata eseguita da qualche parte. La finestra di rilascio segnalata da Socket e la finestra di due ore di Tensorlake sono coerenti con una versione rimossa prima che si diffondesse.

• I bug del payload stesso potrebbero averlo limitato. SafeDep ne ha trovati due: il percorso di propagazione npm richiede ./dist/Math_Symbol.js su disco e si arresta senza di esso, e il loader impiantato cerca ai_init.js mentre il worm scrive math_init.js. SafeDep etichetta questi risultati come limitazioni alla diffusione, e l'articolo li considera come l'interpretazione del codice da parte di una singola analisi, non come una garanzia che nulla si sia propagato.

• L'attestazione di provenienza è autentica. Non è un'affermazione contestata: la provenienza npm registra dove è stato compilato un pacchetto e da quale workflow, e in questo caso ha registrato la verità — il workflow di rilascio del progetto stesso, che compilava codice sorgente avvelenato. L'avviso di Tensorlake lo afferma senza mezzi termini: "il pacchetto reca una provenienza npm valida". Socket esprime lo stesso concetto con chiarezza quando osserva che la provenienza "dice dove è stato compilato un pacchetto. Non dice che il codice è sicuro".

Diversi dettagli in circolazione sono affermazioni basate su una singola analisi e vanno letti come tali. Il meccanismo specifico con cui l'attaccante ha ottenuto l'account del maintainer non è stato pubblicato da nessuna delle società che hanno svolto le indagini né da Tensorlake. L'indirizzo del contratto Ethereum e il suo ruolo nella risoluzione dell'endpoint compaiono nei resoconti di SafeDep e Socket — Socket afferma che il payload risolve il proprio endpoint tramite un contratto Ethereum utilizzando circa 30 endpoint RPC pubblici con un fallback su GitHub, mentre SafeDep indica il numero di RPC in 35 e riporta che l'8 ottobre il contratto restituiva iseekaigogo.com — e Tensorlake conferma l'endpoint e il contratto nel suo avviso. Il numero esatto di RPC differisce tra i due resoconti; il design no.

Una lacuna nella documentazione pubblica merita di essere dichiarata chiaramente. Nessuna delle fonti esaminate per questo articolo riporta un'infezione a valle confermata — un altro pacchetto o repository contaminato dal worm usando credenziali rubate a questo. Il codice di propagazione esiste e SafeDep lo ha letto; non è noto se abbia prodotto una seconda vittima.

Cosa è cambiato in seguito

La risposta è stata più rapida e più coordinata dell'incidente.

• La versione non c'è più. È stata attiva dalle 01:12 alle 02:54 UTC dell'8 ottobre, secondo Tensorlake; SafeDep riferisce che npm l'ha rimossa. Interrogando direttamente il registro npm il 10 ottobre per questo articolo, 0.5.144 non compare più tra le versioni pubblicate del pacchetto, e il tag latest del pacchetto è 0.5.148. L'avviso di Tensorlake indirizza gli sviluppatori a 0.5.143 come ultima versione non interessata.

• L'avviso è pubblicato con una correzione.L'avviso GHSA-8g63-53c9-65j2 di Tensorlake afferma che i pacchetti PyPI e crates.io tensorlake e la CLI tensorlake non sono stati interessati — solo il pacchetto npm lo è stato — e che le versioni 0.5.143 e precedenti non sono interessate. SafeDep riporta che i manutentori hanno ripristinato il codice sorgente nella pull request #1016 e rilasciato 0.5.145.

• Il thread di divulgazione è insolitamente completo.Il ricercatore di StepSecurity Ashish Kurmi ha aperto la issue GitHub #1014 alle 01:22:02 UTC dell'8 ottobre — circa dieci minuti dopo la pubblicazione — facendo riferimento alla descrizione fatta da StepSecurity stessa di quello che definisce il worm del "token ostaggio". Oliver Smith di Aikido ha commentato che il payload è stato introdotto nel commit 41b38f0 e lo ha identificato come un nuovo infostealer Shai-Hulud. Il maintainer David Lorenzo — l'identità del maintainer indicata sul pacchetto npm come calavera — ha risposto il 9 ottobre confermando l'avviso di sicurezza e chiudendo la issue come completata lo stesso giorno. Il titolo stesso della issue segue le prove: è iniziato come una segnalazione di "possibilmente malevolo" ed è stato rinominato, nel momento in cui è stata chiusa, per descrivere il payload come malevolo senza riserve.

• La campagna a cui appartiene è più ampia di questo pacchetto. Socket, SafeDep e Aikido collocano tutti la release di Tensorlake nell'ondata ChainDrop / Mini Shai-Hulud documentata per la prima volta all'inizio di agosto 2026, le cui vittime npm includevano keyv, cacheable e pacchetti correlati. L'advisory di Tensorlake afferma lo stesso, citando Socket, SafeDep e Aikido.

Le indicazioni di Socket per chiunque abbia installato la versione sono che l'host va considerato compromesso: controllare lockfile, manifest e log di build relativi alla versione; rimuovere il gh-token-monitorservizio prima di revocare qualsiasi token; poi ruotare le credenziali da una macchina pulita. L'avviso di Tensorlake aggiunge la stessa sequenza di operazioni e suggerisce di controllare i registri dei pacchetti e i repository in cui i token esposti avrebbero potuto scrivere, alla ricerca di release inattese. L'analisi di Aikido consiglia di impostare ignore-scripts=true in .npmrc per bloccare gli hook di installazione e di trattare qualsiasi macchina su cui l'hook è stato eseguito come completamente compromessa.

Questo è un record, riportato da altri e qui citato con riferimento a loro. Gli altri incidenti documentati che coinvolgono agenti, ciascuno con le proprie fonti, gravità, grado di confidenza e flag di contestazione, si trovano in l'archivio degli incidenti di IA — così una compromissione della catena di fornitura mirata agli strumenti per agenti può essere letta accanto al resto di ciò che è effettivamente accaduto.