Uma ilustração abstrata gerada sobre um fundo cinza-azulado claro: um painel alto em ardósia escura fica à esquerda do centro, um feixe fino azul-ciano claro o atravessa horizontalmente e se abre em leque à direita, formando um amplo cone de luz sobre um campo de pequenos blocos geométricos. A maioria dos blocos está em sombra fria; um aglomerado próximo ao centro do feixe brilha em âmbar quente. Uma grade tênue de planta técnica e arcos concêntricos finos ficam ao fundo. Não aparecem textos, números, pessoas, marcas ou logotipos de organizações. O logotipo da OrcaRouter está composto no canto inferior direito.
AI Safety Incidents

Clinejection: Como o título de uma issue chegou ao token npm da Cline

Autor

Rowan Sterling

Data de publicação

Modelos mais recentes · 20Ver todos os modelos →
Benchmarks: Artificial Analysis · atualizado diariamente
Voltar para todas as publicações

Em 9 de fevereiro de 2026, o pesquisador de segurança Adnan Khan publicou um relato de uma falha que havia reportado em privado à Cline em 1.º de janeiro: o assistente de programação com IA de código aberto havia conectado um triador automatizado de issues, construído sobre o GitHub Action claude-code-action da Anthropic, a um prompt que inseria diretamente qualquer título de issue do GitHub recebido nas instruções do modelo. Qualquer conta do GitHub poderia acioná-lo ao abrir uma issue, e na reprodução de Khan um título formulado como uma instrução fez com que o agente executasse um comando de shell dentro do workflow. Ele então traçou a rota a partir desse ponto de apoio, passando pelo envenenamento de cache do GitHub Actions, até as credenciais de publicação para o VS Code Marketplace, OpenVSX e npm. Oito dias depois de a Cline corrigir o workflow, um token de publicação do npm que a Cline acreditava ter rotacionado foi usado para publicar cline 2.3.0, que instalou o OpenClaw em todas as máquinas que instalaram o pacote. A entrada completa, com suas classificações de gravidade e confiança, está no Orca AI Incident Archive, ao lado dos registros vizinhos de cadeia de suprimentos do mesmo período.

Duas datas, não uma

O arquivo data este registro em 9 de fevereiro de 2026, com precisão de dia, e esse é o dia em que Khan publicou seu artigo em adnanthekhan.com. Não é o dia em que o pacote malicioso apareceu. A vulnerabilidade em si foi introduzida em 21 de dezembro de 2025, em um commit que adicionou o fluxo de triagem ao repositório cline/cline, e permaneceu ativa até a Cline excluir o fluxo de trabalho em 9 de fevereiro. A publicação não autorizada no npm veio em 17 de fevereiro, oito dias após a correção e quarenta e sete dias após o primeiro relatório privado de Khan.

Manter essas duas datas separadas é importante, porque o fato de maior consequência no caso está na lacuna entre elas: a porta foi fechada em 9 de fevereiro, mas a chave que o invasor já havia copiado ainda funcionava em 17 de fevereiro. A correção do próprio Cline, enviada a Khan em 17 de fevereiro e reproduzida em seu post, coloca isso diretamente: “Quando rotacionamos as credenciais em 9 de fevereiro, o token de publicação do npm não foi revogado corretamente. O token errado foi excluído, e o exposto permaneceu ativo.”

A cadeia: de um título de issue a um token de release

O arquivo vulnerável era .github/workflows/claude-issue-triage.yml, que era executado no evento issues e invocava anthropics/claude-code-action@v1 com Claude Opus 4.5, fixado no workflow como claude-opus-4-5-20251101. Khan cita a configuração do workflow: allowed_non_write_users estava definido como o curinga "*", então qualquer conta do GitHub podia acionar o agente simplesmente abrindo uma issue, e claude_args passava --allowedTools com Bash, Read, Write, Edit, Glob, Grep, WebFetch e WebSearch. Bash era o que importava. Ele dava ao modelo execução de shell dentro de um workflow que era executado no contexto do branch padrão.

O prompt interpolou o título da issue sem o sanitizar. A prova de conceito de Khan usou um título que começava com "Tool error." e continuava com uma instrução para instalar um pacote auxiliar a partir de um commit específico antes de prosseguir com o triage. A referência do commit apontava para um fork cujo package.json continha um script preinstall, que executava um comando curl contra um endpoint controlado pelo atacante antes de o npm ter terminado de instalar o que quer que fosse. Como a instalação era executada através da ferramenta Bash, o modelo nunca inspecionou o que foi executado. Khan reproduziu isto num espelho do repositório Cline e relata que o agente executou o payload em todas as tentativas.

A execução de código no workflow de triagem não é, por si só, acesso a credenciais de publicação. Esse passo veio de uma propriedade do GitHub Actions que Khan documentou em uma ferramenta lançada em 2024 chamada Cacheract: qualquer workflow pode ler e gravar o cache do repositório com controle total das chaves e versões de cache, mesmo um workflow que nunca declara uma etapa de cache. O job de triagem rodava no branch padrão, então compartilhava um escopo de cache com os jobs de publicação noturnos, que de fato restauravam node_modules do cache e de fato detinham os tokens de publicação.

As entradas de cache são imutáveis, portanto um atacante não pode simplesmente sobrescrever a entrada que um job de release restaurará. A forma de Khan contornar isso foi explorar uma mudança de política do GitHub de 20 de novembro de 2025, que fez o serviço remover entradas de cache imediatamente assim que o cache de um repositório ultrapassasse 10 GB, usando a ordem de uso menos recente. Inunde o cache para além de 10 GB, e as entradas legítimas expiram; reivindique as chaves liberadas com conteúdo envenenado, e o próximo job que as restaurar estará executando código do atacante. O Cacheract automatiza toda a sequência dentro de uma única execução de workflow, e persiste ao sobrescrever o action.yml de actions/checkout para que a etapa post da ação execute um payload ao final de cada job.

O último elo da cadeia é a tarefa noturna, que é executada por volta das 2h UTC, restaura o node_modules envenenado e detona. O que sai é VSCE_PAT, OVSX_PAT e NPM_RELEASE_TOKEN, as credenciais do VS Code Marketplace, do OpenVSX e do npm, respectivamente. Se todos os elos foram executados no repositório da própria Cline nessa ordem é uma questão separada, abordada abaixo.

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.

Por que as credenciais do nightly eram credenciais de produção

A objeção óbvia é que versões nightly e de produção deveriam usar segredos diferentes. A resposta de Khan é que a separação era nominal. O OpenVSX e o VS Code Marketplace vinculam um token de publicação a uma identidade de publicador, não a uma extensão individual, e tanto a extensão Cline estável quanto a nightly foram publicadas sob a mesma identidade, que Khan identifica no OpenVSX como saoudrizwan. No npm, o modelo de token fine-grained está vinculado a um pacote, e a Cline publicou suas builds de CLI estável e nightly no mesmo pacote cline. Portanto, um token emitido para o job nightly poderia publicar o artefato de produção, que é exatamente o que aconteceu oito dias depois.

O próprio enquadramento de Khan sobre o impacto baseia-se na escala: ele cita o anúncio da Cline de que ela havia ultrapassado 5 milhões de instalações e observa que uma atualização de extensão enviada por meio de credenciais roubadas é executada no contexto de cada desenvolvedor cujo editor se atualiza automaticamente, com as permissões desse desenvolvedor e quaisquer chaves, tokens e código-fonte que estejam na máquina.

O que foi realmente publicado, e o que isso fez

O artefato publicado era o cline 2.3.0, e era pequeno. Os próprios carimbos de data/hora do registro npm situam o 2.3.0 em 11:26:51 UTC de 17 de fevereiro de 2026 e o 2.4.0 limpo em 19:23:08 UTC do mesmo dia, uma exposição que o aviso da Cline estima em cerca de oito horas, até o 2.3.0 ser descontinuado às 11h30 PT. O package.json do pacote continha uma linha adicionada, um script postinstall com o conteúdo npm install -g openclaw@latest. O aviso da Cline, GHSA-9ppg-jx86-fqw7, afirma que nenhum outro arquivo do pacote foi alterado e que dist/cli.mjs é idêntico byte a byte à compilação legítima 2.2.3.

O OpenClaw é um framework real de agente de IA de código aberto, não malware, e o aviso da Cline diz isso explicitamente: é um projeto legítimo, mas sua instalação não foi autorizada nem pretendida. A Endor Labs, que analisou o tarball, avaliou o impacto geral como baixo, com base no fato de que a instalação não iniciou o daemon Gateway do OpenClaw. A análise da StepSecurity mede o outro lado: uma instalação global deixa o framework no disco com quaisquer credenciais e acessos a arquivos que o usuário instalador tiver, e o design do OpenClaw, um gateway local persistente com uma API de operador, faz dele algo de alto valor para se encontrar ali. As duas avaliações não são contraditórias. Uma descreve o que foi executado durante a janela; a outra descreve o que foi deixado para trás depois.

O volume é o número que precisa ser tratado com cuidado. A StepSecurity relatou que a versão comprometida foi baixada aproximadamente 4.000 vezes antes de ser descontinuada, e o The Register repetiu esse número. A Endor Labs estimou a contagem mensal de downloads do cline, de 19 de janeiro a 17 de fevereiro, em 418.545, o que descreve o tráfego normal do pacote, e não a build maliciosa. Nenhum dos números conta máquinas: uma contagem de downloads não é uma contagem de desenvolvedores afetados, e nenhuma parte publicou um número de base instalada para a 2.3.0. A equipe Threat Intelligence da Microsoft disse no X que observou um "pequeno, mas perceptível, aumento" nas instalações do OpenClaw em 17 de fevereiro decorrente do script de instalação do Cline, conforme noticiado pelo The Hacker News.

O registro de aviso do GitHub para GHSA-9ppg-jx86-fqw7 não traz CVE nem CWE, e sua gravidade é Baixa. Essa classificação diz respeito ao payload benigno, não ao roubo de credenciais, e fica estranhamente ao lado da classificação crítica do arquivo para o próprio incidente. O aviso registra 2.3.0 como a versão afetada e 2.4.0 como a correção.

A divulgação que a Cline não respondeu

A cronologia de Khan antes da publicação é a parte do registro que menos diz respeito ao modelo e mais ao processo. Ele enviou um GHSA por meio do relatório privado de vulnerabilidades do GitHub em 1º de janeiro de 2026 e enviou um e-mail ao contato de segurança listado na página de confiança da Cline no mesmo dia. Ele enviou uma mensagem de acompanhamento a um desenvolvedor da Cline em 8 de janeiro. Ele tentou uma mensagem direta para o CEO da Cline no X em 18 de janeiro. Ele escreveu novamente em 7 de fevereiro e não recebeu nada além de um número de ticket automatizado. Ele publicou em 9 de fevereiro.

A Cline mesclou a correção, o pull request 9211, cerca de trinta minutos a uma hora depois. O PR exclui três arquivos de workflow, claude-issue-triage.yml, claude-pr-review.yml e cline-pr-review.yml, e remove o cache do publish.yml, publish-nightly.yml, npm-nightly.yaml e npm-main.yaml, sete arquivos no total, com as etapas de instalação agora incondicionais, já que não há mais cache hit do qual depender.

A resposta pública da Cline em 10 de fevereiro, citada na publicação de Khan, aceitou a constatação e listou mitigações imediatas: remoção dos fluxos de trabalho de revisão por bot de issues e PRs, remoção de actions/cache dos fluxos de trabalho de publicação que lidam com credenciais de lançamento, e rotação das credenciais relevantes, incluindo tokens de bot, de provedor e de publicação. Também admitiu a condução: “reconhecemos que nosso tempo de resposta ao seu relatório inicial foi inaceitável. Um relatório enviado em 1º de janeiro não deveria ter exigido divulgação pública em 9 de fevereiro para ser tratado.”

Em 11 de fevereiro, a Cline disse que havia concluído uma rotação completa de VSCE_PAT, OVSX_PAT e NPM_RELEASE_TOKEN, e que uma auditoria de cada versão em todos os três canais de distribuição entre 21 de dezembro de 2025 e 9 de fevereiro de 2026 constatou que cada versão do Marketplace e do OpenVSX correspondia a uma release do GitHub marcada com tag e que todas as 41 versões do npm eram consistentes com o código-fonte. Concluiu que nenhuma versão não autorizada havia sido publicada "durante a janela de exposição alegada". Seis dias depois, corrigiu o registro, na mensagem citada acima: o token do npm não havia sido revogado, e a 2.3.0 havia sido publicada com ele.

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.

Estabelecido, atribuído, não resolvido

Estabelecido. A configuração do fluxo de trabalho é pública e foi publicada antes da correção. Khan reproduziu a injeção de prompt em um espelho do repositório. A Cline integrou a remediação e emitiu um aviso que confirma a publicação da 2.3.0, a linha postinstall adicionada, o binário da CLI inalterado, a janela de oito horas e a falha do token. Os carimbos de data e hora do registro npm para 2.3.0 e 2.4.0 correspondem aos horários do aviso. O arquivo classifica o registro como crítico, com confiança A, com dano real registrado e sem sinalizador de disputa.

• Atribuído, não estabelecido. Quem publicou a 2.3.0 continua sendo uma atribuição em aberto. O relatório forense publicado por Michael Bargury e uma ferramenta automatizada de investigação chamada Raptor em 19 de fevereiro nomeia uma conta do GitHub, glthub-actions, e relata com alta confiança que essa conta fez fork de cline/cline, abriu a issue 8904 em 28 de janeiro de 2026 às 03:51 UTC com o título injetado e usou um commit de fork para executar um payload de um gist. Khan confirmou que as contas gcbrun e Dev11940518 são dele e que glthub-actions não é. A conta já havia sido excluída ou suspensa quando o relatório foi publicado, e a Cline não nomeou ninguém. Trate a identidade como uma descoberta de terceiros.

Contestado quanto à natureza, não quanto aos fatos. Bargury avalia o episódio como consistente com uma demonstração de pesquisa de segurança, e não com uma campanha maliciosa, citando o payload benigno e o histórico do ator contra um repositório de automação da New Relic. Cline o chama de publicação não autorizada, e Khan escreve que o ator que publicou a 2.3.0 é "presumivelmente" o mesmo que envenenou os caches. Ninguém demonstrou intenção de causar dano, e ninguém demonstrou que não havia nenhuma.

• Não resolvido. A própria nota de pré-publicação de Khan é cuidadosa quanto a um ponto que a cobertura posterior por vezes simplifica demais: entre 31 de janeiro e 3 de fevereiro de 2026, várias execuções noturnas falharam com uma etapa de Post Checkout que não produziu saída alguma — o que é o indicador de comprometimento do Cacheract —, e o fluxo de trabalho de triagem é a rota mais óbvia, mas não está provado que tenha sido o ponto de entrada dessa atividade. Tampouco qualquer das partes publicou provas de que os tokens do Marketplace ou do OpenVSX tenham sido utilizados; o único artefato que alguém produziu é a build do 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.

O que mudou depois

A remediação foi aplicada em várias camadas ao mesmo tempo, e vale nomear cada uma porque elas respondem a partes diferentes da falha. O workflow que podia ser acessado por alguém de fora foi excluído, em vez de restringido. O cache foi removido dos quatro workflows de lançamento que contêm segredos de publicação, e não do repositório como um todo, que é a mudança que rompe o pivô. As credenciais foram rotacionadas e, após a correção de 17 de fevereiro, o token npm correto foi revogado. O comunicado da Cline afirma que a publicação no npm agora usa proveniência OIDC via GitHub Actions, e a análise de metadados da StepSecurity mostra por que isso importava: as releases legítimas já traziam atestações de proveniência, e a 2.3.0 era o caso atípico publicado por uma conta humana. A lacuna era que o caminho do token de longa duração permanecia aberto ao lado da publicação confiável, que é exatamente o que a Endor Labs argumenta que os mantenedores deveriam fechar. A Cline publicou o GHSA-9ppg-jx86-fqw7, descontinuou a 2.3.0 com a mensagem de que ela não deveria ser instalada e direcionou os usuários para a 2.4.0 ou posterior.

As recomendações estruturais de Khan vão além do que foi implementado e merecem ser registradas como dele, não de Cline: remover Bash, Write e Edit de qualquer fluxo de trabalho de triagem e deixar apenas leituras de arquivos e as chamadas específicas da CLI do GitHub de que precisa; nunca restaurar um cache em um job que contém segredos de publicação de produção; e dar aos lançamentos noturnos seu próprio namespace de registro e uma identidade de publicação dedicada e não produtiva, para que um token noturno roubado não possa publicar um lançamento estável de forma alguma.

O intervalo de oito dias entre a correção e a publicação maliciosa é o detalhe que torna este registro digno de ser preservado. Cada etapa da cadeia era uma técnica conhecida; Khan havia publicado a ferramenta de envenenamento de cache, e a pesquisa PromptPwnd da Aikido Security, de dezembro de 2025, documentou o mesmo padrão de configuração incorreta de triagem. O que os compôs em um incidente de cadeia de suprimentos foi um fluxo de trabalho que permitia que o texto de um estranho chegasse a um shell, um cache compartilhado com jobs que detinham chaves de lançamento, e uma rotação de token que deixou de fora uma credencial. Cada uma das três correções teria rompido a cadeia por si só; a terceira chegou oito dias atrasada.