Mercoledì 21 ottobre, dalle 11:39 alle 13:20 UTC, su PyPI, l’archivio da cui si installano i programmi Python, c’erano i pacchetti infetti di LiteLLM 1.107.0, una libreria con cui chi costruisce applicazioni le collega a più di cento fornitori di intelligenza artificiale. Chi ne installava uno si portava in casa un ladro, pronto a partire a ogni avvio di Python in quell’ambiente, e a riprovarci finché la spedizione del bottino non andava a buon fine. Password del browser, chiavi dei server, chiavi del cloud, le chiavi di ChatGPT, di Claude e di tutti gli altri modelli configurati. Le impacchettava, le cifrava e le spediva a un indirizzo che sembrava quello del produttore. Poi si metteva in attesa di ordini.
Se il nome non ti dice niente, potresti usarlo lo stesso senza saperlo, dentro qualcosa che ti ha costruito qualcun altro. E la parte più interessante della storia non è il furto. È come ci sono entrati.
In breve
Il 21 ottobre 2026 la versione 1.107.0 di LiteLLM, la libreria che collega più di cento fornitori di AI a un’unica porta, è stata pubblicata su PyPI e nelle immagini Docker ufficiali, i pacchetti pronti per far girare il servizio, con dentro un ladro di credenziali e una porta sul retro. Su PyPI è rimasta un’ora e quarantuno minuti; le immagini Docker un po’ di più, fino alle 13:53 UTC circa secondo Wiz. Secondo BerriAI, l’azienda che la sviluppa, l’attacco è passato dagli account GitHub di tre ingegneri, a quanto pare con token rubati, cioè le credenziali che permettono di agire attraverso quegli account; l’azienda ritiene che siano stati presi dai log, i registri di attività, della propria installazione interna, e come gli intrusi ci siano entrati resta da confermare. È la seconda volta in sette mesi. Chi ha installato quella versione deve cambiare tutte le chiavi.
Il rubinetto da cui esce l’acqua di cento acquedotti
LiteLLM fa una cosa semplice, e per questo gira in tanti posti. Ogni fornitore di intelligenza artificiale ha il suo modo di farsi chiamare: OpenAI in un modo, Anthropic in un altro, Google in un altro ancora. LiteLLM mette tutti dietro una porta sola, scritta come quella di OpenAI, così chi costruisce un’applicazione scrive il codice una volta e cambia modello quando vuole. Gira sui computer degli sviluppatori, nelle catene di montaggio del software e, soprattutto, nei «proxy» di produzione: la macchina in mezzo che tiene in cassaforte le chiavi di tutti i fornitori e le usa per conto di tutti gli altri.
Chi tiene le chiavi di tutti è il bersaglio migliore che esista. Rubi il mazzo, e hai le cento chiavi in una volta sola.
Cosa faceva la versione avvelenata
Le ricostruzioni di Wiz, StepSecurity e degli altri che hanno smontato il pacchetto raccontano la stessa cosa. Dentro ognuno dei sette pacchetti compilati della versione 1.107.0, e nelle immagini Docker ufficiali, c’erano tre file in più. Il primo è lungo dodici byte e contiene un’istruzione sola, che Python esegue da solo ogni volta che parte nell’ambiente in cui quei file sono stati installati. Nessuno deve usare LiteLLM, nessuno deve nemmeno aprirlo: basta avviare Python lì dentro e il ladro si sveglia.
Il ladro si chiama, con una certa modestia, privcollect. Lavora in sedici reparti. Prende le password salvate in Chrome, Edge, Brave e Opera, decifrandole al volo su Linux e Windows, fino a tremila per volta; di Firefox si porta via i file, per decifrarle con calma. Prende le chiavi SSH, quelle con cui si entra nei server, e le chiavi private GPG, quelle con cui si cifra e si firma. Prende le credenziali di Amazon, Google e Microsoft Cloud, comprese quelle che le macchine in cloud si passano fra loro. Su Linux legge le variabili d’ambiente, cioè i valori di configurazione che spesso contengono credenziali, di tutti i processi a cui riesce ad arrivare; cerca i file .env fino a due livelli sotto la cartella personale e quella di lavoro; prende certificati e chiavi private. Prende le credenziali di più di venti strumenti di programmazione con l’AI: Claude Code, Cursor, Copilot, Gemini CLI, Codex, Windsurf, l’elenco continua. E se trova il database del proxy, lo interroga direttamente e si porta via tutte le chiavi dei fornitori che ci sono dentro. Tutte.
Il bottino viene cifrato e spedito a un sito con lo stesso nome del produttore, registrato una settimana prima, il 13 ottobre. Un dettaglio parla da solo: il programma segna di aver finito solo quando il server dei ladri risponde «ricevuto». Finché la spedizione fallisce, riprova a ogni avvio.
Il terzo file è una porta sul retro, e funziona solo su Linux e macOS. Ogni ora controlla un file ospitato su GitHub, in attesa di un indirizzo. Se ci trova un dominio, scarica da lì ed esegue qualunque codice gli venga servito. Quando Wiz l’ha analizzato, quel file conteneva solo valori di prova: nessun indirizzo operativo. GitHub ha chiuso il repository alle 13:30 UTC. Wiz aggiunge che usare insieme le due tecniche di avvio automatico, il file di percorso e il file di personalizzazione di Python, sembra essere il primo caso documentato in un attacco reale.
Alle 11:39 UTC il pacchetto era su PyPI. Alle 13:20 era in quarantena. Le immagini Docker con l’etichetta «ultima versione», quelle che molti server scaricano in automatico al riavvio, sono rimaste infette più a lungo, fino alle 13:53 UTC circa secondo Wiz. Nessuno ha ancora detto quante installazioni hanno scaricato quella versione. StepSecurity spiega perché il numero potrebbe essere alto: LiteLLM pubblica aggiornamenti di continuo, dodici in quattro giorni, e tantissimi progetti lo richiedono con un vincolo aperto, «qualunque versione dalla tale in su». Con quei vincoli aperti, un’installazione pulita o un aggiornamento delle dipendenze in quella finestra poteva selezionare da sola uno dei pacchetti infetti, senza che nessuno lo chiedesse.
Come sono entrati: la chiave era nel diario
Qui la storia smette di essere una storia di hacker e diventa una storia di uffici.
Il codice sorgente di LiteLLM, quello pubblico su GitHub, era pulito. La versione 1.107.0 che si poteva leggere non conteneva niente di strano. Il veleno è stato aggiunto nel passaggio fra la lettura e l’impacchettamento: l’attaccante ha creato una copia del repository con un nome quasi identico, un trattino in più, Berri-AI invece di BerriAI, ci ha aggiunto dieci modifiche fra le 8:56 e le 10:46 UTC di quella mattina, e poi ha fatto partire la catena ufficiale di pubblicazione di BerriAI puntandola alla copia. Quello che la gente ha scaricato arrivava dai canali ufficiali, costruito dalla catena ufficiale di pubblicazione a partire dalla copia manomessa. Era una versione vera, a modo suo: l’avevano costruita le macchine giuste, con le credenziali giuste.
Le credenziali, dice BerriAI, erano i token GitHub di tre dei suoi ingegneri, cioè le chiavi con cui quegli account operano sui repository. Con l’account del primo l’attaccante ha avviato la pubblicazione; con quello del secondo l’ha approvata. E come se li era procurati? La spiegazione dell’azienda, che la presenta ancora come un’ipotesi della propria indagine, è la riga più istruttiva di tutta la vicenda. In certe situazioni, scrive BerriAI, Claude Code, lo strumento di Anthropic per programmare con l’AI, «inserisce il token GitHub dell’utente nel corpo della risposta», e dove le risposte vengono registrate «questi token possono comparire nei log di LiteLLM». BerriAI aveva un’installazione interna di LiteLLM esposta su internet. Dentro, hanno trovato un utente che non doveva esserci, con un nome innocuo. Credono che l’attaccante sia entrato lì, forse da una falla corretta di recente, abbia letto i log, e nei log abbia trovato le chiavi della casa.
Pensaci un momento. Se la ricostruzione di BerriAI è giusta, l’azienda che fa il programma che custodisce le chiavi di tutti ha perso le proprie chiavi perché stavano scritte nel suo diario di bordo: un file di testo che registrava le conversazioni con l’AI, e che qualcuno ha letto.
Il log è il registro di quello che il sistema ha fatto. Se ci finiscono risposte che contengono una credenziale, ci finisce anche la credenziale. Ed è esattamente per questo che è il posto in cui si cerca per primo.
Un virus con la grafia dell’AI
C’è un secondo particolare che Wiz segnala quasi di passaggio e che merita una pausa. Il codice del ladro ha «forti indizi di sviluppo assistito da un modello di linguaggio»: nomi di variabili prolissi, gestione degli errori generica e difensiva, percorsi per Windows che falliscono in silenzio perché cercano una cartella che su Windows non esiste, e un intero modulo definito e mai chiamato. La struttura, scrive Wiz, «suggerisce prompt iterativi: funziona nel caso felice, è fragile ai bordi e non è stato testato».
Sono indizi ricavati dal codice, non una ricostruzione verificata di come sia stato scritto. Ma raccontano una cosa: chi ha scritto questo ladro, con ogni probabilità, si è fatto aiutare da un modello e l’ha spedito così com’era. Funzionava abbastanza. Circa quattro ore e mezza dopo i primi furti, fra le 16:20 e le 17:01 UTC, Wiz ha visto le credenziali cloud rubate essere provate una per una e poi usate per elencare i modelli AI disponibili su Amazon Bedrock. È il primo passo dello schema che avevamo raccontato pochi giorni fa: chi ruba una chiave AI oggi la cerca per far girare la sua AI a spese tue. Quanto sia stato consumato e addebitato, in questo caso, le fonti non lo dicono.
È un cerchio quasi perfetto. Un programma scritto, a quanto pare, con l’aiuto di un’AI ruba le chiavi delle AI; le chiavi di chi lo distribuiva, se BerriAI ha ragione, erano uscite da un log di conversazioni con un’AI; e le chiavi rubate sono state provate subito contro altri servizi di AI. In mezzo, gli account di due persone, usati da qualcun altro per avviare e approvare la pubblicazione.
Seconda volta in sette mesi
LiteLLM era già stato avvelenato a marzo, con le versioni 1.82.7 e 1.82.8, nell’ondata di attacchi alla catena di distribuzione del software attribuita al gruppo TeamPCP. Stessa tecnica di avvio automatico, stesso tipo di file. Sette mesi dopo, un attaccante diverso o lo stesso, nessuno lo dice, è rientrato da una porta diversa.
BerriAI ha revocato tutti i token coinvolti, ha tolto dalla propria organizzazione GitHub tutti gli utenti tranne uno, ha spezzato i collegamenti di fiducia fra i registri pubblici e il proprio GitHub, così che nessuno possa pubblicare un’altra versione in quel modo. E ha scritto, con un’onestà rara, che non avendo ancora capito come siano stati presi i token «non può affermare che non ci sia ulteriore accesso» agli account. È la frase giusta. È anche la frase che nessun cliente vorrebbe leggere dal fornitore che tiene le sue chiavi.
Cosa c’entra chi non ha mai scritto una riga di codice
Se hai fatto fare un assistente, un chatbot, un sistema che legge le mail o che risponde ai clienti, in mezzo potrebbe esserci LiteLLM o un suo cugino. L’agenzia lo usa per non legarsi a un fornitore solo. Il consulente lo usa per tenere in un posto unico le chiavi di tutti i modelli che prova. Tu non lo vedi, come non vedi il contatore dell’acqua. Vedi la bolletta.
E la bolletta è il punto. Le chiavi rubate in questo attacco sono le chiavi che pagano: ogni chiamata a un modello fatta con la tua chiave viene addebitata a te. Se il tuo fornitore ha installato uno dei pacchetti compilati della versione 1.107.0, o ha avviato un’immagine Docker compromessa (le etichette latest, main-latest e main-stable scaricate il 21 ottobre), le chiavi che ti ha configurato sono da considerare in mano ad altri. StepSecurity lo scrive senza sfumature: quella macchina va trattata come interamente compromessa.
È la stessa lezione di stamattina, vista dall’altro lato. Nell’attacco a Microsoft 365 guidato da agenti AI, gli intrusi entravano con la chiave di un’applicazione di backup di cui i clienti non conoscevano nemmeno il nome. Qui entrano con la chiave di una libreria che gli sviluppatori installano senza pensarci. La fiducia delegata ha sempre un anello che non guardi. E quello è l’anello che cede.
Come portarlo nel tuo lavoro
Se sviluppi, o se hai qualcuno che sviluppa per te, la prima cosa da fare non si discute. Controllare se LiteLLM 1.107.0 è stato installato da pacchetto compilato o avviato da un’immagine Docker compromessa. Se sì: trattare la macchina come compromessa e, da un ambiente pulito, revocare e sostituire tutte le chiavi che poteva raggiungere. Non solo quelle dei modelli AI. Quelle del cloud, dei server, del browser, dei repository. Il ladro non faceva distinzioni, e nemmeno tu dovresti farne. Prima di riusare quella macchina: eliminare i tre file, fermare il processo rimasto in sottofondo o, meglio, rifare da zero l’ambiente, con LiteLLM fissato alla 1.106.2 e, per Docker, l’immagine fissata per impronta e non per etichetta.
Poi le regole che valgono anche quando non c’è un incendio. Una chiave per ogni progetto e, dove il fornitore lo permette, un limite di spesa: una chiave rubata fa meno danni se può spendere poco. Le versioni dei programmi fissate: «dall’ultima in su» è una scommessa che fai ogni notte senza saperlo. E i log. Chiedi a chi lavora per te cosa finisce nei registri del sistema: se una risposta dell’AI contiene una credenziale e viene salvata per intero, nel registro finisce anche la credenziale. Un log che nessuno ripulisce è un archivio di chiavi che aspetta solo un lettore.
Infine, una domanda da fare al fornitore, non per metterlo in difficoltà ma per capire con chi lavori: «cosa succede alle nostre chiavi se il tuo server viene compromesso?». Se la risposta è un piano, bene. Se la risposta è una faccia, hai imparato qualcosa.
Chi tiene il mazzo di chiavi di tutti deve aspettarsi che tutti vengano a cercarlo. E deve saper dire, prima che succeda, cosa farà quando succede.
👉 Leggi anche: 1Password: l’agente entra, la password no
Domande frequenti
Cos’è LiteLLM?
Una libreria Python e un «proxy» sviluppati da BerriAI che mettono più di cento fornitori di modelli di intelligenza artificiale dietro un’unica interfaccia, scritta come quella di OpenAI. Gli sviluppatori la usano per cambiare modello senza riscrivere il codice; nelle installazioni di produzione il proxy custodisce le chiavi di tutti i fornitori configurati.
Quale versione è compromessa e per quanto tempo è stata online?
La 1.107.0, pubblicata su PyPI il 21 ottobre 2026 alle 11:39 UTC e messa in quarantena alle 13:20. Tutti e sette i pacchetti compilati erano infetti; le immagini Docker ufficiali, comprese quelle con le etichette latest, main-latest e main-stable, sono rimaste infette fino alle 13:53 UTC circa, secondo Wiz. L’ultima versione sicura è la 1.106.2.
Cosa rubava?
Password e cookie dei browser, chiavi SSH e GPG, credenziali di AWS, Google Cloud e Azure, su Linux le variabili d’ambiente dei processi a cui riusciva ad accedere, file .env, certificati e chiavi private, le credenziali di più di venti strumenti di programmazione con l’AI (Claude Code, Cursor, Copilot, Codex, Gemini CLI e altri) e, se trovava il database del proxy, tutte le chiavi dei fornitori configurati. Il tutto cifrato e inviato a un dominio che imitava quello del produttore. Su Linux e macOS, un secondo componente controllava ogni ora un file su GitHub in attesa di un indirizzo da cui scaricare altro codice: al momento dell’analisi, Wiz non aveva osservato scaricamenti né esecuzioni di altro codice attraverso questo componente.
Come hanno fatto a pubblicarla come versione ufficiale?
Secondo BerriAI, usando i token GitHub di tre ingegneri: uno per avviare la pubblicazione, uno per approvarla. La versione è stata costruita da una copia del repository con un nome quasi identico (Berri-AI, con il trattino), in cui l’attaccante aveva inserito il codice malevolo. BerriAI ritiene che i token fossero finiti nei log della propria installazione interna di LiteLLM, esposta su internet, perché in certe situazioni Claude Code includeva il token nel corpo delle risposte registrate. L’azienda lo presenta come ipotesi: come l’attaccante sia entrato nell’installazione non è ancora confermato.
Cosa devo fare se l’ho installata?
Trattare la macchina come compromessa: da un ambiente pulito revocare e sostituire tutte le credenziali che poteva raggiungere, chiavi dei fornitori AI comprese; poi eliminare i tre file malevoli e fermare il processo rimasto in sottofondo, o meglio ricreare da zero l’ambiente, con LiteLLM fissato alla 1.106.2 (per Docker, l’immagine fissata per impronta). Bloccare il dominio litellm.dev. Le istruzioni passo per passo sono nelle analisi di StepSecurity e Wiz linkate fra le fonti.
Io non programmo: mi riguarda?
Se qualcuno ha costruito per te un servizio basato sull’AI, chiedigli se usa LiteLLM e se ha controllato. Le chiavi configurate in un proxy compromesso sono le tue, e ogni uso che ne fa un ladro viene addebitato a te. In generale: chiavi separate per progetto, con un limite di spesa dove il fornitore lo permette, e versioni dei programmi fissate.
Fonti
- Wiz Research, «LiteLLM Compromised, Steals Credentials», 21 ottobre 2026
- StepSecurity, «litellm 1.107.0 Compromised on PyPI: Backdoored Wheels Drop a Credential Stealer and an Hourly Remote Code Loader», 21 ottobre 2026
- Repository BerriAI/litellm, issue #47826 «[SECURITY] litellm 1.107.0 compromised», 21 ottobre 2026
- The Hacker News, «LiteLLM Compromised in Supply Chain Attack Delivering Credential Stealer and Backdoor», 21 ottobre 2026