Ilustração técnica abstrata sobre um fundo azul-marinho escuro: um pequeno cubo de pacote em vetor plano no centro-esquerda, com uma linha fina descendo em curva até uma representação compacta de uma estação de trabalho de desenvolvedor; um leque de filamentos finos em ciano e azul-aço se espalha para a direita a partir da estação de trabalho em direção a muitos pequenos nós circulares em uma grade solta, dois deles se curvam de volta para cima até o cubo de pacote, e um na extremidade direita fica sozinho e desconectado. Não aparecem pessoas, logotipos nem texto. O logotipo da OrcaRouter está composto no canto inferior direito.
AI Safety Incidents

O SDK npm da Tensorlake foi envenenado para roubar credenciais de agentes de IA — e para apagar seu diretório pessoal se você revogasse o token

Autor

Alistair Wren

Data de publicação

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

Em 8 de outubro de 2026, uma versão envenenada de tensorlake — o SDK npm da plataforma da Tensorlake, que executa código não confiável gerado por LLM dentro de sandboxes isolados — chegou ao registro npm. A versão 0.5.144 foi publicada às 01:12:07 UTC; pesquisadores da Socket dizem que a sinalizaram cerca de onze minutos depois. Não foi uma versão autorizada. A Tensorlake afirma que o atacante enviou código diretamente para o repositório GitHub da empresa e o publicou por meio do próprio fluxo de lançamento do projeto, então o pacote carregava proveniência npm válida — atestado assinado mostrando onde foi construído, para um código-fonte que já havia sido envenenado. A empresa diz que a versão ficou ativa por cerca de 1 hora e 40 minutos, de 01:12 a 02:54 UTC, antes de o npm removê-la.

O payload não precisava de importação nem de um agente em execução. Um preinstall hook no manifesto do pacote executou node lib/setup.mjs, um carregador ofuscado que instalou o runtime Bun na máquina e o usou para executar lib/Math_Symbol.js, um ladrão de credenciais de 856.501 bytes e um verme autorreplicante. Qualquer pessoa que fez uma instalação simples daquela versão o executou. Como era a tag latest do pacote, essa era a versão para a qual uma instalação padrão resolvia enquanto ela estava ativa.

O que faz este registro valer a pena guardar não é o tamanho do payload — a família Shai-Hulud já foi documentada antes. É a lista de alvos. Ao lado de tokens do npm e do GitHub, credenciais da AWS, segredos do Kubernetes e do Vault, chaves SSH, arquivos .env, senhas de navegador e carteiras de criptomoedas, esta build coletou especificamente configurações de ferramentas de desenvolvimento de IA e arquivos MCP — aqueles associados ao Claude Code, Cursor, Kiro, Windsurf e Zed, segundo a Socket. Ele também gravou seus próprios .claude/settings.json e .vscode/tasks.json em repositórios que conseguia alcançar, para que o código fosse executado novamente na próxima vez que um desenvolvedor abrisse esse projeto no Claude Code ou no VS Code. É um ataque à cadeia de suprimentos direcionado diretamente às máquinas nas quais as pessoas criam agentes.

Como o release saiu da conta de um mantenedor

Socket, SafeDep e Aikido publicaram, cada um, a sua própria análise a 8 de outubro, e as suas descrições do mecanismo coincidem. A classificação de confiança do arquivo para este registo é A, não está marcado como contestado, e nada do que foi encontrado nas fontes contradiz qualquer um deles.

O relatório da SafeDep rastreia oito commits até a branch main do repositório entre 01:20 e 03:57 UTC em 7 de outubro, atribuídos a uma conta de administrador do repositório e feitos por meio da interface web do GitHub. O commit que o arquivo cita como o primeiro malicioso é 41b38f0, uma revisão de quatro arquivos de 03:44:48 UTC de 7 de outubro, cuja mensagem é "Add files via upload" e que carrega a assinatura verified do GitHub — o GitHub assina commits feitos em seu próprio editor web, portanto "verified" registra a superfície de edição, não a pessoa. Esse commit não tocou em nenhum arquivo além de typescript/lib/Math_Symbol.js e typescript/lib/setup.mjs, segundo a API do GitHub: o payload, e nada mais.

SafeDep oferece uma interpretação do comportamento do operador, rotulada como sua própria inferência: a primeira edição do hook de pré-instalação quebrou a sintaxe JSON do arquivo e um commit de correção veio dezenove minutos depois, o que ela descreve como consistente com uma pessoa editando arquivos em um navegador, em vez de um pipeline com scripts. Nada publicado pela Socket, SafeDep, Aikido, StepSecurity ou Tensorlake identifica o método pelo qual a conta do mantenedor foi tomada.

O atacante não precisou de um token do npm. A SafeDep relata que a conta iniciou o workflow publish_npm.yaml do projeto manualmente em 8 de outubro às 00:08 UTC; o log de build mostra os arquivos de payload dentro do tarball publicado. A release usou npm trusted publishing, e os pacotes irmãos tensorlake-native-* publicados na mesma execução carregam proveniência SLSA válida — proveniência genuinamente válida para um build de código-fonte envenenado. A release foi publicada doze minutos após o início do workflow.

O arquivo registra que o repositório ficou comprometido por cerca de 20 horasantes de a publicação ser disparada — a lacuna que a linha do tempo abaixo detalha commit a commit — o que é consistente com a própria declaração da Tensorlake de que o atacante publicou "por meio do nosso próprio fluxo de lançamento".

O que o payload fez quando foi executado

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.'

A avaliação da Socket identifica a coleta em arquivos locais, ambientes de CI, fontes do Kubernetes e do Vault, além de exfiltração, persistência e execução de código fornecido remotamente. A SafeDep reproduziu o payload decodificado: lib/setup.mjs baixa o Bun 1.3.13 da release oficial do GitHub e o usa para executar o worm, e ele encerra a execução em runners de CI — o alvo é uma máquina de desenvolvedor, não um agente de build. A SafeDep também descobriu que o payload carrega uma cópia simples desse mesmo loader, que ele insere em outros pacotes e repositórios.

O payload executa três camadas de ofuscação, que a SafeDep decodificou sem executar a amostra: um array de strings do ofuscador, uma cifra personalizada usando o salt svksjrhjkcejg — idêntico ao relatado no comprometimento anterior do keyv — e AES-256-GCM sobre onze arquivos incorporados, incluindo scripts, hooks e duas chaves públicas RSA. Sua primeira linha carrega a tag de build WORMTAG='tensrlake', escrita incorretamente, que é como a SafeDep distingue esta build de uma reinfecção em andamento.

Além da configuração de ferramentas de IA, a lista de coleta é ampla e específica: ~/.claude.json e ~/.kiro/settings/mcp.json para configurações de agente; chaves SSH, arquivos de CLI de nuvem, .npmrc, .env, arquivos do Docker e do Kubernetes, e histórico do shell; wallet.dat além de dados do Exodus, Electrum e Ledger Live e extensões de carteira de navegador como MetaMask e Phantom; AWS STS, SSM Parameter Store e Secrets Manager; segredos do GitHub Actions lidos da memória do processo Runner.Worker; e tokens de conta de serviço do Kubernetes e tokens do Vault. Ele baixou um binário por plataforma de iseekaigogo[.]com/hbd/<platform> e o executou com os argumentos "dump -b all -c password -f json" — argumentos que correspondem à ferramenta HackBrowserData, embora a SafeDep observe que o próprio binário não foi recuperado e classifique a identificação como uma inferência. O worm, acrescenta a SafeDep, encerra-se em locales russos.

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.'

A persistência é deliberada. A Socket escreveu sobre o payload: "Essa combinação amplia o risco para além de uma única chave de API roubada", acrescentando que "a persistência pode manter o acesso do atacante depois que a dependência afetada for removida". A SafeDep relata que o worm faz commit de arquivos de hook do Claude Code e do VS Code com o autor do git claude, e implanta um workflow "Run Copilot" que extrai todos os segredos do repositório e depois exclui a execução e o branch. O aviso da Tensorlake orienta os desenvolvedores que verificam seus logs a procurar um branch chamado dependabot/github_actions/format/setup-formatter e commits com autoria sob essa mesma identidade.

O Spread baseia-se em tokens roubados, em vez de numa segunda vulnerabilidade. A Socket afirma que o worm enumera os pacotes associados à identidade de publicação de uma vítima, cria proveniência do Sigstore e republica versões envenenadas. A SafeDep acrescenta o detalhe de que, dentro do CI, ele adiciona uma dependência git e assina a sua saída com Fulcio e Rekor — de modo que a proveniência do pacote que publica a seguir é tão válida quanto era a proveniência do 0.5.144.

As vinte horas antes da publicação

O intervalo entre o primeiro commit malicioso e o lançamento é a parte da linha do tempo que explica como um pacote envenenado passou a ter proveniência válida. Todos os horários estão em UTC; os horários dos commits são da SafeDep e da API do GitHub, e os horários de publicação, remoção e aviso são da 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.'

Leia em conjunto: os arquivos de payload chegaram ao branch principal do repositório em 7 de outubro, a versão foi definida como 0.5.144 às 03:57 daquela manhã, e nada foi publicado até que uma conta iniciou manualmente o fluxo de trabalho de release às 00:08 do dia seguinte. O código-fonte comprometido permaneceu no branch por cerca de vinte horas antes de o pipeline do próprio projeto compilá-lo. Isso é todo o ataque ao caminho de release — nenhuma atestação forjada, nenhum tarball republicado. A proveniência estava correta quanto a um build de código que nunca deveria ter estado no branch.

O interruptor de homem morto

A parte deste incidente que não tem precedente nos comprometimentos anteriores do npm é o que acontece depois que uma vítima reage corretamente. Se o token do GitHub roubado pertence a uma conta sem organizações, relata a SafeDep, o worm instala gh-token-monitor: um serviço que consulta api.github.com/user com esse token roubado a cada 60 segundos, durante 24 horas. Quando o GitHub retorna um 40x — como faz no momento em que o token é revogado —, o monitor executa um manipulador fornecido pelo atacante e exclui o diretório home do usuário.

O Socket descreve o mesmo componente como usando um monitor do PowerShell que persiste por meio de uma tarefa agendada ONLOGON, executando um handler fornecido pelo atacante via Invoke-Expression, e observa que o código contém a string literal "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner", vista em ondas anteriores do Shai-Hulud. O SafeDep nomeia o handler como rm -rf ~/. O texto do Socket é explícito ao afirmar que isso dispara independentemente de onde a revogação ocorre; o monitor é local, e a revogação não é. Todas as quatro fontes — Socket, SafeDep, StepSecurity e o próprio aviso da Tensorlake — fornecem a mesma ordem de operações: remova o monitor primeiro, depois revogue.

O que está estabelecido, e o que é apenas inferido

O arquivo não registra nenhum dano confirmado para esta entrada, e as fontes corroboram isso, em vez de simplesmente deixarem de contradizê-lo.

• A Tensorlake afirma que não há uso da versão. Seu aviso diz que a empresa monitora o uso do SDK por meio de cabeçalhos user-agent e "não viu nenhum uso desta versão desde o seu lançamento". Essa é uma declaração do fornecedor sobre sua própria telemetria, não uma contagem auditada.

• O número de downloads não é uma contagem de infecções. Socket relata que o pacote tem aproximadamente 12 mil downloads semanais e observa que isso descreve o uso geral do pacote, e não os downloads da versão maliciosa; SafeDep cita cerca de 106 mil downloads mensais no mesmo pacote. Nenhum dos dois é evidência de que a 0.5.144 tenha sido executada em qualquer lugar. A janela do lançamento sinalizado do Socket e a janela de duas horas da Tensorlake são compatíveis com uma versão que foi removida antes de se espalhar.

• Os próprios bugs do payload podem tê-lo limitado. A SafeDep encontrou dois: o caminho de propagação do npm precisa de ./dist/Math_Symbol.js no disco e para sem ele, e o loader plantado procura por ai_init.js enquanto o worm grava math_init.js. A SafeDep classifica essas descobertas como limitações à propagação, e o artigo as trata como a leitura do código por uma análise, não como garantia de que nada se propagou.

• A atestação de proveniência é real. Isto não é uma alegação contestada: a proveniência do npm registra onde um pacote foi compilado e por qual workflow, e neste caso registrou a verdade — o próprio workflow de release do projeto, compilando código-fonte envenenado. O aviso da Tensorlake afirma isso com todas as letras: "o pacote carrega proveniência npm válida". A Socket apresenta o mesmo ponto de forma clara quando observa que a proveniência "diz onde um pacote foi compilado. Não diz que o código é seguro."

Vários detalhes em circulação são alegações baseadas em uma única análise e devem ser encarados como tal. O mecanismo específico pelo qual o atacante obteve a conta do mantenedor não foi publicado por nenhuma das empresas investigadoras nem pela Tensorlake. O endereço do contrato Ethereum e seu papel na resolução do endpoint aparecem nos relatos da SafeDep e da Socket — a Socket afirma que o payload resolve seu endpoint por meio de um contrato Ethereum usando aproximadamente 30 endpoints RPC públicos, com um fallback no GitHub, enquanto a SafeDep estima a contagem de RPCs em 35 e relata que, em 8 de outubro, o contrato retornou iseekaigogo.com — e a Tensorlake confirma o endpoint e o contrato em seu aviso. A contagem exata de RPCs difere entre os dois relatos; o design, não.

Uma lacuna no registro público merece ser declarada sem rodeios. Nenhuma das fontes revisadas para este artigo relata uma infecção a jusante confirmada — outro pacote ou repositório envenenado pelo worm usando credenciais roubadas deste. O código de propagação existe e a SafeDep o leu; não se sabe se ele produziu uma segunda vítima.

O que mudou depois disso

A resposta foi mais rápida e mais coordenada do que o incidente.

• A versão desapareceu. Esteve ativa das 01:12 às 02:54 UTC em 8 de outubro, segundo a Tensorlake; a SafeDep relata que o npm a removeu. Ao consultar diretamente o registro do npm em 10 de outubro para este artigo, 0.5.144 não aparece mais entre as versões publicadas do pacote, e a tag mais recente do pacote é 0.5.148. O aviso da Tensorlake orienta os desenvolvedores a usar a 0.5.143 como a última versão não afetada.

• O aviso é publicado com uma correção. O comunicado GHSA-8g63-53c9-65j2 da Tensorlake afirma que os pacotes tensorlake do PyPI e do crates.io e a CLI tensorlake não foram afetados — apenas o pacote npm foi — e que as versões 0.5.143 e anteriores não são afetadas. O SafeDep relata que os mantenedores reverteram o código-fonte no pull request #1016 e lançaram 0.5.145.

• O fio de divulgação está invulgarmente completo.O investigador da StepSecurity, Ashish Kurmi, abriu a issue do GitHub #1014 às 01:22:02 UTC de 8 de outubro — cerca de dez minutos após a publicação — apontando para o artigo da própria StepSecurity sobre aquilo a que chama worm do "token refém". Oliver Smith, da Aikido, comentou que o payload foi introduzido no commit 41b38f0 e identificou-o como um novo ladrão de informações Shai-Hulud. O mantenedor David Lorenzo — a identidade de mantenedor indicada no pacote npm como calavera — respondeu a 9 de outubro confirmando o aviso de segurança e encerrando a issue como concluída no mesmo dia. O próprio título da issue acompanha as provas: começou como um relatório de "possivelmente malicioso" e foi renomeado, quando foi encerrada, para descrever o payload como malicioso sem qualquer qualificação.

• A campanha à qual isto pertence é maior do que este pacote. A Socket, a SafeDep e a Aikido situam todas o lançamento da Tensorlake na onda ChainDrop / Mini Shai-Hulud documentada pela primeira vez no início de agosto de 2026, cujas vítimas do npm incluíam keyv, cacheable e pacotes relacionados. O comunicado de segurança da Tensorlake diz o mesmo, citando Socket, SafeDep e Aikido.

A orientação da Socket para quem instalou a versão é que o host deve ser tratado como comprometido: verifique se há referências à versão nos lockfiles, manifestos e registos de build; remova o gh-token-monitorserviço antes de revogar qualquer token; depois, proceda à rotação das credenciais a partir de uma máquina limpa. O aviso da Tensorlake acrescenta a mesma sequência e sugere verificar se há lançamentos inesperados nos registos de pacotes e nos repositórios onde os tokens expostos podiam escrever. O artigo da Aikido aconselha a definir ignore-scripts=true em .npmrc para bloquear hooks de instalação e tratar qualquer máquina onde o hook foi executado como totalmente comprometida.

Este é um registro, relatado por outros e citado aqui a eles. Os outros incidentes documentados envolvendo agentes, cada um com suas próprias fontes, gravidade, grau de confiança e indicador de disputa, ficam no arquivo de incidentes de IA — para que um comprometimento da cadeia de suprimentos voltado às ferramentas de agentes possa ser lido ao lado do resto do que realmente aconteceu.