Voltar ao Blog
    Segurança
    Backend

    Shai-Hulud: O Worm que Continua Infectando o npm e Como Proteger Sua Cadeia de Suprimentos

    Mais de 1.280 pacotes npm com 2+ bilhões de downloads/mês comprometidos, se espalhando sozinho a cada poucos minutos. Um ano depois da primeira onda, o Shai-Hulud voltou — e o que fazer no seu pipeline hoje.

    Publicado em ·10 min de leitura·por Bernardo Gomes

    Em 4 de agosto de 2026, um atacante comprometeu a conta do GitHub de jaredwray, mantenedor do keyv — biblioteca de armazenamento chave-valor com cerca de 127 milhões de downloads semanais no npm — e publicou uma versão maliciosa. Em minutos, o malware se auto-replicou para outros pacotes do mesmo mantenedor (flat-cache, file-entry-cache, cacheable, cache-manager) e, de lá, para dependentes de outros mantenedores. Pesquisadores da Aikido Security batizaram a nova onda de 'Shai-Hulud: Here We Go Again' — o mesmo nome do worm que abalou o npm em setembro de 2025.

    ⚠️

    Fonte: DevOps.com / Aikido Security, Ilyas Makari e Charlie Eriksen (04/08/2026). No pico, o worm infectou 50 a 100 pacotes novos a cada poucos minutos, chegando a mais de 1.280 pacotes com 2+ bilhões de instalações mensais combinadas — incluindo dependências usadas por Deliveroo, ServiceTitan, Picsart e Qlik.

    Como o worm se espalha sozinho

    O mecanismo é o que torna esse ataque diferente de um typosquatting comum: cada pacote infectado recebe dois arquivos — setup.mjs e Math_Symbol.js — injetados via CI comprometido, com release cortado imediatamente e assinatura de provenance legítima (porque o workflow que publicou era, de fato, o workflow oficial do mantenedor). O Math_Symbol.js, com 728KB, varre o sistema com cerca de 200 padrões glob procurando chaves privadas, tokens do GitHub e npm, credenciais AWS, segredos do Kubernetes e do HashiCorp Vault, tokens do Stripe e do Slack, configurações de VPN e de IDE. Ao encontrar um token npm ou GitHub com permissão de publicação, o worm usa a própria credencial da vítima para infectar os pacotes que ela mantém — e o ciclo recomeça.

    ℹ️

    Provenance do npm confirma onde e como um pacote foi construído — não que o código-fonte por trás seja confiável. Neste ataque, os arquivos maliciosos foram enviados através de uma conta de mantenedor comprometida e publicados pelo workflow legítimo, o que dá aos pacotes envenenados uma assinatura de provenance tecnicamente válida.

    O que fazer agora, na prática

    • Trave ou reverta versões suspeitas de keyv, flat-cache, file-entry-cache e demais pacotes da árvore do jaredwray — geralmente entram como dependência transitiva, então audite o lockfile inteiro, não só as diretas
    • Rotacione qualquer token npm, PAT do GitHub, chave de nuvem e segredo de CI/Vault usado em máquinas que rodaram npm install após o horário de exposição — o custo de rotacionar é sempre menor que o de um vazamento
    • Use --ignore-scripts no CI: isso bloqueia toda uma classe de malware que depende de hooks de instalação (preinstall/postinstall) para executar
    • Adicione overrides no seu gerenciador de pacotes (pnpm-workspace.yaml, package.json resolutions ou npm overrides) fixando versões conhecidas-boas de dependências sensíveis — é a mesma técnica que já usamos neste projeto para travar TypeScript e Vitest em versões estáveis
    • Audite lockfiles e logs de CI em busca de versões maliciosas, incluindo em devDependencies — o worm não distingue produção de desenvolvimento
    • Prefira pnpm com minimumReleaseAge (ou equivalente) para exigir que um pacote tenha algumas horas de idade antes de ser instalável — a maioria dos worms é detectada e removida do registro em menos de 24h
    yaml
    # pnpm-workspace.yaml — mitigação de defesa em profundidade
    # contra pacotes recém-publicados e dependências comprometidas
    minimumReleaseAge: 1440   # minutos (24h) antes de um pacote virar instalável
    
    overrides:
      # trave em versão auditada manualmente até a árvore do keyv normalizar
      keyv: "4.5.4"
      flat-cache: "3.2.0"

    Por que isso não vai parar de acontecer

    O npm tem mais de 3 milhões de pacotes e depende de um modelo de confiança onde qualquer mantenedor pode publicar código que roda, sem sandbox, na máquina de milhões de desenvolvedores e em pipelines de CI com acesso a produção. Isso não é uma falha pontual: é a arquitetura. Desde a primeira onda do Shai-Hulud em setembro de 2025, houve pelo menos três variantes documentadas — incluindo o 'Mini Shai-Hulud' que atingiu pacotes do TanStack em maio de 2026 e o 'ChainDrop' identificado pela Datadog em agosto. O padrão se repete: conta de mantenedor comprometida (geralmente por phishing ou token vazado), publicação de release maliciosa, propagação worm-like via credenciais roubadas da própria vítima.

    💡

    Trate toda dependência transitiva como superfície de ataque, não como detalhe de implementação. Um SBOM atualizado, overrides para pacotes sensíveis e rotação de credenciais como rotina — não como resposta a incidente — são o que separa 'li sobre isso' de 'não fui afetado'.