Aikido

Keyv e os seus amigos foram alvo de um ataque ativo à cadeia de abastecimento do Shai-Hulud

Escrito por
Ilyas Makari

A 4 de agosto de 2026, uns atacantes comprometeram a conta do GitHub do responsável pela manutenção do keyv, uma biblioteca de armazenamento de chave-valor com cerca de 127 milhões de downloads semanais no npm, e aproveitou esse acesso para introduzir um worm que rouba credenciais em toda a família de pacotes. O mesmo mantenedor é proprietário de armazenável em cache (29 milhões de downloads por mês), cache plana (565 milhões de downloads por mês), cache-de-entradas-de-ficheiros (557 milhões de downloads por mês) e vários outros utilitários de cache amplamente utilizados, todos os quais foram afetados pelo mesmo ataque.

A invasão foi levada a cabo através da introdução direta de ficheiros maliciosos no principal criar um ramo e, em seguida, lançar imediatamente uma nova versão, o que significa que as versões corrompidas foram publicadas no npm com uma proveniência válida, assinada pelo GitHub Actions.

Os pacotes afetados incluem:

  • keyv 6,0,0 (604 milhões/mês)
  • cache plana 6,1,24 (580 milhões/mês)
  • cache-de-entradas-de-ficheiros 11,1,6 (571 milhões/mês)
  • pedido-armazenável-em-cache 13,0,20 (137 milhões/mês)
  • armazenável em cache 2,5,1 (30 milhões/mês)
  • @cacheable/memória 2,2,1 (28 milhões por mês)
  • gestor de cache 7,2,10 (16 milhões por mês)
  • @cacheable/node-cache 3.1.2 (6 milhões por mês)
  • @cacheable/utils 2,5,1 (34 milhões por mês)
  • @cacheable/net 2.1.1 (3,7 mil/mês)
  • ecto 5,0,1 (4,5 mil/mês)

Estamos também a assistir a uma propagação comunitária muito ativa deste «worm» da cadeia de abastecimento para outros responsáveis pela manutenção e pacotes, incluindo organizações de grande dimensão:

  • @deliveroo/reevent 1.0.1
  • @or-sdk/invitations 1.4.9
  • @picsart/ai-sdk 3.32.2
  • @qlik/embed-runtime 1.6.4
  • picasso.js 2.11.6

Atualização — 4 de agosto de 2026, 13:37 CEST: Pelo menos 434 pacotes (em 1 381 versões) foram comprometidos pelo worm, com um total combinado de mais de 2 mil milhões de instalações mensais à data da redação deste artigo.

O que aconteceu

Cada pacote da família recebeu dois novos ficheiros, setup.mjs e Math_Symbol.js, juntamente com um "preinstall": "node setup.mjs" registo adicionado a cada um package.json. Qualquer pessoa que tenha participado npm install contra uma versão afetada teria tido setup.mjs ser executados automaticamente antes de a sua instalação estar concluída.

setup.mjs é um dropper altamente ofuscado. A sua única função é descarregar silenciosamente o ambiente de execução Bun JavaScript a partir de github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/ e utilizá-lo para executar a carga útil real, Math_Symbol.js:

execFileSync(<bun binary>, ['<script_dir>/Math_Symbol.js'], {
  stdio: 'inherit',
  cwd: <script_dir>
})

O Math_Symbol.js é um ficheiro JavaScript de 728 KB fortemente ofuscado que contém programas de roubo de credenciais que recolhem secrets ambiente da vítima, encriptam os dados obtidos e os transferem para um repositório público do GitHub cuja descrição diz «Shai-Hulud: Lá vamos nós outra vez". A carga útil também contém funcionalidades de propagação do tipo «worm» para infetar pacotes de outros responsáveis pela manutenção que tenham instalado um dos pacotes comprometidos.

O que ele rouba

O Math_Symbol.js O ficheiro implementa um conjunto de extratores de credenciais, cada um dos quais visando um repositório de segredos diferente na máquina da vítima.

tokens npm

~/.npmrc e analisa o sistema de ficheiros à procura de quaisquer outros .npmrc ficheiros. Excertos authToken valores e quaisquer //registry.*:_authToken=... entradas. Valida cada token em tempo real em relação a registry.npmjs[.]org/-/whoami antes de proceder à exfiltração.

tokens do GitHub

São visados três formatos de tokens: os PAT clássicos (ghp_...) e tokens OAuth (gho_...), tokens servidor-a-servidor da aplicação GitHub (ghs_...), e tokens JWT OIDC. As fontes incluem ~/.config/gh/hosts.yml, variáveis de ambiente e uma verificação do sistema de ficheiros.

Nos executores do GitHub Actions, a carga útil também executa um comando de shell que lê diretamente a memória do processo do executor para extrair todo o armazenamento de segredos. Este lê ACTIONS_ID_TOKEN_REQUEST_TOKEN e ACTIONS_ID_TOKEN_REQUEST_URL para roubar os tokens OIDC utilizados na publicação no npm.

Credenciais AWS

  • ~/.aws/credentials e ~/.aws/config, analisando todos os perfis nomeados
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, e AWS_SESSION_TOKEN variáveis de ambiente
  • Serviço de Metadados de Instâncias EC2 em 169.254.169.254, experimentando primeiro o IMDSv2, com o IMDSv1 como alternativa
  • Ponto de acesso container do ECS em 169.254.170.2
  • AWS Secrets , a ligar secretsmanager:ListSecrets em várias regiões, para identificar e extrair todos secrets aí secrets

secrets do Kubernetes

Lê o token da conta de serviço, o certificado da CA e o espaço de nomes a partir de secrets.io/serviceaccount/. Utiliza o token da conta de serviço para consultar diretamente a API do Kubernetes e recuperar todos secrets namespace. Também tem como alvo KUBECONFIG e ~/.kube/config.

Tokens do HashiCorp Vault

Verifica seis fontes por ordem de prioridade: o VAULT_TOKEN variável de ambiente, ~/.vault-token, o caminho do executor do GitHub Actions /home/runner/.vault-token, vários container conhecidos, um início de sessão no Kubernetes utilizando o JWT da conta de serviço roubada e o ponto final de autenticação do Vault no AWS IAM utilizando quaisquer credenciais roubadas da AWS. Após obter um token, enumera todas as bases de dados KV através de /v1/sys/mounts e lê todos os segredos dos caminhos KV v1 e v2.

Tokens do Stripe e do Slack

Procura chaves da API do Stripe (tanto de teste como de produção, sk_ e pk_ prefixos) e tokens do Slack (xox[baprs]-...) em todos os ficheiros analisados pelo scanner do sistema de ficheiros.

Análise geral do sistema de ficheiros

Um scanner que tem em conta a plataforma (macOS vs. Linux) executa cerca de 200 padrões globais em todo o sistema de ficheiros, visando, entre outras coisas:

  • .env, .env.*, e .envrc files
  • Ficheiros de chaves privadas (*.pem, *.key, *.p12, *.pfx, *.jks)
  • Chaves SSH e configuração (id_rsa, id_ed25519, .ssh/config)
  • Ficheiros de estado do Terraform e .tfvars
  • Ficheiros de credenciais do registo do Docker (docker/config.json)
  • Bases de dados do KeePass (*.kdbx)
  • Configurações de VPN (*.ovpn)
  • Ficheiros de configuração do IDE, incluindo .vscode/tasks.json e .claude/settings.json

Os ficheiros com mais de 5 MB são ignorados. São utilizadas até 64 leituras simultâneas. É também aplicado um motor de expressões regulares genérico a todos os ficheiros analisados, identificando chaves privadas PEM, chaves públicas SSH, chaves de armazenamento do Azure, cadeias de ligação a bases de dados com credenciais incorporadas e genéricas chave=valor padrões que correspondam a nomes de campos secretos comuns.

Exfiltração

Assim que as credenciais são recolhidas, a carga útil encripta todo o pacote antes de o enviar para qualquer lugar. Apenas o atacante, que possui a chave privada correspondente RSA , pode desencriptar o que é carregado. Isto significa que os dados roubados ficam à vista de todos na infraestrutura pública, mas são ilegíveis para qualquer outra pessoa.

O principal destino da exfiltração é um repositório público do GitHub cuja descrição contém a sequência«Shai-Hulud: Here We Go Again». À data da redação deste artigo, o GitHub contém cerca de 1 300 repositórios públicos que correspondem a essa sequência, servindo cada um deles como ponto de entrega do pacote de credenciais encriptadas da vítima.

Se o envio para o GitHub falhar, a carga útil recorre a https://npm-cache[.]com:443/router, um domínio registado em 22 de maio de 2026 que parece não ter qualquer finalidade legítima. Este domínio é obtido dinamicamente a partir de um contrato inteligente da Ethereum em 0xE1f2395ee43e45A1556EC6438a88c31B83493103, permitindo que o atacante altere a infraestrutura a qualquer momento sem alterar a carga útil.

Worm autorreplicante

Para além de roubar credenciais, a carga útil utiliza-as ativamente para propagar o malware a outros mantenedores e repositórios. Possui dois vetores de infeção distintos.

Infecção do ficheiro tarball do npm

Utilizando o token npm roubado, a carga útil chama https://registry.npmjs[.]org/-/npm/v1/tokens para listar todos os pacotes para os quais esse token tem direitos de publicação e, em seguida, descarrega e descompacta o ficheiro tar atual de cada um deles. Antes de voltar a publicar, efetua as seguintes alterações:

  • Aumenta a versão do patch em um (por exemplo, 1.2.3 torna-se 1.2.4)
  • Adiciona "preinstall": "node setup.mjs" para os scripts do pacote
  • Injeções setup.mjs e math_init.js (funcionalmente idêntico a Math_Symbol.js) para dentro da embalagem

Em seguida, volta a compactar e publica o ficheiro tarball modificado no registo.

É assim que o worm se propaga para além do responsável original. Após o ataque inicial ao keyv Como responsáveis pela manutenção, observámos que mais de 400 pacotes foram infetados através da propagação na comunidade. Estas infeções de segunda geração são identificáveis pelo uso de math_init.js em vez de Math_Symbol.js, uma vez que foram infetados pelo worm de injeção de ficheiros tarball do npm.

Infecção do repositório do GitHub

Quando a carga útil encontra um ghs_ token, efetua o commit em todos os ramos a que consegue aceder, até um máximo de 50 ramos por repositório, processando primeiro os ramos mais recentes e ignorando dependabot e copiloto ramificações. Adiciona ganchos maliciosos a .claude/settings.json e .vscode/tasks.json para que o código executável seja executado automaticamente da próxima vez que um programador abrir o repositório no VS Code ou iniciar uma sessão do Claude Code no seu interior, sem necessidade de executar o comando «npm install». Os commits são criados como claude por e-mail claude@users.noreply.github[.]com e transmitir a mensagem tarefa: atualizar a configuração, misturando-se com commits reais.

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 Device Protection da 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 IDE e dependências de build, tudo em um só lugar. Pare 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.

Indicadores de Compromisso (IOCs)

Arquivos

  • setup.mjs
    • SHA-256 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668
  • setup.mjs (versão de transmissão comunitária)
    • SHA-256 fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb
  • Math_Symbol.js e math_init.js
    • SHA-256 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc

Rede

  • https://npm-cache[.]com:443/router — terminal de exfiltração
  • eth-mainnet.nodereal[.]io pedido que contém 0xE1f2395ee43e45A1556EC6438a88c31B83493103

Outros

  • Qualquer repositório público do GitHub cuja descrição contenha «Shai-Hulud: Lá vamos nós outra vez» — estes são os repositórios controlados pelo atacante utilizados para a exfiltração de credenciais.

Compartilhar:

https://www.aikido.dev/blog/keyv-and-friends-compromised-in-npm-supply-chain-attack

Verificar por malware

Comece Gratuitamente
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.