Un'illustrazione astratta generata su un campo grigio-azzurro pallido: un alto pannello in ardesia scura si erge a sinistra del centro, un sottile raggio ciano pallido lo attraversa orizzontalmente e si apre a ventaglio sulla destra in un ampio cono di luce su un campo di piccoli blocchi geometrici. La maggior parte dei blocchi è in ombra fredda; un gruppo vicino al centro del raggio brilla di un ambra calda. Una lieve griglia da disegno tecnico e sottili archi concentrici si trovano sullo sfondo. Non compaiono testi, numeri, persone, marchi o loghi di organizzazioni. Il logo OrcaRouter è sovrapposto nell'angolo in basso a destra.
AI Safety Incidents

Clinejection: come il titolo di una issue ha raggiunto il token npm di Cline

Autore

Rowan Sterling

Data di pubblicazione

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

Il 9 febbraio 2026 il ricercatore di sicurezza Adnan Khan ha pubblicato il resoconto di una vulnerabilità che aveva segnalato privatamente a Cline il 1° gennaio: l'assistente open source per la programmazione basato sull'IA aveva collegato un triager automatico delle issue, costruito sulla GitHub Action claude-code-action di Anthropic, a un prompt che incollava direttamente nelle istruzioni del modello qualsiasi titolo di issue GitHub in arrivo. Qualsiasi account GitHub poteva attivarlo aprendo una issue e, nella riproduzione di Khan, un titolo formulato come istruzione ha indotto l'agente a eseguire un comando shell all'interno del workflow. Ha poi ricostruito il percorso da quel punto d'appoggio, attraverso l'avvelenamento della cache di GitHub Actions, fino alle credenziali di rilascio per VS Code Marketplace, OpenVSX e npm. Otto giorni dopo che Cline ha corretto il workflow, un token di pubblicazione npm che Cline riteneva di aver ruotato è stato usato per pubblicare cline 2.3.0, che installava OpenClaw su ogni macchina che installava il pacchetto. La voce completa, con i suoi gradi di gravità e di confidenza, si trova nell'Orca AI Incident Archive, accanto ai registri vicini della supply chain dello stesso periodo.

Due date, non una.

L'archivio data questo record al 9 febbraio 2026, con precisione al giorno, e quello è il giorno in cui Khan ha pubblicato il suo resoconto su adnanthekhan.com. Non è il giorno in cui è apparso il pacchetto malevolo. La vulnerabilità stessa è stata introdotta il 21 dicembre 2025, in un commit che ha aggiunto il flusso di lavoro di triage al repository cline/cline, ed è rimasta attiva fino a quando Cline ha eliminato il flusso di lavoro il 9 febbraio. La pubblicazione non autorizzata su npm è avvenuta il 17 febbraio, otto giorni dopo la correzione e quarantasette giorni dopo il primo rapporto privato di Khan.

Tenere separate quelle due date è importante, perché il fatto più rilevante del caso si colloca proprio nello spazio tra di esse: la porta è stata chiusa il 9 febbraio, ma la chiave che l'intruso aveva già copiato funzionava ancora il 17 febbraio. La correzione di Cline stesso, inviata a Khan il 17 febbraio e riprodotta nel suo post, lo dice chiaramente: «Quando abbiamo ruotato le credenziali il 9 febbraio, il token di pubblicazione npm non è stato revocato correttamente. È stato eliminato il token sbagliato, e quello esposto è rimasto attivo».

La catena: dal titolo di un issue a un token di rilascio

Il file vulnerabile era .github/workflows/claude-issue-triage.yml, che veniva eseguito sull'evento issues e richiamava anthropics/claude-code-action@v1 con Claude Opus 4.5, fissato nel workflow come claude-opus-4-5-20251101. Khan cita la configurazione del workflow: allowed_non_write_users era impostato sul carattere jolly "*", quindi qualsiasi account GitHub poteva attivare l'agente semplicemente aprendo una issue, e claude_args passava --allowedTools con Bash, Read, Write, Edit, Glob, Grep, WebFetch e WebSearch. Bash era quello che contava. Dava al modello l'esecuzione della shell all'interno di un workflow eseguito nel contesto del branch predefinito.

Il prompt ha interpolato il titolo della issue senza sanitizzarlo. La proof of concept di Khan utilizzava un titolo che iniziava con "Tool error." e proseguiva con un'istruzione di installare un pacchetto helper da uno specifico commit prima di continuare con il triage. Il riferimento al commit puntava a una fork il cui package.json conteneva uno script preinstall, che eseguiva un comando curl verso un endpoint controllato dall'attaccante prima che npm avesse finito di installare qualsiasi cosa. Poiché l'installazione veniva eseguita tramite lo strumento Bash, il modello non ha mai ispezionato ciò che veniva eseguito. Khan ha riprodotto questo su un mirror del repository Cline e riferisce che l'agente ha eseguito il payload in ogni tentativo.

L'esecuzione di codice nel flusso di lavoro di triage non costituisce, di per sé, un accesso alle credenziali di rilascio. Quel passaggio derivava da una proprietà di GitHub Actions che Khan aveva documentato in uno strumento del 2024 da lui rilasciato chiamato Cacheract: qualsiasi flusso di lavoro può leggere e scrivere nella cache del repository con pieno controllo delle chiavi e delle versioni della cache, anche un flusso di lavoro che non dichiara mai un passaggio di caching. Il job di triage veniva eseguito sul branch predefinito, quindi condivideva un ambito di cache con i job di pubblicazione notturni, che ripristinavano effettivamente node_modules dalla cache e detenevano i token di pubblicazione.

Le voci della cache sono immutabili, quindi un attaccante non può semplicemente sovrascrivere la voce che un job di rilascio ripristinerà. La soluzione di Khan per aggirare questo problema è stata sfruttare un cambiamento delle policy di GitHub del 20 novembre 2025, che ha indotto il servizio a espellere immediatamente le voci della cache non appena la cache di un repository superava i 10 GB, usando l'ordine least-recently-used. Inonda la cache oltre i 10 GB e le voci legittime vengono eliminate per anzianità; impossessati delle chiavi liberate con contenuti avvelenati e il prossimo job che le ripristina eseguirà codice dell'attaccante. Cacheract automatizza l'intera sequenza all'interno di una singola esecuzione di workflow e persiste sovrascrivendo il file action.yml di actions/checkout in modo che il post step dell'action esegua un payload alla fine di ogni job.

L'ultimo anello della catena è il job notturno, che viene eseguito all'incirca alle 2:00 UTC, ripristina il node_modules avvelenato e detona. Ciò che ne esce sono VSCE_PAT, OVSX_PAT e NPM_RELEASE_TOKEN, rispettivamente le credenziali per VS Code Marketplace, OpenVSX e npm. Se ogni anello sia stato eseguito sul repository di Cline in quell'ordine è una questione separata, affrontata di seguito.

A self-built HTML card titled 'Six steps from an issue title to a release token', badged 'Clinejection · GHSA-9ppg-jx86-fqw7', subtitled 'The chain as Adnan Khan describes it, with the workflow configuration he quotes'. Six numbered rows read: 1, Issue opened on cline/cline, the title carries the instructions and allowed_non_write_users is set to the wildcard; 2, claude-issue-triage.yml runs, claude-code-action with Bash, Read, Write, Edit, Glob, Grep, WebFetch and WebSearch; 3, npm install from a fork commit, the fork's package.json carries a preinstall script and the model runs it through Bash; 4, Cache flooded past 10 GB, GitHub's LRU eviction removes the legitimate entries and frees their keys; 5, Poisoned entries claim the keys, the nightly jobs restore attacker content as node_modules; 6, Nightly job runs at about 2 AM UTC, VSCE_PAT, OVSX_PAT and NPM_RELEASE_TOKEN leave the runner. A footer reads 'Source: Adnan Khan, Clinejection, 9 February 2026; Cline advisory GHSA-9ppg-jx86-fqw7.' The OrcaRouter logo is composited in the bottom-right corner.

Perché le credenziali notturne erano credenziali di produzione

L'obiezione ovvia è che le release nightly e di produzione dovrebbero avere segreti diversi. La risposta di Khan è che la separazione era nominale. OpenVSX e il VS Code Marketplace legano un token di pubblicazione a un'identità di publisher, non a una singola estensione, e sia l'estensione stabile sia quella nightly di Cline sono state pubblicate con la stessa identità, che Khan identifica su OpenVSX come saoudrizwan. Su npm, il modello di token fine-grained è legato a un pacchetto, e Cline ha pubblicato le sue build CLI stabili e nightly sullo stesso pacchetto cline. Un token emesso per il job nightly poteva quindi pubblicare l'artefatto di produzione, che è esattamente ciò che è accaduto otto giorni dopo.

La stessa impostazione di Khan sull'impatto si basa sulla scala: cita l'annuncio di Cline secondo cui aveva superato i 5 milioni di installazioni, e osserva che un aggiornamento dell'estensione veicolato tramite credenziali rubate viene eseguito nel contesto di ogni sviluppatore il cui editor si aggiorna automaticamente, con i permessi di quello sviluppatore e con qualunque chiave, token e codice sorgente presente sulla macchina.

Cosa è stato effettivamente pubblicato e cosa ha fatto

L'artefatto pubblicato era cline 2.3.0, ed era piccolo. I timestamp del registro npm stesso collocano la 2.3.0 alle 11:26:51 UTC del 17 febbraio 2026 e la 2.4.0 pulita alle 19:23:08 UTC dello stesso giorno, un'esposizione che l'avviso di Cline stima in circa otto ore, fino a quando la 2.3.0 è stata deprecata alle 11:30 PT. Il package.json del pacchetto conteneva una riga aggiunta, uno script postinstall che riportava npm install -g openclaw@latest. L'avviso di Cline, GHSA-9ppg-jx86-fqw7, afferma che nessun altro file del pacchetto è stato alterato e che dist/cli.mjs è identico byte per byte alla build legittima 2.2.3.

OpenClaw è un vero framework open-source per agenti AI, non malware, e l'avviso di Cline lo afferma esplicitamente: è un progetto legittimo, ma la sua installazione non è stata autorizzata né intenzionale. Endor Labs, che ha analizzato il tarball, ha valutato l'impatto complessivo come basso, sulla base del fatto che l'installazione non ha avviato il daemon Gateway di OpenClaw. L'analisi di StepSecurity misura l'altro aspetto della questione: un'installazione globale lascia il framework su disco con le credenziali e l'accesso ai file di cui dispone l'utente che installa, e il design di OpenClaw, un gateway locale persistente con un'API operatore, lo rende un elemento di alto valore da trovare lì. Le due valutazioni non sono contraddittorie. Una descrive ciò che è stato eseguito durante la finestra; l'altra descrive ciò che è stato lasciato indietro in seguito.

Il volume è l’unico numero che va gestito con attenzione. StepSecurity ha riferito che la versione compromessa è stata scaricata circa 4.000 volte prima di essere deprecata, e The Register ha ripreso quella cifra. Endor Labs ha fissato il numero di download mensili di cline per il periodo dal 19 gennaio al 17 febbraio a 418.545, un dato che descrive il traffico normale del pacchetto anziché la build malevola. Nessuna delle due cifre conta le macchine: un conteggio dei download non è un conteggio degli sviluppatori interessati, e nessuna delle parti ha pubblicato una cifra sulla base installata per la 2.3.0. Il team Threat Intelligence di Microsoft ha dichiarato su X di aver osservato un «lieve ma percepibile aumento» delle installazioni di OpenClaw il 17 febbraio, riconducibile allo script di installazione di Cline, come riportato da The Hacker News.

La scheda di advisory di GitHub per GHSA-9ppg-jx86-fqw7 non riporta alcun CVE né CWE, e la sua gravità è Bassa. Quel grado riguarda il payload benigno, non il furto di credenziali, e stona accanto al grado critico dell'archivio per l'incidente stesso. L'advisory indica la 2.3.0 come versione interessata e la 2.4.0 come correzione.

L'informativa a cui Cline non ha risposto

La cronologia precedente alla pubblicazione di Khan è la parte della documentazione che riguarda meno il modello e più il processo. Ha inviato una GHSA tramite la segnalazione privata di vulnerabilità di GitHub il 1° gennaio 2026 e ha inviato un'email al contatto di sicurezza indicato nella pagina trust di Cline lo stesso giorno. Ha inviato un sollecito a uno sviluppatore di Cline l'8 gennaio. Ha provato a inviare un messaggio diretto al CEO di Cline su X il 18 gennaio. Ha scritto di nuovo il 7 febbraio e non ha ricevuto altro che un numero di ticket automatico. Ha pubblicato il 9 febbraio.

Cline ha eseguito il merge della correzione, pull request 9211, circa da trenta minuti a un'ora dopo. La PR elimina tre file di workflow, claude-issue-triage.yml, claude-pr-review.yml e cline-pr-review.yml, e rimuove la cache da publish.yml, publish-nightly.yml, npm-nightly.yaml e npm-main.yaml, sette file in totale, con i passaggi di installazione ora resi incondizionati dato che non c'è più un cache hit su cui fare affidamento.

La risposta pubblica di Cline del 10 febbraio, citata nel post di Khan, ha accettato la segnalazione e ha elencato le mitigazioni immediate: la rimozione dei workflow di revisione del bot per issue e PR, la rimozione di actions/cache dai workflow di pubblicazione che gestiscono le credenziali di rilascio e la rotazione delle credenziali pertinenti, inclusi i token del bot, del provider e di pubblicazione. Ha inoltre ammesso la gestione: «riconosciamo che il nostro tempo di risposta alla tua segnalazione iniziale sia stato inaccettabile. Una segnalazione inviata il 1° gennaio non avrebbe dovuto richiedere la divulgazione pubblica il 9 febbraio per essere presa in carico.»

L'11 febbraio Cline ha dichiarato di aver completato una rotazione completa di VSCE_PAT, OVSX_PAT e NPM_RELEASE_TOKEN e che un audit di ogni release su tutti e tre i canali di distribuzione tra il 21 dicembre 2025 e il 9 febbraio 2026 aveva rilevato che ogni versione di Marketplace e OpenVSX corrispondeva a una release GitHub con tag e che tutte le 41 versioni npm erano coerenti con il codice sorgente. Ha concluso che nessuna release non autorizzata era stata pubblicata "durante la presunta finestra di esposizione". Sei giorni dopo ha rettificato la dichiarazione, nel messaggio citato sopra: il token npm non era stato revocato e la 2.3.0 era stata pubblicata con esso.

A self-built HTML card titled 'From private report to public disclosure', subtitled 'Khan's pre-publication timeline, and what followed'. Eight dated rows read: 21 Dec 2025, vulnerable claude-issue-triage.yml committed; 1 January 2026, GHSA filed and email sent to Cline's listed security contact; 8 January 2026, follow-up email to a Cline developer, no reply; 18 January 2026, direct message to Cline's CEO on X, no reply; 7 February 2026, final email, automated ticket number only; 9 February 2026, public disclosure and PR 9211 merged within about an hour; 11 February 2026, Cline reports full rotation and a clean audit; 17 February 2026, cline 2.3.0 published with a still-valid npm token. A footer reads 'Times and dates as recorded by Adnan Khan; the 17 February publish timestamp is corroborated by the npm registry.' The OrcaRouter logo is composited in the bottom-right corner.

Stabilito, attribuito, irrisolto

Accertato. La configurazione del workflow è pubblica ed è stata pubblicata prima della correzione. Khan ha riprodotto l'iniezione di prompt su un mirror del repository. Cline ha integrato la correzione e ha emesso un avviso che conferma la pubblicazione della 2.3.0, la riga postinstall aggiunta, il binario CLI invariato, la finestra di otto ore e l'errore del token. I timestamp del registry npm per la 2.3.0 e la 2.4.0 corrispondono agli orari dell'avviso. L'archivio classifica il record come critico, con confidenza A, con danno reale registrato e nessun flag di contestazione.

• Attribuito, non stabilito. Chi abbia pubblicato la 2.3.0 resta un'attribuzione aperta. Il resoconto forense pubblicato da Michael Bargury e uno strumento di indagine automatizzato chiamato Raptor il 19 febbraio nomina un account GitHub, glthub-actions, e riporta con elevata sicurezza che questo account ha eseguito il fork di cline/cline, ha aperto l'issue 8904 il 28 gennaio 2026 alle 03:51 UTC con il titolo iniettato e ha usato un commit del fork per eseguire un payload da un gist. Khan ha confermato che gli account gcbrun e Dev11940518 sono suoi e che glthub-actions non lo è. L'account era già stato eliminato o sospeso quando il resoconto è stato pubblicato, e Cline non ha fatto il nome di nessuno. Trattare l'identità come una conclusione di terze parti.

• Se ne contesta il carattere, non i fatti. Bargury valuta l'episodio come coerente con una dimostrazione di ricerca sulla sicurezza più che con una campagna malevola, citando il payload benigno e la storia dell'attore rispetto a un repository di automazione di New Relic. Cline lo definisce una pubblicazione non autorizzata, e Khan scrive che l'attore che ha pubblicato la 2.3.0 è "presumibilmente" lo stesso che ha avvelenato le cache. Nessuno ha dimostrato un'intenzione di causare danni, e nessuno ha dimostrato che non ce ne fosse alcuna.

• Non risolto. La nota pre-pubblicazione di Khan è cauta su un punto che i resoconti successivi talvolta appiattiscono: tra il 31 gennaio e il 3 febbraio 2026 diverse esecuzioni notturne fallirono con una fase Post Checkout che non produceva alcun output, che è l'indicatore di compromissione di Cacheract, e il flusso di lavoro di triage è la via più ovvia ma non è dimostrato che sia stato il punto di ingresso per tale attività. Né alcuna parte ha pubblicato prove che i token di Marketplace o OpenVSX siano stati utilizzati; l'unico artefatto che qualcuno abbia prodotto è la build npm.

A self-built HTML card titled 'What the record supports', subtitled 'One column is documented, one is other people's findings, one is simply open', split into three columns. The first, headed Established, lists four items: the triage workflow interpolated issue titles into the prompt and allowed any GitHub account to trigger it, with Bash among the tools; Khan reproduced the injection on a mirror of the repository; Cline's advisory GHSA-9ppg-jx86-fqw7 confirms cline 2.3.0, the added postinstall line, the unchanged CLI binary and an eight-hour window; npm registry timestamps place 2.3.0 at 11:26 UTC and 2.4.0 at 19:23 UTC on 17 February 2026. The second, headed Attributed, lists three items: the account glthub-actions and issue 8904 come from a third-party forensic write-up, not from Cline; that the actor copied Khan's public proof-of-concept repository is an inference from timing and from his own statement; that the publish was a research demonstration rather than an attack is one analyst's assessment. The third, headed Unresolved, lists three items: whether the triage workflow was the entry point for the late-January cache anomalies; whether any Marketplace or OpenVSX credential was used, with no artefact published; how many distinct machines installed 2.3.0, since about 4,000 is a download count. A footer reads 'Sources: Adnan Khan, Clinejection, 9 February 2026; Cline, GHSA-9ppg-jx86-fqw7; StepSecurity, 17 February 2026; Endor Labs, 18 February 2026; Michael Bargury and Raptor, 19 February 2026.' The OrcaRouter logo is composited in the bottom-right corner.

Cosa è cambiato in seguito

La correzione è stata applicata su più livelli contemporaneamente, e vale la pena nominarli singolarmente perché rispondono a parti diverse del problema. Il workflow raggiungibile da un esterno è stato eliminato anziché limitato. La cache è stata rimossa dai quattro workflow di rilascio che contengono segreti di pubblicazione, anziché dall'intero repository, ed è questa la modifica che interrompe il pivot. Le credenziali sono state ruotate e, dopo la correzione del 17 febbraio, il token npm corretto è stato revocato. L'avviso di Cline afferma che la pubblicazione su npm ora utilizza la provenienza OIDC tramite GitHub Actions, e l'analisi dei metadati di StepSecurity mostra perché ciò era importante: le release legittime portavano già attestazioni di provenienza, e la 2.3.0 era l'anomalia pubblicata da un account umano. Il problema era che il percorso del token a lunga durata restava aperto insieme alla pubblicazione attendibile, che è esattamente ciò che Endor Labs sostiene che i manutentori dovrebbero chiudere. Cline ha pubblicato GHSA-9ppg-jx86-fqw7, ha deprecato la 2.3.0 con il messaggio che non dovrebbe essere installata e ha indirizzato gli utenti alla 2.4.0 o successiva.

Le raccomandazioni strutturali di Khan vanno oltre quanto è stato implementato, e meritano di essere registrate come sue, non di Cline: rimuovere Bash, Write ed Edit da qualsiasi flusso di lavoro di triage e lasciargli solo la lettura dei file e le specifiche chiamate GitHub CLI di cui ha bisogno; non ripristinare mai una cache in un job che detiene i segreti di pubblicazione di produzione; e dare alle release notturne il proprio namespace di registry e un'identità di pubblicazione dedicata non di produzione, così che un token notturno rubato non possa pubblicare alcuna release stabile.

L'intervallo di otto giorni tra la correzione e la pubblicazione malevola è il dettaglio che rende questo caso degno di essere conservato. Ogni passaggio della catena era una tecnica nota; Khan aveva pubblicato lo strumento di avvelenamento della cache, e la ricerca PromptPwnd di Aikido Security del dicembre 2025 documentava lo stesso schema di errata configurazione del triage. Ciò che li ha trasformati in un incidente della supply chain è stato un flusso di lavoro che consentiva al testo di uno sconosciuto di raggiungere una shell, una cache condivisa con job che detenevano chiavi di rilascio e una rotazione dei token che ha tralasciato una credenziale. Ciascuna delle tre correzioni avrebbe interrotto la catena da sola; la terza è arrivata con otto giorni di ritardo.