Il 27 maggio 2026, alle 18:53 UTC, nell’archivio pubblico di un progetto di LiteLLM, uno strumento molto usato da chi costruisce applicazioni per collegarle a diversi fornitori di intelligenza artificiale, finisce per errore un file di configurazione. Dentro c’è una chiave. Non una chiave qualsiasi: quella principale di un sistema interno che coordina agenti AI. L’errore viene visto in fretta. Il file viene coperto. Le chiavi finite in vista vengono segnate come da revocare, cioè da rendere inutilizzabili.
Quella principale, però, resta attiva.
Quasi cinque mesi dopo, il 21 ottobre, una versione avvelenata di LiteLLM esce dai canali ufficiali e ci resta per circa due ore, con durate diverse a seconda del canale. Due giorni fa su questo blog ho raccontato cosa faceva quel pacchetto e come, secondo l’azienda, gli intrusi erano entrati. Venerdì sera LiteLLM ha pubblicato la ricostruzione definitiva. E la porta da cui sono entrati è un’altra.
In breve
Il 23 ottobre 2026 LiteLLM ha pubblicato la ricostruzione ufficiale dell’attacco che il 21 ottobre ha portato su PyPI, l’archivio da cui si scaricano i programmi Python, e nelle immagini Docker, i pacchetti pronti per far girare il servizio, una versione infetta del programma (la 1.107.0). La prima ipotesi, credenziali GitHub rubate dai registri delle attività di un’installazione interna, è smentita dall’azienda stessa. La causa vera è una chiave API, cioè la credenziale con cui un programma si fa riconoscere da un servizio, pubblicata per errore il 27 maggio e mai revocata. Con quella, il 10 ottobre, l’attaccante ha ottenuto il token GitHub, una credenziale che permette ai programmi di agire attraverso un account, di uno dei proprietari dell’organizzazione, configurato dentro un sistema sperimentale per agenti AI; da lì, il 10 e il 12 ottobre, ha sottratto altri token e segreti, poi il 21 ha dirottato la catena di pubblicazione, approfittando anche di una regola allentata quella settimana. La lezione vale per chiunque dia una chiave a un’automazione o a un agente AI: revocare subito, dare a ogni strumento la sua chiave con i permessi minimi, mettere una scadenza alle eccezioni.
La prima spiegazione era sbagliata
Il 21 ottobre, mentre l’incidente era ancora aperto, BerriAI, l’azienda che sviluppa LiteLLM, aveva dato una spiegazione provvisoria. Riportata da Wiz, diceva così: in certe situazioni Claude Code, lo strumento di Anthropic per programmare con l’AI, inserisce il token GitHub dell’utente nel testo delle risposte; se quelle risposte finiscono nei registri di attività, i log, il token finisce lì. L’azienda pensava che l’attaccante fosse entrato in una sua installazione interna esposta su internet e avesse pescato i token proprio da quei log.
Era un’ipotesi, e l’azienda la presentava come tale. Io l’ho riportata con questa cautela nel racconto del 22 ottobre, ma il titolo la dava già per spiegazione. E una spiegazione così, con dentro un nome famoso come Claude Code, è fatta apposta per girare.
La ricostruzione del 23 ottobre, firmata dal responsabile della sicurezza di LiteLLM, Oliver Jensen, e da Mateo Wang, la corregge senza giri di parole: «Il nostro primo post sospettava che i token fossero stati presi dai log di un’installazione interna di LiteLLM. I registri delle richieste mostrano che il primo token è arrivato da un servizio diverso». E in apertura mette le mani avanti su tutto quello che era uscito prima: alcune delle convinzioni degli aggiornamenti scritti durante l’indagine si sono rivelate «inesatte o incomplete». Questo post, scrivono, è «la fonte di verità».
La prima ipotesi aveva un colpevole comodo. La verità ha un colpevole più scomodo: una cosa da fare rimasta a metà.
Maggio: l’errore visto, la revoca mancata
Il file finito in pubblico il 27 maggio si chiamava opencode.json e stava nel repository LiteLLM-Labs/lite-harness, uno spazio di codice visibile a chiunque. Conteneva la chiave principale di un’installazione della LiteLLM Agent Platform, uno strumento che l’azienda usava per coordinare agenti AI. La chiave principale, la master key, è quella con i privilegi più ampi su quel sistema.
L’azienda descrive con precisione cosa successe dopo. L’errore fu individuato in fretta. Il commit, cioè la modifica pubblicata, fu sovrascritto con un’operazione che riscrive la storia dell’archivio (in gergo, un force push). Le chiavi esposte furono individuate come da revocare. «Tuttavia», scrive LiteLLM, «la revoca non è avvenuta per la master key».
Qui sta il primo inciampo, ed è un inciampo umano prima che tecnico. Riscrivere la storia di un archivio nasconde il file a chi arriva dopo. Chi è passato prima, o un programma che sorveglia gli archivi pubblici, può averla già copiata. Una chiave che è stata in vista anche per un minuto va trattata come pubblicata. L’unica cosa che la spegne davvero è la revoca.
E la revoca era stata decisa. Semplicemente, per quella chiave, non è stata fatta. Perché sia andata così, LiteLLM non lo spiega: promette di raccontare la settimana prossima cosa ha imparato. Quello che si sa è il calendario: dal 27 maggio al primo accesso documentato con quella chiave, il 10 ottobre, passano circa quattro mesi e mezzo.
Vedere un errore e chiuderlo sono due lavori diversi. Il primo dà sollievo. Il secondo protegge.
Dalla chiave degli agenti al pass del proprietario
Il 10 ottobre, fra le 21:13 e le 21:28 UTC, l’attaccante usa quella chiave per interrogare la Agent Platform. A una domanda banale, l’elenco degli agenti configurati, il sistema risponde con la configurazione completa di ogni agente. Dentro c’è un token GitHub.
Un token è un pass già timbrato: la prova che hai fatto l’accesso, che il programma esibisce al posto tuo senza chiederti di nuovo la password. Gli agenti di quella piattaforma ne avevano bisogno per proporre modifiche al codice su GitHub. E il token che usavano non era quello di un’utenza dedicata alla macchina, con i soli permessi necessari. Era quello di uno dei due proprietari dell’organizzazione GitHub di LiteLLM. Parole dell’azienda: non associato a un account di servizio e senza permessi ristretti.
Da quel momento, scrive LiteLLM, l’attaccante aveva accesso da proprietario a tutti i repository dell’azienda. C’è un dettaglio che merita una riga in più: i token di questo tipo valgono dopo la verifica in due passaggi, e GitHub non la richiede di nuovo nemmeno per le operazioni più delicate. La verifica in due passaggi controlla chi entra dalla porta. Quello che succede dopo, con un pass già rilasciato, va sorvegliato in un altro modo.
È il nodo di cui ho scritto parlando di 1Password e degli agenti AI: una credenziale consegnata a un agente vale potenzialmente oltre il compito per cui gliel’hai data, e finisce nelle mani di chiunque arrivi a controllare l’agente o il sistema che lo ospita. Qui l’agente stava su un progetto sperimentale, in fase alfa. E portava in tasca le chiavi del padrone di casa. Anche l’attacco a Microsoft 365 che ho raccontato il 22 ottobre passava da applicazioni che avevano già il permesso di entrare: si cambia scenario, il punto debole resta lo stesso.
Agli esperimenti si danno le chiavi degli esperimenti. Quelle di casa restano in casa.
Undici giorni in casa, senza rumore
Con il pass del proprietario, l’attaccante non corre. Lavora in silenzio. La sera stessa del 10 ottobre crea rami usa e getta nei repository di LiteLLM, cioè copie temporanee del codice su cui si può lavorare senza toccare quello principale. In ognuno aggiunge un’automazione minuscola, intitolata come un ritocco di routine, che legge i segreti custoditi dal repository e li spedisce a un indirizzo esterno. Poi cancella tutto in pochi minuti. Fra quei segreti ci sono i token di altri due ingegneri con poteri da manutentore.
La società di sicurezza Socket ha ritrovato le tracce di questi passaggi e le ha consegnate a LiteLLM prima della ricostruzione ufficiale. Il suo conto: una finestra di almeno undici giorni, dal 10 al 21 ottobre, in cui automazioni costruite per rubare segreti hanno girato senza che nessuno se ne accorgesse. Socket è precisa anche sui suoi limiti: ha ritrovato due giri, il 10 e il 12 ottobre, non sa se ce ne siano stati altri in mezzo e dai soli registri non può provare che ogni dato sia arrivato a destinazione. Il furto dei token GitHub, invece, lo conferma LiteLLM. Nei due giri sono stati presi di mira venti segreti diversi. Fra questi le chiavi API di Anthropic e di OpenAI, che si pagano a consumo, le credenziali di alcuni database, una sessione salvata del browser che apre l’account di Linear, uno strumento per organizzare il lavoro, senza password e senza seconda verifica. LiteLLM descrive i segreti sottratti con il commit del 12 ottobre analizzato da Socket come poco sensibili, e le chiavi dei fornitori come chiavi per i test, con pochi fondi; e precisa che quei segreti in più non sono serviti a pubblicare la versione infetta.
E la chiave di GitGuardian, il servizio che ha il compito di accorgersi quando un segreto finisce dove non dovrebbe. Socket lo scrive così: è la credenziale del sistema che dovrebbe far scattare l’allarme, e chi la possiede può vedere, e forse controllare, proprio gli avvisi che lo farebbero scoprire.
Fra le chiavi prese di mira c’era anche quella dell’antifurto.
L’eccezione di questa settimana
Il 21 ottobre arriva il colpo vero. Alle 10:08:29 UTC l’attaccante prova a modificare il sistema che costruisce le nuove versioni, usando il token di uno dei manutentori. La protezione del ramo principale lo respinge: per cambiare quel codice servono una richiesta di modifica, due controlli superati e l’approvazione del responsabile. La regola funziona. Cinque secondi dopo, con il token del proprietario, l’attaccante spegne la protezione e passa lo stesso.
Poi punta la costruzione della nuova versione su una copia del codice tenuta in un archivio sosia, Berri-AI con il trattino invece di BerriAI. Resta un ultimo cancello: l’approvazione per la pubblicazione.
Di solito, racconta LiteLLM, per pubblicare una versione serve che la avvii un ingegnere autorizzato e che la approvi un account speciale, legato a un dispositivo fisico che sta nel loro ufficio. Quella regola era stata allentata all’inizio della stessa settimana, per sostenere una spinta temporanea verso rilasci più frequenti e correzioni da riportare sulle versioni precedenti. Bastavano due ingegneri qualsiasi: uno avvia, l’altro approva. L’attaccante ha avviato la costruzione con il token del proprietario e ha approvato la pubblicazione con quello di uno dei manutentori derubati il 10 ottobre.
L’azienda è onesta fino in fondo: con il token di un proprietario, l’attaccante avrebbe potuto allentare o togliere quella regola da solo. LiteLLM ritiene che abbia usato i due token separati per evitare altre operazioni vistose nei registri. L’eccezione, quindi, non era indispensabile per entrare. Alle 11:39 UTC su PyPI escono sette pacchetti della versione 1.107.0; alle 11:46 le immagini Docker. Fra le 11:53 e le 11:54, con il token di un terzo ingegnere, l’attaccante cancella i registri delle esecuzioni di rilascio. Fra le 12:09 e le 12:24, di nuovo con il token del proprietario e di nuovo forzando le protezioni, ripulisce la storia del ramo principale. Il registro dell’organizzazione, però, ha annotato ogni forzatura: è anche da lì che è uscita la ricostruzione.
Le regole tengono finché chi può spegnerle è al sicuro. Quanto all’eccezione, LiteLLM non dice se avesse una data di fine. Conviene dargliela sempre: un’eccezione senza scadenza tende a diventare la regola, senza che nessuno l’abbia decisa.
Chi se ne è accorto
Alle 12:06 UTC, meno di mezz’ora dopo l’uscita dei primi pacchetti, un utente, LidorMachluf, apre una segnalazione pubblica nel repository: la 1.107.0 è compromessa. L’azienda se ne accorge poco prima delle 13, quasi un’ora dopo. Alle 13:23 la versione su PyPI è congelata. Le immagini su Docker Hub spariscono alle 14:20, anche perché, scrive LiteLLM, hanno dovuto svegliare le persone che avevano accesso a quel registro: nell’ora del Pacifico che l’azienda usa nel suo racconto, era l’alba. In tutto, su PyPI la versione infetta è rimasta scaricabile per circa un’ora e tre quarti; su Docker Hub per circa due ore e mezza.
Per undici giorni nessuno ha visto niente: le automazioni ladre sono emerse dopo, anche grazie a una società esterna. Mentre i pacchetti avvelenati erano disponibili, il primo allarme è arrivato da un utente.
Le contromisure immediate dicono quanto la situazione fosse seria: registri pubblici bloccati, tutti i membri tolti dall’organizzazione GitHub tranne un account di cui erano certi, e da lì in poi un modo di lavorare che dà per scontato che ogni token, ogni chiave, ogni strumento di accesso dell’azienda sia stato rubato. Fra le frasi della ricostruzione c’è questa: l’incidente è stato una forte dimostrazione dei rischi del non sostituire una chiave potenzialmente esposta.
Una chiave esposta e lasciata attiva per mesi ha un prezzo. Si paga tutto insieme, in una mattina.
Come si racconta un incidente mentre brucia
C’è una seconda storia dentro questa, ed è una storia di comunicazione. Durante l’emergenza LiteLLM ha scelto di parlare subito, usando come bacheca proprio la segnalazione aperta da quell’utente. Ha pubblicato aggiornamenti mentre ancora non sapeva, con dentro ipotesi. Una di queste, la storia dei log e di Claude Code, è stata ripresa da chi seguiva il caso, a cominciare da Wiz. Anche da me, nel titolo.
Poi ha fatto la cosa più difficile: ha pubblicato una ricostruzione che smentisce sé stessa. Lo ha fatto con alcune scelte che vale la pena guardare da vicino, perché funzionano anche fuori dall’informatica.
Primo, dice esplicitamente che le versioni precedenti contenevano errori, e indica quale testo vale da ora in poi. Secondo, mette una cronologia al secondo, con le chiavi usate, i passaggi e gli indirizzi da cui è partito l’attacco: chi legge può controllare, e la fiducia nasce dal poter controllare. Terzo, ammette anche le cose che fanno fare brutta figura, come la regola allentata o le persone da svegliare all’alba. Quarto, dice cosa ancora non dice: le lezioni e i cambiamenti arriveranno la settimana prossima.
Il problema è che la prima versione corre e la correzione cammina. Chi ha letto «la chiave era nei log» difficilmente leggerà «la chiave era su GitHub da maggio». Per questo tocca a chi ha scritto la prima versione accompagnare la seconda: in cima al mio articolo del 22 ottobre adesso c’è un aggiornamento che rimanda qui.
Dire subito quello che sai è un dovere. Dire che cosa è ipotesi, e tornare a correggerla, è quello che ti fa credere la volta dopo.
Come portarlo nel tuo lavoro
Forse LiteLLM non lo userai mai. Ma se lavori con l’AI, di chiavi ne hai. La chiave API di ChatGPT o di Claude incollata in un’automazione. Il token che hai dato a uno strumento perché leggesse la tua posta o il tuo calendario. L’accesso al gestionale che hai passato al consulente che ti ha costruito il chatbot. Ognuna apre una porta, con i permessi che le hai dato.
La prima mossa è la più noiosa: fare l’elenco. Quali chiavi esistono, chi le usa, dove sono scritte, chi le ha create. Per cominciare basta un foglio con il servizio, chi la usa, a cosa serve e dove è custodita: le chiavi, nel foglio, non si copiano. Chi non sa quali chiavi ha, non sa nemmeno quali dovrebbe spegnere.
Poi una regola, da scrivere da qualche parte dove la vedono tutti: quando una chiave finisce in vista (in una mail, in una chat di gruppo, in uno screenshot, in un documento condiviso, in un archivio di codice) la si revoca per prima cosa, prima di sistemare qualunque altra cosa. E la voce si chiude solo quando si è provato che la vecchia chiave non funziona più. Revocare vuol dire andare nel pannello del fornitore, disattivarla e crearne una nuova; cancellare il messaggio in cui era scritta non basta.
Terza mossa: a ogni strumento la sua chiave. Un’automazione, una chiave. Un agente AI, una chiave. Mai la tua personale, mai quella dell’amministratore, e sempre con i permessi minimi per fare quel lavoro: se deve leggere, che non possa scrivere; se deve scrivere in una cartella, che non veda le altre. Dove il fornitore lo permette, aggiungi un tetto di spesa. Raccontando il caso OpenCode ho paragonato una chiave API alla tessera carburante dell’azienda: chi la usa fa il pieno, la fattura arriva a te. Lì alcuni utenti riferivano addebiti che non riconoscevano, racconti che restano da verificare, senza un legame dimostrato con la violazione. Il principio vale comunque: chiavi separate, permessi minimi e tetti di spesa, dove ci sono, restringono il raggio del danno.
Quarta: le eccezioni con la scadenza. Ogni volta che allenti una regola «solo per questa settimana» (un accesso in più a un collaboratore, un controllo saltato per fare prima) scrivi il giorno in cui torna com’era, e metti un promemoria. Ogni eccezione, un responsabile e una data di ripristino. Quella di LiteLLM durava da pochi giorni.
Quinta: la verifica in due passaggi è indispensabile, ma protegge l’ingresso. Quando sospetti un furto, cambiare la password non chiude automaticamente le sessioni già aperte né i token già rilasciati. Microsoft lo scrive chiaro nelle sue indicazioni su questo caso: bisogna revocare le sessioni, non dare per scontato che cambiare password o chiave le spenga tutte. Molti servizi hanno un’opzione per disconnettere tutti i dispositivi: cercala nelle impostazioni di sicurezza del tuo account.
Se invece qualcuno ti ha costruito un servizio con l’AI, hai tre domande da fare, senza bisogno di capire il codice. Le chiavi dei miei servizi sono intestate a me o a te? Ogni strumento ha la sua chiave, con i permessi minimi? Se una chiave finisce in vista, chi la revoca, entro quanto, e come me lo dimostra?
Ultima cosa, per chi programma: se hai installato LiteLLM 1.107.0, le indicazioni di Microsoft sono precise. Isola i sistemi coinvolti e, quando puoi farlo in sicurezza, ferma i processi Python e i riavvii automatici. Non avviare Python né pip nell’ambiente sospetto, perché il codice malevolo parte proprio all’avvio. Ricostruisci da pacchetti e immagini verificati invece di disinstallare e basta, e controlla anche le cache e le copie interne. Poi, da una macchina pulita, revoca e sostituisci tutte le credenziali accessibili dal sistema compromesso, e revoca le sessioni coinvolte.
La sicurezza, quasi sempre, è fatta di cose noiose finite fino all’ultima riga.
Domande frequenti
Allora la colpa non era di Claude Code?
Secondo la ricostruzione ufficiale di LiteLLM del 23 ottobre, il primo token rubato non viene dai log: viene da un altro servizio, la LiteLLM Agent Platform, raggiunta con una chiave pubblicata per errore a maggio e mai revocata. L’azienda scrive che alcune ipotesi degli aggiornamenti precedenti si sono rivelate inesatte o incomplete.
Cos’è una master key e perché era così pericolosa?
È la chiave principale di un sistema, quella con i privilegi più ampi. In questo caso permetteva di leggere le configurazioni degli agenti AI di una piattaforma interna, e dentro quelle configurazioni c’era il token GitHub di uno dei proprietari dell’organizzazione, con accesso da proprietario a tutti i repository dell’azienda.
Che differenza c’è fra cancellare una chiave da un file e revocarla?
Cancellarla dal file la toglie dalla vista di chi arriva dopo. Revocarla la rende inutilizzabile per chiunque, anche per chi l’ha già copiata. Una chiave rimasta in vista anche per poco va sempre revocata dal pannello del servizio che l’ha emessa, e sostituita con una nuova.
La verifica in due passaggi non doveva bastare?
Protegge il momento dell’accesso. Nel caso di LiteLLM, il token rubato permetteva di agire senza ripetere la verifica in due passaggi, anche per le operazioni più delicate. Per questo, dopo un sospetto furto, oltre a cambiare la password si revocano esplicitamente sessioni e token: cambiare la password non li spegne necessariamente.
Io uso ChatGPT o Claude per lavoro: devo preoccuparmi?
Se hai creato chiavi API per collegarli ad altri strumenti, quelle chiavi sono soldi e dati: fai l’elenco, dai a ogni strumento la sua chiave con i permessi minimi e, dove il fornitore lo permette, un tetto di spesa; revoca subito quelle finite in vista. Se usi solo l’app con il tuo account, attiva la verifica in due passaggi e controlla ogni tanto i dispositivi collegati.
Fonti
- LiteLLM, «The attack chain behind the v1.107.0 LiteLLM release», Oliver Jensen e Mateo Wang, 23 ottobre 2026
- Socket, «New Evidence Shows LiteLLM Secret-Stealing Workflows Ran 11 Days Before Supply Chain Attack», 23 ottobre 2026
- Microsoft Security Blog, «Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks», 23 ottobre 2026
- The Hacker News, «Leaked LiteLLM Master Key Let Attackers Steal GitHub Tokens and Hijack Release Pipeline», 24 ottobre 2026
- Wiz Research, «LiteLLM Compromised, Steals Credentials», 21 ottobre 2026 (con la prima ipotesi di BerriAI)