Os patches do php2shell (CVE-2026-109618 e CVE-2026-109619) para o PHP em fim de vida (EOL) já estão disponíveis. Como as respostas do atendimento de vendas estão mais demoradas do que o normal devido à alta demanda, a maneira mais rápida de obter os pacotes corrigidos é adquirir o ELS para Runtimes on-line (abre em uma nova aba). Leia as perguntas frequentes sobre os patches

Vá direto para um resumo gerado por IA desta postagem do blog

  • Resuma esta postagem com o Perplexity
  • Resuma esta postagem com o Gemini

A versão resumida

O ataque Shai-Hulud ao npm voltou a ocorrer em 4 de agosto de 2026, entrando no registro por meio de keyv e o cacheable família de bibliotecas de cache, espalhando-se depois por conta própria para centenas de outros pacotes. Trata-se de um ladrão de credenciais que se auto-reproduz. Pesquisadores que o analisaram detalhadamente descobriram que a campanha se identificava nas descrições do repositório do GitHub como “Shai-Hulud: Here We Go Again”, o que a coloca na mesma linhagem dos ataques à cadeia de suprimentos do npm de setembro de 2025 e do As campanhas Shai-Hulud e Megalodon que analisamos em junho.

Os números variam dependendo de quem fez a medição e quando. A JFrog registrou mais de 400 pacotes em mais de 1.700 versões. O CyberScoop informou que a onda inicial atingiu 440 pacotes em menos de quatro horas, e que o total final ultrapassou 860 pacotes, somando dois bilhões de instalações mensais. Considere que são mais de 400 pacotes e, segundo algumas estimativas, mais de 800.

O número que vale a pena analisar não é a contagem de pacotes. São as quatro horas. Uma conta de mantenedor foi invadida e, em uma única tarde, a invasão se propagou por centenas de projetos não relacionados, pertencentes a pessoas que não fizeram nada de errado e não tinham como saber do ocorrido.

O que torna essa campanha interessante para estudo é que ela passou por duas vias completamente diferentes, e a maior parte das ferramentas defensivas do setor não está voltada para nenhuma delas. Para entrar, foi necessário comprometer um mantenedor e inserir código malicioso na árvore de código-fonte. A disseminação não exigiu a escrita de nenhum código. Exigiu apenas a capacidade de publicar.

Esses são dois problemas diferentes. Eles exigem duas respostas diferentes.

Estou sujeito ao ataque Shai-Hulud no npm?

Comece por aqui antes de ler qualquer outra coisa.

Você corre o risco de estar vulnerável se tiver instalado, ou se sua infraestrutura de código (CI) tiver instalado, qualquer versão do keyv, cacheable, cacheable-request, cache-manager, flat-cache, file-entry-cache, ou qualquer coisa sob o @cacheable a partir de 4 de agosto de 2026. As emissões contaminadas documentadas até o momento são keyv 6.0.0, cacheable 2.5.1, @cacheable/memory 2.2.1, @cacheable/net 2.1.1, @cacheable/node-cache 3.1.2 e @cacheable/utils 2.5.1, segundo a análise da JFrog, com cache-manager 7.2.10 e cacheable-request 13/01/2020, confirmado por Wiz. Segundo o CyberScoop flat-cache e file-entry-cache publicado cerca de trinta minutos após o primeiro lançamento. Verifique o que seu próprio arquivo de bloqueio resolveu, já que todas as listas publicadas ainda estavam sendo atualizadas à medida que eram divulgadas.

Você está exposto à segunda onda se consumir embalagens sob a @onereach, @or-sdk, @nebula.js, @qlik, @ornikar ou @servicetitan scopes ou qualquer um das centenas de outros pacotes cujos mantenedores tinham tokens do npm armazenados em uma máquina acessada pelo worm. Considere suspeita qualquer instalação do npm realizada em 4 de agosto ou depois dessa data até que você verifique o que ela realmente resolveu.

Um detalhe reduz consideravelmente o raio de ação. A carga útil era um npm preinstall gancho de ciclo de vida; e, no npm 12 e versões posteriores, esses ganchos não são executados por padrão. Se seus construtores e máquinas de desenvolvedores estiverem no npm 12 ou em versões mais recentes, de acordo com a política padrão de scripts, ou se você instalar com --ignore-scripts, o dropper não teria sido executado mesmo que o tarball infectado tivesse sido colocado em node_modules, a menos que os scripts de ciclo de vida tivessem sido explicitamente reativados para esses pacotes. A JFrog deixa isso bem claro, e essa é a única boa notícia realmente importante em relação ao incidente.

Um detalhe amplia isso. keyv e flat-cache não são pacotes que a maioria das equipes escolhe. Eles chegam como dependências transitivas do ESLint e de bibliotecas de clientes HTTP, várias camadas abaixo, em projetos que nem imaginam que eles estejam lá.

É por isso que esse ataque teve um alcance maior do que seus antecessores. Dados de telemetria da Wiz, citados pelo CyberScoop, revelaram que o pacote comprometido mais comum estava presente em cerca de 46% dos ambientes em nuvem monitorados, contra aproximadamente 28% na onda anterior do Shai-Hulud 2.0. O ataque Shai-Hulud ao npm conseguiu esse alcance ao invadir por meio de uma infraestrutura na qual ninguém pensa.

Como ocorreu o ataque Shai-Hulud ao npm

O ponto de entrada foi a conta de um mantenedor no GitHub. O Wiz descreve o keyv e cacheable pacotes que foram comprometidos “após o comprometimento da conta de um mantenedor do GitHub, o que resultou na publicação de versões maliciosas dos pacotes”, e descreve a sequência dos eventos: o invasor primeiro utilizou a identidade comprometida para introduzir cargas de persistência em IDEs no keyv no próprio repositório e, logo em seguida, publicou uma nova versão do keyv transportando a carga útil.

Essa ordem é importante. O código foi incorporado ao projeto antes de ser enviado ao registro; portanto, a versão que chegou ao npm resultou do próprio processo de publicação do projeto, e não de algo feito à margem dele. Do ponto de vista desse processo, uma identidade autorizada havia inserido o código no repositório e lançado uma versão. É para isso que ele existe.

Cada pacote continha dois arquivos. O primeiro, setup.mjs, é um pequeno dropper ofuscado integrado ao package.json como "preinstall": "node setup.mjs". Ele não transporta a carga útil. Ele baixa o ambiente de execução do JavaScript Bun, o descompacta e o utiliza para executar o segundo arquivo: cerca de 710 a 728 kilobytes de código JavaScript fortemente ofuscado, chamado math_init.js em alguns pacotes e Math_Symbol.js em outros.

A escolha de utilizar o Bun em vez do runtime do Node já presente é deliberada. Isso proporciona à carga útil um ambiente de execução previsível, independentemente da versão do Node da vítima, e transfere o trabalho propriamente dito para um processo que o gerenciador de pacotes não monitora.

A primeira porta: uma árvore-fonte envenenada

Para keyv e o cacheable pacotes, o código malicioso estava presente no repositório Git de origem. Isso é mais importante do que parece.

Isso significa que o compromisso resiste a qualquer abordagem baseada na suposição de que o código-fonte é confiável e apenas o artefato publicado é suspeito. Se você recompilar a partir do código-fonte, estará recompilando a porta dos fundos. Se verificar o artefato em relação ao código-fonte, a verificação será bem-sucedida. Verifique o atestado de proveniência, e ele será genuíno, porque a compilação realmente ocorreu no fluxo de trabalho declarado, a partir do commit declarado. O atestado vincula o artefato a um código-fonte e a um processo de compilação, e ambos eram reais; o código-fonte simplesmente já estava corrompido.

A campanha levou esse raciocínio até o fim, direcionando-o a um alvo diferente. A JFrog identificou uma lógica de caso específico voltada para o OpenSearch opensearch-js repositório, que utiliza o GitHub Actions OIDC para publicação confiável: dentro de uma execução de fluxo de trabalho cujo repositório era opensearch-js e cujo GITHUB_WORKFLOW_REF correspondentes release-drafter.yml, a carga útil solicitou um token OIDC do tipo “Actions” com escopo restrito a npm:registry.npmjs.org, trocou-o por um token de publicação, publicou um arquivo tar malicioso e gerou um pacote Sigstore por meio do Fulcio e do Rekor, de modo que o resultado apresentasse uma proveniência válida proveniente de um contexto de fluxo de trabalho confiável.

A defesa mais confiável contra essa brecha é alguém ou algo que analise o diff.

A segunda porta: 400 pacotes para os quais ninguém escreveu código

É aqui que a campanha ganha escala, e onde a mecânica difere do ponto de entrada de uma forma que altera a maneira como se defende contra ela.

A carga útil coleta tokens do npm a partir de ~/.npmrc e os valida em relação ao registro. Quando encontra um token que possui permissão de gravação e bypass_2fa Quando definido como “true”, ele faz o seguinte, citando a descrição da rotina fornecida pela JFrog: ele baixa o atual latest tarball, copia o exemplo em execução para package/math_init.js, grava o carregador em package/setup.mjs, substitui o pacote na íntegra scripts objeto e conjuntos scripts.preinstall para node setup.mjs, aumenta a versão do patch, depois recompila e publica com uma autenticação direta PUT para o repositório do npm.

Leia essa sequência novamente e observe o que está faltando. Nenhum commit. Nenhuma solicitação de pull. Nenhuma execução de CI. Nenhum acesso ao repositório de qualquer tipo. A árvore de código-fonte de cada um desses várias centenas de pacotes secundários permaneceu limpa o tempo todo e continua assim, porque o código malicioso existia apenas dentro de um arquivo tar montado na máquina do invasor e enviado diretamente para o registro com uma credencial roubada.

Essa é a maior parte desse incidente, em termos de número de pacotes: centenas de mantenedores cujos repositórios nunca foram alterados, cuja revisão de código nunca foi contornada, cuja integração contínua (CI) nunca detectou nada incomum e cujos usuários instalaram malware mesmo assim.

O que a carga útil transportou

O coletor de credenciais é tão minucioso que dá a impressão de ser uma lista compilada ao longo de várias campanhas, em vez de ter sido criada especificamente para esta. Ele percorre centenas de caminhos configurados no Linux, macOS e Windows, coletando tokens de gerenciadores de pacotes, credenciais de nuvem de arquivos de configuração e serviços de metadados de instâncias, tokens de contas de serviço do Kubernetes, todo o armazenamento KV do HashiCorp Vault, chaves SSH, perfis de VPN, armazenamentos de credenciais de navegadores, tokens do Stripe e do Slack, além de chaves para serviços de IA, incluindo OpenAI, Anthropic, Cursor e Gemini.

Nos executores do GitHub Actions, ele também faz um dump da memória do processo em busca de segredos que o executor já tenha descriptografado. Por trás de tudo isso, há uma varredura em mais de 200 padrões glob em busca de .env arquivos, chaves privadas, estado do Terraform e bancos de dados do KeePass.

Os resultados criptografados são enviados para repositórios públicos do GitHub criados na própria conta da vítima, com descrições que seguem o padrão “Shai-Hulud: Here We Go Again”. A Ox Security contabilizou mais de 800 desses repositórios identificáveis no GitHub. Um canal HTTP de reserva aponta para um domínio registrado em 22 de maio de 2026, mais de dois meses antes de ter sido utilizado.

A Ox Security também relata um mecanismo de sabotagem que os outros relatórios não descrevem: se o token do GitHub roubado for revogado, o malware emite comandos de exclusão contra a máquina infectada. Considere isso como uma informação fornecida por um fornecedor, e não como algo confirmado de forma independente, mas leve isso em conta ao planejar a sequência de ações de correção. Revogar as credenciais antes de isolar o host pode ter consequências.

E também foi atrás do seu editor

A parte do GitHub relacionada à propagação tem como alvo as máquinas dos desenvolvedores, e não o registro, e é a parte que tem mais chances de ainda estar passando despercebida em algum repositório por aí.

Utilizando tokens de acesso pessoal do GitHub roubados, a carga útil faz o commit de cinco arquivos em até 50 branches por repositório: .vscode/tasks.json, .vscode/setup.mjs, .claude/math_init.js, .claude/settings.json e .claude/setup.mjs. O tasks.json A entrada define uma tarefa chamada “Configuração do ambiente” que é executada node .claude/setup.mjs, e o settings.json a entrada registra um SessionStart hook. A execução ocorre quando um desenvolvedor abre o repositório no VS Code ou inicia uma sessão de programação com IA.

Os commits têm os seguintes títulos chore: update config e apresentam uma linha de coautoria falsificada que os atribui a [email protected]. Quando o token roubado também possui escopo de fluxo de trabalho, a carga útil cria um fluxo de trabalho do GitHub Actions que extrai segredos do Actions, compactando-os em um artefato e fazendo o download dele, em um branch chamado dependabot/github_actions/format/setup-formatter.

Cada um desses nomes é escolhido para passar despercebido em uma análise superficial. Um branch que se parece com o Dependabot, um fluxo de trabalho que se parece com o CodeQL, um commit que se parece com uma atualização de configuração, um artefato que se parece com um formatador e uma linha de coautor que se parece com um assistente de IA — muitos times agora estão fazendo commits desses itens em seus repositórios de forma legítima.

Por que os scanners tradicionais não detectaram o ataque Shai-Hulud ao npm

As ferramentas nas quais a maioria das organizações confia foram criadas para responder a uma pergunta que esse ataque não faz.

Os verificadores de vulnerabilidades comparam sua árvore de dependências com bancos de dados de CVEs conhecidos. Em 4 de agosto, não havia nenhum CVE para keyv 6.0.0, portanto não havia nada com que comparar. Quando os alertas foram divulgados, a janela de quatro horas já havia se encerrado e o worm já havia seguido em frente.

Isso não é uma crítica aos scanners. A detecção de vulnerabilidades conhecidas é uma tarefa diferente, e é algo que eles fazem bem.

Os controles de conta no Registro também cumpriram sua função. A autenticação de dois fatores protege uma conta de publicação contra alguém que tenha apenas uma senha. Ela não protege contra um token gerado por essa conta para fins de automação, e o worm procurava especificamente por tokens marcados para contornar a autenticação de dois fatores, justamente porque esses são os tokens que funcionam sem a presença humana. Muitas configurações automatizadas de publicação no npm têm, historicamente, contado exatamente com esse tipo de credencial: um token capaz de publicar sem a presença humana.

A proveniência e a assinatura são os casos mais complexos, pois, nessa campanha, elas funcionaram exatamente conforme especificado e, mesmo assim, geraram um resultado “verde”. A tentativa do OpenSearch é o exemplo mais claro: um arquivo tar malicioso publicado por meio de um fluxo de trabalho genuinamente confiável, com um pacote Sigstore gerado pelo Fulcio e pelo Rekor para corresponder a ele.

A proveniência responde à pergunta “esse artefato veio da fonte e do fluxo de trabalho que alega?”, e a resposta foi sim. Vale a pena responder a essa pergunta, e ela não perde o sentido neste contexto. Mas uma marca de verificação verde indica de onde um artefato veio, não se o que veio de lá é seguro.

A análise de acessibilidade apresenta o mesmo padrão de lacuna. Comprovar que um caminho de código vulnerável nunca é chamado é útil para priorizar o trabalho relacionado a CVEs. A preinstall O hook não precisa estar acessível a partir do seu aplicativo. Ele é executado como parte da instalação da dependência, antes mesmo de o seu aplicativo chamá-lo.

Duas portas precisam de duas fechaduras diferentes

As duas vias de acesso nesta campanha são bloqueadas por fatores totalmente diferentes; portanto, vale a pena ser preciso ao identificar qual mecanismo do TuxCare bloqueia cada uma delas.

O SecureChain para npm oferece componentes de código aberto que a TuxCare recompila a partir do código-fonte em sua própria infraestrutura de compilação e publica em seu próprio catálogo, acompanhados de atestados de proveniência e de um SBOM do CycloneDX para cada artefato. Os clientes configuram seu gerenciador de pacotes para acessar o SecureChain em vez do registro público, de modo que a TuxCare passa a ser a fonte padrão de onde suas compilações são obtidas.

Existem duas maneiras de fazer isso funcionar. Utilizar apenas o que está no catálogo do SecureChain ou colocar um gerenciador de registro na frente, de modo que tudo o que ainda não estiver no catálogo seja encaminhado para o registro público.

A segunda porta se fecha para os direitos de publicação

Vamos começar pelo mecanismo de propagação, pois é a parte mais importante do caso e a história mais clara. O método do worm consistia em baixar um arquivo tarball publicado, injetar dois arquivos e substituir o scripts bloquear, atualizar a versão do patch e enviar o resultado para o registro usando um token roubado. Esse ataque requer, acima de tudo, uma coisa: a capacidade de colocar uma nova versão de um pacote no local onde seu resolvedor irá procurá-la.

Para qualquer componente do catálogo do SecureChain, a versão que sua compilação utiliza é aquela que a TuxCare compilou a partir do código-fonte desse projeto em seu próprio ambiente de integração contínua (CI). O tarball republicado pelo invasor não está nesse caminho, e por mais que seja publicado no registro público, ele não será colocado lá. Os arquivos maliciosos nessas centenas de pacotes secundários existiam apenas dentro de um tarball enviado para o npm. Eles nunca estiveram no código-fonte. Uma compilação a partir do código-fonte não os reproduz, e não há nada para detectar, pois não há nada lá.

Vale a pena explicar o mecanismo de forma clara. A técnica que permitiu que essa campanha ganhasse escala requer acesso à publicação, independentemente da origem da sua compilação. Se for o registro público, basta um token roubado. Se for o catálogo do SecureChain, um token do npm roubado não traz nenhum benefício ao invasor, pois a publicação no npm não atribui uma versão à sua compilação.

A primeira porta se fecha ao ler o diff

O ponto de entrada é um problema mais complexo, e é justamente esse que o setor tem evitado em grande parte, pois a resposta sincera é que alguém precisa examinar o código.

O SecureChain realiza a detecção de código malicioso em seu pipeline de integração de pacotes. O detector analisa as diferenças no código-fonte entre uma nova versão do pacote e a versão anterior, buscando padrões de comportamento associados a violações na cadeia de suprimentos: execução suspeita durante a compilação, ofuscação, exfiltração de dados e outros indicadores de intenção maliciosa. Os ganchos de execução durante a compilação estão explicitamente incluídos no escopo, que abrange o npm preinstall e postinstall, Python setup.py caminhos de execução e chamadas de plug-ins do Maven.

Uma versão marcada é mantida fora do lançamento. Ela não entra no catálogo, o que significa que, desde o início, nunca chega à compilação do cliente.

Pense no que aquele detector estaria observando no dia 4 de agosto. A diferença entre a última imagem limpa keyv e keyv A versão 6.0.0 contém um novo arquivo chamado setup.mjs, um segundo arquivo novo com cerca de 710 kilobytes de código JavaScript fortemente ofuscado, e um preinstall verba que consta em package.json onde uma biblioteca de cache antes não tinha nenhuma.

Cada um desses é um sinal que o detector foi projetado para detectar: conteúdo ofuscado aparecendo em uma árvore de código-fonte, um gancho de execução durante a compilação surgindo onde antes não havia nenhum, e ambos aparecendo na mesma versão de uma biblioteca cuja única função é armazenar pares chave-valor. O detector se baseia no que uma alteração faz, em vez de apenas comparar com arquivos conhecidos como maliciosos; é por isso que reempacotar a mesma técnica com nomes de arquivo diferentes não consegue passar pelo filtro.

A detecção no nível do código-fonte é o mecanismo do SecureChain que aborda diretamente a primeira falha. Recompilar a partir do código-fonte não adianta quando é justamente o código-fonte que foi corrompido. Esse foi o argumento que apresentamos sobre a proveniência em junho, e essa campanha não o alterou. Ela apenas o reforçou, ao mostrar os dois modos de falha na mesma tarde.

Mitigação sem o SecureChain

Se suas compilações forem resolvidas diretamente a partir do registro público, esses são os controles que teriam limitado essa campanha, na ordem em que surtem efeito.

Atualize para o npm 12 ou uma versão posterior em todas as máquinas dos desenvolvedores e em todos os executores de CI. O preinstall A alteração padrão é a diferença entre um tarball corrompido que está em node_modules e um pacote tar corrompido que foi executado. Se você ainda não puder atualizar, instale com --ignore-scripts e tratar os pacotes que realmente precisam de etapas de compilação como exceções nomeadas.

Defina um limite mínimo de tempo de lançamento para que suas compilações nunca instalem uma versão no mesmo dia em que ela for lançada. Todos os quatro principais gerenciadores de pacotes já oferecem esse recurso de forma nativa: o npm tem min-release-age A partir da versão 11.10.0, o bun possui minimumReleaseAge A partir da versão 1.3.0, tanto o pnpm quanto o yarn oferecem opções equivalentes com exclusões por pacote. Um período de três a sete dias tem um custo muito baixo e teria coberto todo o intervalo de quatro horas desta campanha. Se você for levar apenas uma mudança de configuração desta postagem, que seja essa.

Verifique se os tokens do npm possuem permissão de gravação combinada com a contornagem da autenticação de duas etapas (2FA), que é exatamente a combinação que o worm explorou. Os tokens de publicação devem ter validade curta, estar restritos aos pacotes que precisam deles e ser emitidos para sistemas de automação, e não para pessoas. Dê preferência à publicação confiável sempre que o fluxo de trabalho permitir, mas tenha em mente, com base no caso do OpenSearch, que isso transfere o limite de confiança para as definições do seu fluxo de trabalho, em vez de removê-lo.

Trate os runners do CI como sistemas de produção que lidam com segredos, pois essa carga útil fez o dump da memória do processo do runner. Limite o escopo das políticas de confiança do OIDC a repositórios específicos e arquivos de fluxo de trabalho específicos, em vez de aplicá-las a toda a organização, e exija a revisão das alterações sob .github/workflows.

Analise o que seu editor e suas ferramentas de codificação com IA executam automaticamente a partir de um repositório. O .vscode/tasks.json e .claude/settings.json O Vector funciona porque, ao abrir um projeto, é executada a configuração que vem junto com ele. Trate esses arquivos como conteúdo executável na revisão de código, pois é isso que eles são.

Baixe o SecureChain →

Detecção

Pesquise em todos os ramos de todos os repositórios — e não apenas nos ramos padrão — pelos cinco arquivos de hook: .vscode/tasks.json que contenha uma tarefa “Configuração do ambiente”, .vscode/setup.mjs, .claude/setup.mjs, .claude/math_init.js, e .claude/settings.json com um SessionStart hook. Procure por commits com o título chore: update config, especialmente quando a linha de coautoria menciona [email protected].

Pesquise os nomes dos arquivos nas árvores de dependências do Grep e nos caches de pacotes setup.mjs, math_init.js, Math_Symbol.js e router_runtime.js. A JFrog publicou o hash SHA-256 da carga útil que extraiu de keyv 6.0.0; portanto, sempre que possível, faça a correspondência com base nessa versão, em vez de apenas nos nomes dos arquivos.

Nos registros de auditoria do GitHub, procure o dependabot/github_actions/format/setup-formatter ramificação, execuções de fluxo de trabalho denominadas codeql_analysis.yml ou “Executar Copilot”, que criam e excluem um artefato rapidamente, e qualquer artefato chamado format-results. Procure por repositórios criados nas contas da sua organização cujas descrições correspondam ao padrão “Shai-Hulud: Here We Go Again”.

No que diz respeito à rede, verifique se há conexões com npm-cache.com, e para o tráfego de saída destinado a pontos de extremidade RPC públicos da Ethereum a partir de uma infraestrutura de compilação que não deveria se comunicar com uma blockchain. A carga útil lê sua lista atual de domínios C2 a partir de um contrato da mainnet da Ethereum; portanto, ambos são sinais úteis de detecção, mas nenhum deles constitui um bloqueio confiável.

Lista de verificação para correção do ataque Shai-Hulud no npm, por ordem de prioridade

  1. Determine se preinstall os scripts poderiam ter sido executados. Verifique a versão do npm em todas as máquinas e executores que instalaram dependências a partir de 4 de agosto de 2026 e se --ignore-scripts estava em vigor. Se os hooks não pudessem ser executados, o que restaria a você fazer seria garantir a higiene das dependências, em vez de responder a incidentes.
  2. Isole antes de revogar. Preserve primeiro os arquivos tar, os logs do npm, os logs de CI, os logs de auditoria do GitHub e as imagens do runner. Considerando o comportamento de exclusão relatado na revogação de tokens, isole a sequência antes da rotação de credenciais em qualquer host que você acredite ter executado a carga maliciosa.
  3. Fixem os arquivos de bloqueio nas versões publicadas antes de 4 de agosto de 2026 para todos os pacotes afetados e limpem os caches dos gerenciadores de pacotes para que os arquivos tar corrompidos não fiquem armazenados localmente.
  4. Revogue primeiro os tokens do npm, começando por aqueles que possuem permissão de gravação e contornam a autenticação de duas etapas (2FA); em seguida, revogue os tokens de acesso pessoal do GitHub e os tokens do Actions.
  5. Gire tudo o que o coletor pudesse ler, partindo do princípio de que ele tenha lido: credenciais na nuvem, tokens de contas de serviço do Kubernetes, conteúdo do Vault, credenciais de banco de dados, chaves SSH, perfis de VPN, tokens do Stripe e do Slack e chaves de API para serviços de IA.
  6. Faça uma varredura em todos os ramos de todos os repositórios em busca dos cinco arquivos de hook e dos commits marcadores, e remova-os.
  7. Recrie os executores de CI e os ambientes de desenvolvimento a partir de imagens limpas. Limpar arquivos individuais não é o mesmo que ter certeza de que a máquina está limpa.
  8. Analise os editores confiáveis do npm e as políticas de confiança do OIDC do GitHub, com atenção especial aos fluxos de trabalho de automação de lançamentos, uma vez que esses foram alvo específico dos ataques.
  9. Só então passe para a prevenção: limites mínimos de idade para lançamento, npm 12, escopo de tokens e requisitos de revisão do fluxo de trabalho.

Por que isso continua funcionando

A autoria ainda não foi confirmada. Pesquisadores citados pelo CyberScoop observaram que ainda não possuem evidências concretas que liguem esse caso ao TeamPCP, o agente que comprometeu mais de mil pacotes no início de 2026, embora essa possibilidade esteja em aberto. Várias empresas relataram a mesma carga maliciosa e o mesmo padrão em todos os pacotes afetados, o que aponta para um único agente ou um grupo fortemente coordenado, em vez de imitadores.

A questão da atribuição é menos interessante do que a questão estrutural. A mesma técnica continua funcionando porque, na verdade, não é uma técnica; é uma observação sobre como os ecossistemas de pacotes são construídos: qualquer pessoa capaz de publicar uma versão de um pacote pode executar código em todas as máquinas que o instalem. Isso não é um bug no npm. É para isso que serve um script de ciclo de vida, e milhares de pacotes legítimos dependem desse comportamento.

Some-se a isso o fato de que os direitos de publicação pertencem a indivíduos, que esses indivíduos possuem tokens, que os tokens estão armazenados em arquivos em laptops e que a primeira ação da carga útil é procurar esses arquivos. A propagação do worm não é uma capacidade incomum; trata-se do fluxo de trabalho comum de publicação executado por um malware, em vez de por um mantenedor.

Em junho, o argumento era que uma verificação de proveniência verde é apenas um dos fatores a serem considerados na decisão de confiança, e não um veredicto. Em agosto, o argumento é mais restrito e mais mecânico: se a versão à qual sua compilação faz referência for a que um invasor com um token roubado enviou mais recentemente, então todos os outros controles que você possui estão a jusante de uma decisão que você não tomou.

Então, tome essa decisão de forma consciente. Verifique quais versões suas compilações resolveram em 4 de agosto e, em seguida, defina um limite mínimo de idade para as versões antes da próxima onda, pois haverá uma. Se você preferir que as versões que suas compilações resolvem venham de um catálogo que alguém recompila e revisa, em vez de quem quer que seja que possua um token de publicação, entre em contato conosco para saber mais sobre o SecureChain para npm.

Perguntas frequentes

Isso é a mesma coisa que a campanha Shai-Hulud de setembro de 2025?

Da mesma linhagem, e se autodenomina como tal, mas não é o mesmo evento. O ataque npm Shai-Hulud de agosto de 2026 ocorreu por meio de keyv e cacheable em vez dos pacotes afetados anteriormente, e o CyberScoop a descreve como uma variante do Mini Shai-Hulud. De acordo com os números de prevalência no ambiente divulgados pela Wiz, ela se espalhou consideravelmente mais do que suas versões anteriores.

O repositório do pacote no GitHub parece estar livre de problemas. Isso significa que a versão que instalei também está livre de problemas?

Não, e esse é o detalhe que mais facilmente passa despercebido. No caso das centenas de pacotes secundários, o invasor nunca acessou o repositório de código-fonte. O código malicioso existia apenas no arquivo tar publicado no npm. Um repositório limpo não diz nada sobre o que seu gerenciador de pacotes realmente baixou. Verifique a versão que seu arquivo de bloqueio (lockfile) resolveu, não o código-fonte.

Uma assinatura válida ou um atestado de proveniência garantem que uma encomenda é segura?

Não. No caso do OpenSearch, essa campanha gerou um pacote Sigstore autêntico, por meio do Fulcio e do Rekor, para um arquivo tar malicioso publicado a partir de um fluxo de trabalho confiável. A proveniência determina a origem. Ela não avalia o conteúdo.

Utilizamos um registro privado que atua como proxy do npm. Estamos protegidos?

Só se ele fizer mais do que simplesmente repassar os artefatos. Um proxy de cache armazenará em cache e servirá a versão corrompida sem problemas, geralmente mais rápido do que o servidor de origem faria. O que importa é se há algo que inspecione, recompile ou atrase o que passa por ele.

Executamos um verificador de vulnerabilidades em cada compilação. Por que ele não detectou isso?

Não foi encontrada nenhuma vulnerabilidade conhecida. Os scanners comparam sua árvore de dependências com bancos de dados do CVE e, em 4 de agosto, as versões comprometidas já tinham algumas horas, sem nenhum aviso associado. A verificação de vulnerabilidades conhecidas e a detecção de código malicioso são problemas distintos que exigem ferramentas diferentes.

O que a SecureChain teria feito nessa situação?

Há duas situações diferentes para os dois caminhos de acesso. No caso das centenas de pacotes comprometidos pela republicação de tarballs, a versão corrompida não está no caminho a partir do qual sua compilação é resolvida, pois o SecureChain disponibiliza a versão que a TuxCare compilou a partir do código-fonte, em vez de atuar como proxy para o que quer que o desenvolvedor original tenha publicado mais recentemente. Para o inicial keyv e cacheable Como solução alternativa, quando o código é enviado primeiro para o repositório, o detector de código malicioso analisa as diferenças entre as versões durante a integração e retém a versão, de modo que a versão corrompida nunca entre no catálogo. Ambas as medidas se aplicam em todo o SecureChain catálogo, para cada componente nele contido.

Resumo
Ataque Shai-Hulud no npm: keyv, versões afetadas, o que fazer
Nome do artigo
Ataque Shai-Hulud no npm: keyv, versões afetadas, o que fazer
Descrição
O ataque Shai-Hulud ao npm atingiu mais de 400 pacotes em quatro horas por meio do keyv e do cacheable. Versões afetadas, indicadores de comprometimento (IOCs) e uma lista de verificação de correções priorizadas.
Autor
Nome da editora
TuxCare
Logotipo da editora

Junte-se a mais de 4.500 profissionais de Linux e código aberto!

2 vezes por mês. Sem spam.

Índice
Obtenha as respostas sobre segurança de código aberto de que você precisa

Junte-se a mais de 4.500 profissionais de Linux e código aberto!

2 vezes por mês. Sem spam.