← back
CVE-2026-45321criticalunder attackransomwareCWE-506

Malware in 42 @tanstack/* packages exfiltrates cloud credentials, GitHub tokens, and SSH keys

78Vexday Risk Score

Prioritize patching. It under exploitation confirmed by CISA and has a public proof of concept.

ssvc Actcvss 9.6epss 2.3%
from disclosure to weapon0 days
Published on NVDMay 12
1st PoCMay 12
CISA KEV+15d
exploitation probability
2.3%top 18% of all CVEs
observed exploitation
yesCISA + VulnCheck
13 public exploit(s)
Action required by CISAfederal deadline: 2026-06-10

Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.

Summary

Não é uma falha de código nos pacotes @tanstack/*, mas um comprometimento pontual da cadeia de publicação: em 11/05/2026, um atacante conseguiu publicar 84 versões maliciosas de 42 pacotes @tanstack/* no npm, autenticadas via o mecanismo legítimo de trusted-publisher OIDC do GitHub Actions do repositório TanStack/router. Quem instalou uma dessas versões específicas — publicadas numa janela de ~6 minutos — executou um payload que rouba credenciais de nuvem, tokens do GitHub e chaves SSH. O impacto é real e severo para quem instalou nessa janela exata, mas irrelevante para qualquer instalação fora dela: não há brecha residual explorável no código do TanStack hoje.

Technical detail

O ataque encadeou três classes de falha conhecidas em pipelines de CI/CD do GitHub Actions. Primeiro, um 'Pwn Request' (CWE-829, execução de código de esfera não confiável): o atacante abriu um PR de um fork renomeado (github.com/zblgg/configuration) contendo um commit malicioso com payload JS bundlado. Workflows configurados com pull_request_target (bundle-size.yml, labeler.yml) rodam automaticamente para PRs de forks, sem exigir aprovação de first-time contributor — diferente do workflow pr.yml, que usa pull_request e ficou bloqueado. Um force-push no PR fez o job de benchmark checkar out o merge do PR e executar pnpm install, disparando o payload do fork.

Segundo, envenenamento do cache do GitHub Actions através da fronteira de confiança fork↔base: a execução do payload durante o job do PR salvou uma entrada de cache pnpm-store com uma chave que coincidia com a que o workflow de release (release.yml) do branch main buscaria depois. O PR foi então revertido para um estado inócuo e fechado, mas o cache envenenado permaneceu no repositório.

Terceiro, extração de memória em runtime do token OIDC do processo do runner: quando um release legítimo do TanStack/router foi disparado (merge de PRs não relacionados), o release.yml restaurou o cache envenenado, executando o malware novamente — agora dentro de um workflow com permissão id-token: write. O malware minerou o token OIDC do processo do runner em memória e usou-o para publicar pacotes diretamente via POST para registry.npmjs.org, contornando o step 'Publish Packages' definido no workflow (que sequer chegou a rodar, pois os testes falharam). Nenhum token de npm foi roubado e o workflow de publish em si não foi alterado — a autenticação usada era genuína.

O payload em si (router_init.js, ~2,3 MB, obfuscado) é entregue via uma dependência opcional inexistente no registro (@tanstack/setup) que resolve para um commit órfão num fork do repositório — o GitHub serve commits de toda a rede de forks para dependências git-URL, então o atacante não precisou de acesso de escrita ao repositório oficial.

How it’s exploited

Não há exploração 'remota' no sentido tradicional de um atacante mirando uma vítima específica: o vetor é a cadeia de suprimentos do npm. Qualquer ambiente — dev local ou CI — que executou npm install, pnpm install ou yarn install contra uma das versões maliciosas exatas publicadas entre 19:20 e 19:26 UTC de 11/05/2026 disparou o lifecycle script 'prepare' da dependência opcional falsa, que baixou e executou o payload automaticamente, sem interação além do próprio comando de instalação (refletido no UI:R do vetor CVSS).

O payload varre e exfiltra: metadados de instância AWS (IMDS) e Secrets Manager, metadata service GCP, tokens de service account Kubernetes, tokens do HashiCorp Vault, ~/.npmrc, tokens do GitHub (variáveis de ambiente, config do gh CLI, .git-credentials) e chaves privadas SSH em ~/.ssh/. A exfiltração ocorre pela rede de upload de arquivos do Session/Oxen messenger (filev2.getsession.org, seed{1,2,3}.getsession.org), ponta a ponta criptografada e sem C2 controlado diretamente pelo atacante — o que elimina bloqueio por IP/domínio como controle eficaz de conteúdo, embora ainda sirva como indicador. Adicionalmente, o malware se autopropaga: enumera outros pacotes que a vítima mantém via a API de busca do npm (maintainer:) e republica-os com a mesma injeção, criando um efeito cascata na cadeia de suprimentos.

A falha está confirmada no catálogo KEV da CISA como exploração ativa (adicionada 2026-05-27, prazo 2026-06-10) e há PoC pública documentando o fingerprint do ataque. O EPSS baixo (0,023) reflete que, encerrado o incidente e removidas as versões do registro, o risco prospectivo de exploração é mínimo — o dano relevante já ocorreu na janela específica.

Versions

Affected
84 versões maliciosas (duas por pacote) publicadas entre 19:20 e 19:26 UTC de 2026-05-11 em 42 pacotes @tanstack/* do monorepo Router/Start. Exemplos: @tanstack/react-router 1.169.5 e 1.169.8; @tanstack/history 1.161.9 e 1.161.12; @tanstack/eslint-plugin-router 1.161.9 e 1.161.12; @tanstack/eslint-plugin-start 0.0.4 e 0.0.7; @tanstack/nitro-v2-vite-plugin 1.154.12 e 1.154.15; @tanstack/react-router-devtools 1.166.16 e 1.166.19; @tanstack/arktype-adapter, @tanstack/valibot-adapter e @tanstack/zod-adapter 1.166.12 e 1.166.15 (lista completa das 42 famílias na advisory GHSA-g7cv-rxg3-hmpx). Pacotes de outros repositórios TanStack (Query, Table, Form, Virtual, Store, Pacer, DB, AI, HotKeys, Config, Devtools, CLI, Intent) não foram afetados.
Fixed in
Cada pacote afetado recebeu uma versão corrigida imediatamente subsequente às duas maliciosas: @tanstack/react-router 1.169.9; @tanstack/history 1.161.13; @tanstack/eslint-plugin-router 1.161.13; @tanstack/eslint-plugin-start 0.0.8; @tanstack/nitro-v2-vite-plugin 1.154.16; @tanstack/react-router-devtools 1.166.20; @tanstack/arktype-adapter, @tanstack/valibot-adapter e @tanstack/zod-adapter 1.166.16 (ver advisório GHSA-g7cv-rxg3-hmpx para as 42 correções). O fornecedor declarou 'all clear' em 2026-05-15: todas as versões atualmente publicadas de todos os pacotes TanStack, incluindo Router e Start, são seguras.

How to protect

Atualizar imediatamente qualquer um dos 42 pacotes @tanstack/* afetados para a versão corrigida (patch) publicada na sequência de cada par malicioso — por exemplo @tanstack/react-router 1.169.5/1.169.8 (maliciosas) → 1.169.9 (corrigida); @tanstack/history 1.161.9/1.161.12 → 1.161.13; @tanstack/eslint-plugin-router 1.161.9/1.161.12 → 1.161.13; @tanstack/eslint-plugin-start 0.0.4/0.0.7 → 0.0.8; @tanstack/nitro-v2-vite-plugin 1.154.12/1.154.15 → 1.154.16; @tanstack/react-router-devtools 1.166.16/1.166.19 → 1.166.20; @tanstack/arktype-adapter e @tanstack/valibot-adapter e @tanstack/zod-adapter 1.166.12/1.166.15 → 1.166.16 (ver advisório GHSA-g7cv-rxg3-hmpx para a tabela completa das 42 famílias). Pacotes fora dessa lista — Query, Table, Form, Virtual, Store, o meta-pacote @tanstack/start — não foram afetados segundo o fornecedor.

Se o ambiente instalou uma versão maliciosa na janela de 2026-05-11 19:20–19:26 UTC, atualizar o pacote não é suficiente: o host de instalação deve ser tratado como comprometido. É necessário rotacionar toda credencial acessível ao processo de instalação — credenciais AWS e GCP, tokens de service account Kubernetes, tokens Vault, tokens npm (~/.npmrc), tokens e credenciais GitHub (env vars, gh CLI, .git-credentials) e chaves SSH privadas — e revisar logs de auditoria de nuvem por atividade originada dos hosts afetados durante e após a janela de instalação. Bloquear filev2.getsession.org e seed{1,2,3}.getsession.org é o único controle de rede aplicável, mas não substitui a rotação de credenciais: a exfiltração é ponta a ponta criptografada e pode já ter concluído antes de qualquer bloqueio surtir efeito.

O que não funciona como mitigação isolada: apenas fixar (pin) uma versão anterior à data do incidente sem verificar se ela é uma das duas versões maliciosas publicadas; confiar em lockfiles gerados durante a janela do ataque sem regenerá-los contra versões corrigidas; e assumir que, por a autenticação de publish ter sido legítima (OIDC trusted-publisher), o conteúdo publicado também é confiável — o mecanismo de confiança foi abusado, não falsificado.

How to detect

O fingerprint mais confiável é o manifesto (package.json) da versão instalada: as versões maliciosas contêm a entrada exata optionalDependencies: {"@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"} — um pacote que não existe no registro npm. Para inspecionar sem rodar scripts de lifecycle, baixe o tarball com npm pack @tanstack/@ (não executa install scripts), extraia e verifique o package.json e a presença de router_init.js (~2,3 MB) na raiz do pacote — arquivo deliberadamente omitido do array "files", então não aparece no conteúdo documentado do pacote.

Em tráfego de rede, indicadores de exfiltração são conexões para filev2.getsession.org e os hosts seed1/seed2/seed3.getsession.org (rede de upload do Session/Oxen messenger) originadas de hosts de build/CI ou estações de desenvolvimento — mas como o canal é E2E criptografado sem C2 fixo do atacante, a ausência desse tráfego não garante ausência de comprometimento caso outro canal tenha sido usado. Em logs de nuvem, procure atividade anômala (chamadas de API, criação de chaves de acesso) originada de hosts que rodaram instalação de pacotes @tanstack/* durante ou pouco depois da janela 2026-05-11 19:20–19:26 UTC.

Researched and written with AI from the vendor advisory and public analysis, with the sources above. Always confirm the fixed version in the official advisory before acting.
On 2026-05-11, between approximately 19:20 and 19:26 UTC, 84 malicious versions across 42 @tanstack/* packages were published to the npm registry. The publishes were authenticated via the legitimate GitHub Actions OIDC trusted-publisher binding for TanStack/router, but the publish workflow itself was not modified. The attacker chained three known vulnerability classes — a pull_request_target "Pwn Request" misconfiguration, GitHub Actions cache poisoning across the fork↔base trust boundary, and runtime memory extraction of the OIDC token from the Actions runner process — to publish credential-stealing malware under a trusted identity. Each affected package received exactly two malicious versions, published a few minutes apart.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
⚠ Public resources, to assess the exposure of systems you control or are authorized to test. Test only with authorization.