Aikido

Mini Shai-Hulud Está de Volta: Worm de npm Atinge mais de 160 Pacotes, incluindo Mistral e Tanstack

Escrito por
Raphael Silva

Mini Shai-Hulud está de volta. Como eu disse antes, ainda não tínhamos visto a escala total do ataque.

A campanha npm que cobrimos em abril, quando visava pacotes SAP, agora se transformou em um comprometimento muito maior. Nossa equipe de Malware detectou 373 entradas maliciosas de versão de pacote em 169 nomes de pacotes npm.

O objetivo básico ainda é o mesmo: roubar credenciais de máquinas de desenvolvedores e runners de CI/CD, e então usar essas credenciais para alcançar mais pacotes.

O que mudou é a escala e o caminho de lançamento. Esta onda não parece apenas alguém publicando versões ruins manualmente. O malware é construído para rodar dentro de sistemas de build, roubar acesso npm e GitHub, e abusar de caminhos de publicação confiáveis para empurrar novos pacotes comprometidos.

Se você leu nossa publicação anterior, Mini Shai-Hulud Targets SAP npm Packages With a Bun-Based Secret Stealer, este é o acompanhamento: a mesma ideia, mas com um raio de explosão muito maior.

O que aconteceu

TanStack ainda é um dos clusters mais visíveis, mas não é mais a história completa. O conjunto afetado agora inclui pacotes em @squawk, @tanstack, @uipath, @tallyui, @beproduct, @mistralai, @draftlab, @draftauth, @taskflow-corp, @tolka, e vários pacotes sem escopo.

Os maiores clusters nesta campanha são:

  • @squawk: 87 entradas de versão de pacote
  • @tanstack: 83 entradas de versão de pacote
  • @uipath: 66 entradas de versão de pacote
  • pacotes sem escopo: 39 entradas de versão de pacote
  • @tallyui: 30 entradas de versão de pacote
  • @beproduct: 18 entradas de versão de pacote

Esta lista ainda está em atualização. Você pode ver a lista completa de pacotes afetados no final do blog. O importante não é apenas o número de pacotes, mas onde eles são executados. É provável que esses pacotes sejam instalados em ambientes de desenvolvedor locais, jobs de CI, fluxos de trabalho de release e sistemas de build internos.

Como a nova onda funciona

Na onda do SAP, os pacotes comprometidos adicionaram um preinstall hook que executava setup.mjs, que então usou Bun para executar um grande payload ofuscado chamado execution.js.

Esta onda usa um caminho ligeiramente diferente.

Em pacotes TanStack comprometidos, o tarball do pacote inclui um novo arquivo ofuscado na raiz do pacote:

router_init.js

O pacote comprometido também adiciona uma dependência opcional que aponta para um pacote hospedado no GitHub

"optionalDependencies": {
  "@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"
}

Essa dependência Git contém um prepare script:

"scripts": {
  "prepare": "bun run tanstack_runner.js && exit 1"
}

Este é o truque. O npm executa scripts de ciclo de vida para dependências Git durante a instalação. Assim, um pacote que parece uma dependência normal pode silenciosamente acessar uma dependência hospedada no GitHub, executar seu prepare hook, e executar o payload.

O && exit 1 no final também é interessante. Como a dependência é opcional, falhar após a execução do payload pode fazer com que a instalação pareça menos suspeita. O código malicioso já foi executado quando o npm trata a dependência opcional como falha.

Por que o Trusted Publishing é Importante Aqui

Uma das partes mais incômodas desta onda é o uso do trusted publishing.

O trusted publishing visa remover tokens npm de longa duração dos fluxos de trabalho de release. Um fluxo de trabalho do GitHub Actions pode usar OIDC para solicitar um token de publicação npm de curta duração, publicar o pacote e anexar a proveniência ao release.

Isso é bom quando o fluxo de trabalho está limpo.

É muito pior quando um código controlado por um atacante é executado dentro do fluxo de trabalho. Nesse ponto, o atacante pode nem precisar roubar um token npm de longa duração. Ele pode usar as próprias permissões OIDC do fluxo de trabalho para gerar um token de publicação durante o build e publicar a partir daí.

Isso também significa que a proveniência não é um sinal de segurança completo. Um pacote malicioso ainda pode vir do fluxo de trabalho esperado do GitHub Actions se esse fluxo de trabalho foi abusado durante o lançamento.

Em termos simples: a proveniência pode dizer onde o pacote foi construído. Não prova que a construção foi segura.

O que o payload tenta roubar

O payload é construído para ambientes CI/CD e de desenvolvedor.

Ele procura por:

  • tokens do GitHub
  • tokens npm
  • tokens OIDC do GitHub Actions
  • credenciais AWS e metadados de instância
  • arquivos de conta de serviço Kubernetes
  • tokens do HashiCorp Vault e endpoints locais do Vault
  • variáveis de ambiente
  • Secrets do sistema de arquivos local

O payload também contém lógica de propagação. Após roubar tokens, ele tenta usá-los para encontrar pacotes que a vítima pode publicar, modificar arquivos de pacote, injetar a dependência maliciosa, atualizar versões e publicar novos lançamentos comprometidos.

É isso que torna isso mais do que um infostealer normal. O malware não está apenas tentando roubar da vítima atual. Ele está tentando transformar o acesso de lançamento da vítima no próximo caminho de infecção.

O que mudou em relação ao ataque SAP

A onda SAP foi menor em número de pacotes, mas ainda de alto impacto porque afetou ferramentas de build corporativas.

Esta onda é mais ampla. Os pacotes TanStack são amplamente utilizados em aplicações JavaScript modernas, especialmente em ferramentas de roteamento e React full-stack. Um pacote comprometido nessa parte da árvore de dependências pode chegar a muitos lugares rapidamente.

Há também algumas mudanças técnicas:

  • os pacotes SAP usados setup.mjs e execution.js
  • a nova onda TanStack usa router_init.js e um hospedado no GitHub @tanstack/setup dependência
  • a nova onda se apoia mais em GitHub Actions, OIDC, publicação npm e reempacotamento de pacotes
  • o payload ainda é baseado em Bun e ainda focado em roubar Secrets

O padrão, contudo, é o mesmo: obter execução de código durante a instalação, roubar credenciais e usá-las para publicar mais malware.

Detecção e mitigação

Comece pelos lockfiles e caches de pacotes.

Pesquise por namespaces e pacotes afetados:

  • @squawk/
  • @tanstack/
  • @uipath/
  • @tallyui/
  • @beproduct/nestjs-auth
  • @mistralai/
  • @draftauth/
  • @draftlab/
  • @taskflow-corp/cli
  • @tolka/cli
  • @ml-toolkit-ts/
  • @mesadev/
  • @dirigible-ai/sdk
  • @supersurkhet/
  • pacotes sem escopo listados acima, incluindo safe-action, ts-dna, cross-stitch, cmux-agent-mcp, agentwork-cli, git-branch-selector, wot-api, git-git-git, nextmove-mcp, e ml-toolkit-ts

Procure pelos novos arquivos de payload e marcadores de dependência:

  • router_init.js
  • router_runtime.js
  • tanstack_runner.js
  • @tanstack/setup
  • github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c
  • bun run tanstack_runner.js

Procure nos logs de CI por:

  • execução inesperada do Bun durante npm install
  • falhas de dependência opcionais envolvendo @tanstack/setup
  • conexões de saída durante a instalação de dependências
  • atividade de publicação npm de fluxos de trabalho que não deveriam ter publicado
  • solicitações de token OIDC do GitHub Actions durante etapas inesperadas

Se uma versão de pacote comprometida foi executada em uma máquina de desenvolvedor ou runner de CI, rotacione os Secrets desse ambiente. Não pare nos tokens npm.

Rotacione ou revise:

  • tokens npm e acesso de publicação de pacotes
  • PATs do GitHub e Secrets do GitHub Actions
  • credenciais de Cloud
  • Tokens de conta de serviço Kubernetes
  • tokens do Vault
  • Secrets de implantação

Audite também as publicações npm recentes, as execuções do GitHub Actions e os registros de proveniência. Um registro de proveniência válido não deve ser tratado como prova de que o pacote está limpo.

Indicadores de comprometimento

Arquivos e payloads:

  • router_init.js
  • router_runtime.js
  • tanstack_runner.js
  • router_init.js SHA-256: ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c
  • tanstack_runner.js SHA-256: 2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96

Marcadores de pacote:

  • @tanstack/setup
  • github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c
  • prepare execução de script bun run tanstack_runner.js
  • arquivo de payload de nível raiz incluído fora do conteúdo normal do pacote

Indicadores de rede e serviço:

  • hxxp://filev2[.]getsession[.]org/file/
  • hxxp://169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/
  • hxxp://169[.]254[.]170[.]2
  • hxxps://registry[.]npmjs[.]org/-/npm/v1/tokens
  • vault[.]svc[.]cluster[.]local:8200

Marcadores de campanha:

  • Um Mini Shai-Hulud Apareceu
  • nomes de repositório com tema Dune usados para saída e staging do worm

Conclusão

Mini Shai-Hulud passou de um incidente menor focado em SAP para um ataque mais amplo à cadeia de suprimentos npm.

A lição importante não é apenas que mais pacotes foram comprometidos. É que o malware é construído em torno da forma como os sistemas de lançamento modernos funcionam. Ele é executado durante a instalação, procura credenciais de CI/CD, abusa de caminhos de publicação do GitHub e npm e tenta se inserir no próximo pacote.

Se algum dos pacotes afetados foi executado em seu ambiente, trate a máquina ou o runner como exposto até que os Secrets sejam rotacionados e a atividade de publicação recente tenha sido revisada.

Como a Aikido detecta isso

Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. Isso aparecerá como um problema crítico 100/100. O Aikido reanalisa todas as noites, mas recomendamos acionar uma reanálise manual agora.

Se você ainda não é um usuário Aikido, pode criar uma conta e conectar seus repositórios. Nossa cobertura de malware está incluída no plano gratuito, não é necessário cartão de crédito.

Para uma cobertura mais ampla em toda a sua equipe, o Endpoint Protection do Aikido oferece visibilidade e controle sobre os pacotes de software instalados nos dispositivos da sua equipe. Ele abrange extensões de navegador, bibliotecas de código, plugins de IDE e dependências de build, tudo em um só lugar. Impeça o malware antes que ele seja instalado.

Para proteção futura, considere Aikido Safe Chain (open source). O Safe Chain se integra ao seu fluxo de trabalho existente, interceptando comandos npm, npx, yarn, pnpm e pnpx e verificando pacotes contra Aikido Intel antes da instalação.

Apêndice: Pacotes e Versões Afetados

Lista atual de pacotes e versões que nossa equipe identificou:

  • @tanstack/history: 1.161.9, 1.161.12
  • @tanstack/react-router: 1.169.5, 1.169.8
  • @tanstack/router-core: 1.169.5, 1.169.8
  • @tanstack/router-utils: 1.161.11, 1.161.14
  • @tanstack/router-plugin: 1.167.38, 1.167.41
  • @tanstack/virtual-file-routes: 1.161.10, 1.161.13
  • @tanstack/router-generator: 1.166.45, 1.166.48
  • @tanstack/start-server-core: 1.167.33, 1.167.36
  • @tanstack/start-client-core: 1.168.5, 1.168.8
  • @tanstack/start-storage-context: 1.166.38, 1.166.41
  • @tanstack/start-plugin-core: 1.169.23, 1.169.26
  • @tanstack/react-start-server: 1.166.55, 1.166.58
  • @tanstack/react-start-client: 1.166.51, 1.166.54
  • @tanstack/start-fn-stubs: 1.161.9, 1.161.12
  • @tanstack/react-start: 1.167.68, 1.167.71
  • @tanstack/react-start-rsc: 0.0.47, 0.0.50
  • @mistralai/mistralai: 2.2.2, 2.2.3, 2.2.4
  • @tanstack/react-router-devtools: 1.166.16, 1.166.19
  • @tanstack/router-devtools-core: 1.167.6, 1.167.9
  • @tanstack/router-devtools: 1.166.16, 1.166.19
  • @tanstack/router-ssr-query-core: 1.168.3, 1.168.6
  • @tanstack/react-router-ssr-query: 1.166.15, 1.166.18
  • @tanstack/router-cli: 1.166.46, 1.166.49
  • @tanstack/zod-adapter: 1.166.12, 1.166.15
  • @tanstack/eslint-plugin-router: 1.161.9
  • @tanstack/router-vite-plugin: 1.166.53, 1.166.56
  • @tanstack/nitro-v2-vite-plugin: 1.154.12, 1.154.15
  • @mistralai/mistralai-gcp: 1.7.1, 1.7.2, 1.7.3
  • @tanstack/solid-router: 1.169.5, 1.169.8
  • @tanstack/solid-start: 1.167.65, 1.167.68
  • @tanstack/solid-start-client: 1.166.50, 1.166.53
  • @tanstack/solid-start-server: 1.166.54, 1.166.57
  • @tanstack/solid-router-devtools: 1.166.16, 1.166.19
  • @tanstack/start-static-server-functions: 1.166.44, 1.166.47
  • @tanstack/vue-router: 1.169.5, 1.169.8
  • @uipath/apollo-react: 4.24.5
  • @tanstack/solid-router-ssr-query: 1.166.15, 1.166.18
  • safe-action: 0.8.3, 0.8.4
  • @tanstack/valibot-adapter: 1.166.12, 1.166.15
  • @tanstack/vue-start: 1.167.61, 1.167.64
  • @uipath/apollo-wind: 2.16.2
  • @uipath/cli: 1.0.1
  • @tanstack/vue-start-server: 1.166.50, 1.166.53
  • @squawk/types: 0.8.2, 0.8.3, 0.8.4
  • @uipath/rpa-tool: 0.9.5
  • @squawk/mcp: 0.9.1, 0.9.2, 0.9.3, 0.9.4
  • @tanstack/vue-start-client: 1.166.46, 1.166.49
  • @squawk/weather: 0.5.6, 0.5.7, 0.5.8, 0.5.9
  • @squawk/airspace: 0.8.1, 0.8.2, 0.8.3, 0.8.4
  • @squawk/icao-registry-data: 0.8.4, 0.8.5, 0.8.6, 0.8.7
  • @tanstack/arktype-adapter: 1.166.12, 1.166.15
  • @squawk/flightplan: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @squawk/airports: 0.6.2, 0.6.3, 0.6.4, 0.6.5
  • @mesadev/sdk: 0.28.3
  • @squawk/geo: 0.4.4, 0.4.5, 0.4.6, 0.4.7
  • @mesadev/rest: 0.28.3
  • @squawk/procedure-data: 0.7.3, 0.7.4, 0.7.5, 0.7.6
  • @squawk/navaid-data: 0.6.4, 0.6.5, 0.6.6, 0.6.7
  • @squawk/fix-data: 0.6.4, 0.6.5, 0.6.6, 0.6.7
  • @squawk/navaids: 0.4.2, 0.4.3, 0.4.4, 0.4.5
  • @squawk/fixes: 0.3.2, 0.3.3, 0.3.4, 0.3.5
  • @squawk/airport-data: 0.7.4, 0.7.5, 0.7.6, 0.7.7
  • @squawk/airway-data: 0.5.4, 0.5.5, 0.5.6, 0.5.7
  • @squawk/units: 0.4.3, 0.4.4, 0.4.5, 0.4.6
  • @squawk/procedures: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @squawk/airways: 0.4.2, 0.4.3, 0.4.4, 0.4.5
  • @squawk/icao-registry: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @uipath/apollo-core: 5.9.2
  • @squawk/notams: 0.3.6, 0.3.7, 0.3.8, 0.3.9
  • @uipath/filesystem: 1.0.1
  • @uipath/solutionpackager-tool-core: 0.0.34
  • @squawk/flight-math: 0.5.4, 0.5.5, 0.5.6, 0.5.7
  • @squawk/airspace-data: 0.5.3, 0.5.4, 0.5.5, 0.5.6
  • @mistralai/mistralai-azure: 1.7.1, 1.7.2, 1.7.3
  • @uipath/solution-tool: 1.0.1
  • @tanstack/eslint-plugin-start: 0.0.4, 0.0.7
  • @uipath/maestro-tool: 1.0.1
  • @uipath/codedapp-tool: 1.0.1
  • @uipath/agent-tool: 1.0.1
  • @draftlab/auth: 0.24.1, 0.24.2
  • @uipath/orchestrator-tool: 1.0.1
  • @uipath/integrationservice-tool: 1.0.2
  • @taskflow-corp/cli: 0.1.24, 0.1.25, 0.1.26, 0.1.27, 0.1.28, 0.1.29
  • @tanstack/vue-router-ssr-query: 1.166.15, 1.166.18
  • @uipath/rpa-legacy-tool: 1.0.1
  • @uipath/vertical-solutions-tool: 1.0.1
  • @uipath/flow-tool: 1.0.2
  • @uipath/codedagent-tool: 1.0.1
  • @uipath/common: 1.0.1
  • @uipath/resource-tool: 1.0.1
  • @uipath/auth: 1.0.1
  • @uipath/docsai-tool: 1.0.1
  • @uipath/case-tool: 1.0.1
  • @uipath/api-workflow-tool: 1.0.1
  • @tanstack/vue-router-devtools: 1.166.16, 1.166.19
  • @uipath/test-manager-tool: 1.0.2
  • @uipath/robot: 1.3.4
  • @uipath/traces-tool: 1.0.1
  • @uipath/agent-sdk: 1.0.2
  • @uipath/integrationservice-sdk: 1.0.2
  • @uipath/maestro-sdk: 1.0.1
  • @uipath/data-fabric-tool: 1.0.2
  • @mesadev/saguaro: 0.4.22
  • @uipath/tasks-tool: 1.0.1
  • @uipath/insights-tool: 1.0.1
  • @uipath/insights-sdk: 1.0.1
  • @uipath/uipath-python-bridge: 1.0.1
  • @draftlab/db: 0.16.1
  • @uipath/ap-chat: 1.5.7
  • @uipath/project-packager: 1.1.16
  • @uipath/packager-tool-case: 0.0.9
  • @uipath/packager-tool-workflowcompiler-browser: 0.0.34
  • @uipath/packager-tool-connector: 0.0.19
  • @uipath/packager-tool-workflowcompiler: 0.0.16
  • @uipath/packager-tool-webapp: 1.0.6
  • @uipath/packager-tool-apiworkflow: 0.0.19
  • @uipath/packager-tool-functions: 0.1.1
  • ts-dna: 3.0.1, 3.0.2, 3.0.3, 3.0.4
  • @uipath/widget.sdk: 1.2.3
  • @uipath/resources-tool: 0.1.11
  • @uipath/agent.sdk: 0.0.18
  • cross-stitch: 1.1.3, 1.1.4, 1.1.5, 1.1.6
  • @uipath/codedagents-tool: 0.1.12
  • @uipath/aops-policy-tool: 0.3.1
  • @uipath/solution-packager: 0.0.35
  • @draftlab/auth-router: 0.5.1, 0.5.2
  • cmux-agent-mcp: 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8
  • agentwork-cli: 0.1.4, 0.1.5
  • @uipath/packager-tool-bpmn: 0.0.9
  • @draftauth/core: 0.13.1, 0.13.2
  • @dirigible-ai/sdk: 0.6.2, 0.6.3
  • @uipath/packager-tool-flow: 0.0.19
  • git-branch-selector: 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7
  • wot-api: 0.8.1, 0.8.2, 0.8.3, 0.8.4
  • git-git-git: 1.0.8, 1.0.9, 1.0.10, 1.0.11, 1.0.12
  • @beproduct/nestjs-auth: 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8, 0.1.9, 0.1.10, 0.1.11, 0.1.12, 0.1.13, 0.1.14, 0.1.15, 0.1.16, 0.1.17, 0.1.18, 0.1.19
  • @ml-toolkit-ts/xgboost: 1.0.3, 1.0.4
  • nextmove-mcp: 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7
  • ml-toolkit-ts: 1.0.4, 1.0.5
  • @uipath/telemetry: 0.0.7
  • @draftauth/client: 0.2.1, 0.2.2
  • @ml-toolkit-ts/preprocessing: 1.0.2, 1.0.3
  • @tallyui/connector-medusa: 1.0.1, 1.0.2, 1.0.3
  • @uipath/tool-workflowcompiler: 0.0.12
  • @uipath/vss: 0.1.6
  • @tallyui/theme: 0.2.1, 0.2.2, 0.2.3
  • @tallyui/storage-sqlite: 0.2.1, 0.2.2, 0.2.3
  • @uipath/solutionpackager-sdk: 1.0.11
  • @tallyui/connector-vendure: 1.0.1, 1.0.2, 1.0.3
  • @tallyui/core: 0.2.1, 0.2.2, 0.2.3
  • @tallyui/connector-woocommerce: 1.0.1, 1.0.2, 1.0.3
  • @tallyui/components: 1.0.1, 1.0.2, 1.0.3
  • @uipath/ui-widgets-multi-file-upload: 1.0.1
  • @tallyui/pos: 0.1.1, 0.1.2, 0.1.3
  • @tallyui/database: 1.0.1, 1.0.2, 1.0.3
  • @supersurkhet/cli: 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
  • @tallyui/connector-shopify: 1.0.1, 1.0.2, 1.0.3
  • @tolka/cli: 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6
  • @supersurkhet/sdk: 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
  • @uipath/access-policy-tool: 0.3.1
  • @uipath/context-grounding-tool: 0.1.1
  • @uipath/gov-tool: 0.3.1
  • @uipath/admin-tool: 0.1.1
  • @uipath/identity-tool: 0.1.1
  • @uipath/llmgw-tool: 1.0.1
  • @uipath/resourcecatalog-tool: 0.1.1
  • @uipath/functions-tool: 1.0.1
  • @uipath/access-policy-sdk: 0.3.1
  • @uipath/platform-tool: 1.0.1

Compartilhar:

https://www.aikido.dev/blog/mini-shai-hulud-is-back-tanstack-compromised

4.7/5
Cansado de falsos positivos?

Experimente Aikido como 100 mil outros.
Começar Agora
Obtenha um tour personalizado

Confiado por mais de 100 mil equipes

Agende Agora
Escaneie seu aplicativo em busca de IDORs e caminhos de ataque reais

Confiado por mais de 100 mil equipes

Iniciar Escaneamento
Veja como o pentest de IA testa seu aplicativo

Confiado por mais de 100 mil equipes

Iniciar Testes

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.