Alguém registrou o tanstack nome no npm, criou um SDK de player de vídeo que chamaram de "TanStack Player" e hoje publicou quatro versões rápidas projetadas para exfiltrar seus arquivos de ambiente no momento em que você executa npm install.
O verdadeiro TanStack, a casa do TanStack Query, TanStack Table, TanStack Router, todos esses @tanstack/* pacotes com milhões de downloads semanais, não tem nada a ver com isso. O atacante simplesmente pegou o nome não-escopado, o disfarçou de forma convincente e esperou.
Hoje, às 17:08 UTC, eles implantaram o payload.
O que aconteceu
Entre 17:08 e 17:35 UTC de 29 de abril de 2026, quatro novas versões do tanstack pacote npm foram publicadas: 2.0.4, 2.0.5, 2.0.6 e 2.0.7. Todas as quatro contêm um postinstall hook que é acionado automaticamente quando o pacote é instalado.
Antes de hoje, tanstack@2.0.3 (publicado em março) não tinha nenhum postinstall hook. Era um pacote limpo, sem chamadas de rede. Mas isso mudou hoje.
O postinstall.cjs script lê arquivos de ambiente do diretório de trabalho do desenvolvedor e envia seus conteúdos para um endpoint de webhook Svix controlado pelo atacante. Sem prompts. Sem saída visível na maioria das versões. Ele simplesmente é acionado e sai.
O pacote teve cerca de 19.830 downloads no último mês antes do início desta campanha.
O payload
O script é direto. Na instalação, ele lê arquivos locais e os envia via POST como JSON para este endpoint:
https://api.svix.com/ingest/api/v1/source/src_3387PLMB2uhXOBe3Q8sHu/in/3j2jokvbaF4WWdngv8zBbk
Svix é uma empresa legítima de webhooks-as-a-service. O atacante está usando seu produto "Ingest" como um relé de exfiltração, roteando dados roubados através de um terceiro confiável para evitar bloqueios em nível de rede.
O payload inclui conteúdo de arquivos e metadados do sistema:
{
"package": "tanstack",
"version": "2.0.x",
"event": "postinstall",
"readme": "<contents of .env>",
"agents": "<contents of .env.local>",
"timestamp": "...",
"node": "v22.x.x",
"platform": "linux",
"arch": "x64"
}Os nomes dos campos (readme, agents) são uma distração. 🪄 O que está sendo enviado na verdade é o seu .env e .env.local.
Quatro versões, 27 minutos, um atacante testando ao vivo
O histórico de versões é a parte mais interessante deste incidente. O atacante publicou quatro releases em menos de meia hora, iterando visivelmente em seu payload entre cada push.
2.0.4 (17:08): Visa .env e .env.local. A verificação de opt-out (TANSTACK_TELEMETRY_OPT_OUT) está comentada, o que significa que não há uma saída de Escape. Inclui um arquivo duplicado postinstall.js que não aparece em nenhuma outra versão. Importa o módulo http mas nunca o utiliza.
2.0.5 (17:11, três minutos depois): Altera os arquivos alvo para README.md e AGENTS.md. Também reabilita o mecanismo de opt-out. Isso parece um breve desvio — seja para testar se o webhook estava recebendo dados, ou uma tentativa de fazer o hook parecer mais inócuo antes de retornar. README.md não é um arquivo de credenciais.
2.0.6 (17:26): A versão perigosa. Abandona completamente os caminhos dos arquivos alvo e os substitui por uma varredura de diretório:
function collectEnvFiles() {
const allFiles = fs.readdirSync(rootDir);
const matches = allFiles.filter(
(f) => f === ".env" || f.startsWith(".env.")
);
for (const file of matches) {
envFiles[file] = fs.readFileSync(path.join(rootDir, file), "utf-8");
}
return envFiles;
}Isso captura tudo: .env, .env.local, .env.production, .env.staging, .env.development. Tudo isso é enviado em um único POST. A saída do console é completamente suprimida. O opt-out é comentado novamente.
2.0.7 (17:35): Reverte para .env + .env.local direcionamento, mantém a saída do console comentada. Adiciona uma curiosa dependência autorreferencial "tanstack": "^2.0.6" em seu próprio package.json. Se isso é um erro ou serve a algum propósito, não está claro.
O que você está observando neste histórico de versão é uma depuração ao vivo. O invasor ajustou seu direcionamento, testou seu receptor e otimizou para discrição, tudo isso enquanto o pacote estava publicamente disponível e instalável.
A perspectiva da ocupação de nome
O @tanstack organização publica algumas das bibliotecas JavaScript mais amplamente utilizadas no npm: Somente o TanStack Query recebe cerca de 8 milhões de downloads por semana. O tanstack nome não-escopado tem permanecido separadamente desde dezembro de 2024.
Um desenvolvedor executando npm install tanstack em vez de npm install @tanstack/query não obtém o que esperam. Eles obtêm isso.
O README do pacote é bem elaborado. Ele possui um selo de patrocínio, badges de download do npm, uma tabela de comparação de recursos, exemplos de código. Ele se apresenta como um produto real. A história de fachada é boa o suficiente para que um olhar casual não a sinalizasse.
O que é roubado
Em um projeto JavaScript típico, .env arquivos contêm:
- chaves de acesso AWS e Secrets
- Tokens de acesso pessoal do GitHub
- Tokens de publicação npm
- Strings de conexão de banco de dados
- Chaves de API Stripe, Twilio, Resend, SendGrid
- Chaves de API OpenAI, Anthropic e de outros LLMs
- Secrets de cliente OAuth
- Quaisquer outras credenciais de terceiros configuradas localmente
Se você tiver um .env.production arquivo em qualquer lugar próximo ao seu diretório de trabalho (a versão 2.0.6 o teria encontrado), isso significa credenciais de produção entregues a um invasor na instalação.
Remediação e detecção
Passo 1: Verifique se você foi afetado
Verifique seus arquivos de lock e histórico de instalação para qualquer uma destas versões de pacote:
# Verificar package-lock.json
grep -r "tanstack" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
# Verificar node_modules
ls node_modules/tanstack/package.json 2>/dev/null && cat node_modules/tanstack/package.json | grep '"version"'Versões afetadas: 2.0.4, 2.0.5, 2.0.6, 2.0.7. Se alguma destas aparecer em um arquivo de lock, considere seus arquivos de ambiente comprometidos.
Passo 2: Se você foi afetado
Assuma que qualquer .env arquivo presente no diretório de trabalho no momento da instalação foi exfiltrado. Rotacione imediatamente:
- Chaves de acesso e Secrets da AWS (verifique o CloudTrail para chamadas de API não autorizadas)
- Tokens do GitHub com escopo de repositório ou organização
- Tokens npm — revogue em npmjs.com/settings e reemita
- Quaisquer credenciais de banco de dados presentes em
.env - Todas as chaves de API de terceiros nos arquivos afetados
Para ambientes CI: o postinstall é executado durante npm ci também. Se o seu pipeline CI instalou este pacote, rotacione todos os Secrets injetados no ambiente desse pipeline. Verifique os logs de trabalho do seu provedor CI para a etapa de instalação por volta do momento do comprometimento.
Para máquinas de desenvolvedores: trata-se de exfiltração de dados persistente, não de um ataque em memória. Os arquivos foram lidos e enviados. Não há binários descartados ou mecanismos de persistência para limpar, mas suas credenciais já foram comprometidas.
Procure por tráfego HTTPS de saída para api.svix.com em seus logs de rede por volta do momento da instalação. O POST teria vindo do runner CI ou da máquina do desenvolvedor executando a instalação.
Passo 3: Detecte com Aikido
Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. A vulnerabilidade será apresentada como um problema crítico 100/100 no feed. Dica: Aikido reanalisa seus repositórios todas as noites, embora recomendemos acionar uma reanálise completa também.
Se você ainda não é um usuário Aikido, crie uma conta e conecte seus repositórios. Nossa cobertura proprietária de malware está incluída no plano gratuito (não é necessário cartão de crédito).
Passo 4: Proteção futura (SafeChain)
Para proteção futura, considere usar o Aikido SafeChain (código aberto), um wrapper seguro para npm, npx, yarn, pnpm e pnpx. O SafeChain se integra aos seus fluxos de trabalho atuais, interceptando comandos de instalação de pacotes e verificando pacotes em busca de malware contra o Aikido Intel antes da instalação. Pare as ameaças antes que atinjam sua máquina.
IOCs
tanstack@2.0.4— SHA256:72ec4571e27c06f1d48737477c2b38a4f90d699950dab8946b48591133dc4f90tanstack@2.0.5— SHA256:04ee5325c8900c9d644ed81c9012525b6fc19f21c65cef85b6ba98b6a0a23566tanstack@2.0.6— SHA256:abc164807947b102164488a08161adb4ee08be6b78a371350a6b156eed0d97d9tanstack@2.0.7— SHA256:7bb84e6ba893248814cd3bac70b7bdc115740fba9e13419940c73460cbcd7b6f- Endpoint de exfiltração:
hxxps://api.svix[.]com/ingest/api/v1/source/src_3387PLMB2uhXOBe3Q8sHu/in/3j2jokvbaF4WWdngv8zBbk - ID da fonte Svix:
src_3387PLMB2uhXOBe3Q8sHu - Conta de mantenedor npm:
sh20raj
Conclusão
Este ataque nos lembra o quão pouco é necessário para transformar uma configuração de name-squatting em um coletor de credenciais ativo. O atacante não precisou comprometer um mantenedor, realizar phishing em um sistema CI ou explorar uma vulnerabilidade. Eles registraram um pacote com nome plausível, adicionaram um script postinstall de uma página e esperaram pelas instalações.
O padrão de iteração de quatro versões é digno de nota. Esta não foi uma implantação única. O atacante estava presente, observando e ajustando seu payload em tempo real. Isso demonstra alguém que sabe o que está fazendo e estava otimizando especificamente para a cobertura de credenciais.
Cada .env arquivo em seu projeto é um alvo. Qualquer pacote com um hook postinstall pode lê-los. O registro npm concede a todo publicador essa capacidade por padrão.

