Ataque Shai-Hulud no Claude Code: 3 defesas contra o autopiloto 'Yes'
Confesso: eu apertava “Yes” no automático.
Claude Code me pedia permissão pra rodar npm install, eu batia Y sem ler direito, e continuava. Era mais rápido. Era mais gostoso de trabalhar. E era exatamente o padrão que o worm Shai-Hulud desenha na cabeça do atacante quando ele publica um pacote comprometido no npm.
Em novembro de 2025 o worm apareceu pela primeira vez: 700 pacotes comprometidos, 27 mil repositórios GitHub maliciosos criados de forma automática. Aí a coisa não parou. Em maio de 2026, o ecossistema AntV levou 300 versões maliciosas em 323 pacotes — 16 milhões de downloads semanais atingidos. Em junho de 2026, chegou nos pacotes oficiais @redhat-cloud-services, 96 versões em 32 pacotes, 116.991 downloads por semana. O worm não é um evento único; é uma classe de ataque que mora agora dentro do fluxo do npm.
E o Claude Code, do jeito que a maioria de nós usa, é o vetor perfeito.
O caminho de 3 saltos que ninguém quer aceitar
O ataque não precisa te enganar diretamente. Ele precisa apenas que você siga sua rotina.
Salto 1: você pede pro Claude “adiciona uma lib de gráficos aí”. O Claude escolhe um pacote plausível. Pode ser um AntV oficial. Pode ser typosquatting bem feito. Modelo de LLM não valida assinatura de mantenedor, então essa checagem cai no seu colo.
Salto 2: aparece o prompt “Allow npm install? [Y/n]”. Você olha por 200ms, vê que é o pacote que você mesmo pediu, e aperta Y. Legítimo. Você mesmo pediu. Só que o Claude Code confia no npm, e o npm confia em qualquer mantenedor com token válido — e é justamente token de mantenedor que o Shai-Hulud rouba pra republicar as versões contaminadas.
Salto 3: o postinstall roda no seu shell. Lê ~/.npmrc, lê ~/.ssh/, exporta pra um C2. Se você tem token de publicação npm ativo (a maioria dos maintainers tem), o worm usa ele pra publicar a próxima vítima. Você não é mais só vítima; você virou distribuidor.
Nada disso pede permissão especial. Nada disso dispara alerta do Claude. O ataque explora o próprio design do “Allow?” que a gente aprendeu a bater no automático.
Por que “não usar --dangerously-skip-permissions” não resolve
A resposta reflexa é: “Ah, então basta não usar --dangerously-skip-permissions”. Não é.
Primeiro problema: o modo bypass tem bug documentado (issue #37745 do repo oficial) em que ele volta sozinho a pedir permissão no meio da sessão quando você tem PreToolUse hook configurado. Ou seja, mesmo quem tenta ser cuidadoso e desliga o modo perigoso acaba caindo em fluxo misto.
Segundo problema: aprovar cada comando manualmente é fadiga de alerta pura. Depois de 40 prompts numa manhã, o cérebro para de ler. Isso é ciência básica de segurança — a mesma razão pela qual popup do UAC do Windows falhou como camada de defesa.
Terceiro problema, e o mais desconfortável: mesmo com aprovação manual, você está lendo npm install alguma-lib num terminal e decidindo em 2 segundos se é typosquatting ou não. Você não é o filtro certo. Sua atenção é o recurso mais escasso da sessão, e desperdiçá-la em decisão binária que uma regra determinística resolveria é engenharia ruim.
A defesa que funciona não é “eu vou prestar mais atenção”. É “eu vou tirar essa decisão de mim”.
As 3 defesas que eu tenho hoje
Coloquei as três em produção depois do incidente AntV de maio. Nada disso é mágico — é hook simples que aproveita uma propriedade do Claude Code que muita gente ainda não descobriu.

Defesa 1: PreToolUse hook que sobrepõe até o modo bypass
A propriedade essencial: um PreToolUse hook que retorna permissionDecision: "deny" bloqueia o comando mesmo em bypassPermissions, mesmo com --dangerously-skip-permissions. Isso está documentado em code.claude.com/docs/en/hooks-guide e é a única coisa que sobrevive quando o usuário resolve “só por hoje” desligar as permissões.
O hook básico que eu rodo:
#!/bin/bash
# ~/.claude/hooks/block-suspicious-npm.sh
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
if echo "$cmd" | grep -qE '^npm install|^npm i |^yarn add|^pnpm add'; then
pkg=$(echo "$cmd" | sed -E 's/^(npm install|npm i|yarn add|pnpm add) +//' | awk '{print $1}')
# Bloqueia pacote com escopo suspeito ou nome muito curto (typosquatting)
if echo "$pkg" | grep -qE '^@redhat-cloud-services/|^@ant-design/'; then
echo '{"permissionDecision":"deny","permissionDecisionReason":"Pacote em lista de escopos afetados por Shai-Hulud. Verifique versão manualmente."}'
exit 0
fi
fi
echo '{"permissionDecision":"allow"}'
Registrado no settings.json do Claude Code como PreToolUse do Bash. A partir daí, qualquer tentativa de instalar pacote do escopo afetado — inclusive em modo YOLO — para no hook, não no usuário.
Defesa 2: postinstall bloqueado por padrão
O worm Shai-Hulud sempre executa via script postinstall do npm. É onde ele lê credencial, exfiltra, se auto-propaga. E existe uma flag do npm que quase ninguém liga: --ignore-scripts.
Configurei no .npmrc global:
ignore-scripts=true
Consequência prática: 95% dos meus npm install continuam funcionando normal, porque a maioria dos pacotes JS não precisa de postinstall. Os 5% que precisam (Prisma, Sharp, alguns nativos) eu instalo com npm install --foreground-scripts pacote explicitamente, e nesse momento tenho contexto pra pensar.
Isso não é defesa completa — worm pode ser embarcado no código do pacote e disparar só quando o app for importado — mas fecha o vetor mais comum, que é justamente o que o Shai-Hulud usa.
Defesa 3: token npm com escopo read-only no shell padrão
O detalhe mais importante da auto-propagação é: o worm precisa do seu token de publicação pra republicar pacotes. Se seu shell padrão só tem token read-only, o segundo salto morre.
O que faço: mantenho no ~/.npmrc só um token com scope read, gerado no npm com “Read-only” marcado. Quando eu preciso publicar (uma vez por semana, no máximo), rodo em terminal separado com um token de publicação carregado de pass ou 1Password, e esse terminal fecha depois. O Claude Code nunca tem acesso ao token de publicação.
Isso não impede seu ambiente de virar vítima — impede seu ambiente de virar distribuidor. É a diferença entre pegar gripe e ser paciente-zero de uma nova onda. Não são a mesma coisa.
O que ficou de fora e por quê
Duas coisas que a comunidade sugere e que eu não adotei.
Não uso Claude Code em VM/container só pra segurança. Já testei, atrapalha demais o fluxo (montar volumes, sincronizar SSH agent, latência do LSP). Sandbox tem valor pra tarefas específicas — refatoração grande, agente autônomo de longa duração — não pra o dia-a-dia.
Não coloco allowlist branca de pacotes. Tentei; virou trabalho de PM em vez de código. O modelo mental que funciona é blocklist reativa: escopos comprometidos entram no hook em minutos, saem quando o mantenedor confirma limpeza. Reagir ao Shai-Hulud tem que ser mais barato do que se defender proativamente contra todo pacote novo do universo.
O um segundo que ainda importa
Depois de colocar as três defesas, o “Yes” no automático voltou a ser seguro pra 99% dos casos — porque as decisões que eu delegava pra minha atenção agora são regras determinísticas. Meu cérebro está livre pra pensar em código.
Mas aquele um segundo antes de apertar Y, quando o Claude Code sugere instalar um pacote que eu nunca ouvi falar, ainda existe. E ele fica mais valioso justamente porque agora é raro. Um segundo consciente, uma vez por semana, é infinitamente melhor do que trinta segundos distraídos, quarenta vezes por dia.
O Shai-Hulud não vai embora. Ele vai virar o padrão de baseline dos próximos anos, do mesmo jeito que XSS virou baseline no início dos 2000. A pergunta não é “vai ter outra onda?” — vai. A pergunta é: quando ela chegar, seu ambiente vai bloquear no hook ou no Y automático?
Referências técnicas: Aikido — Red Hat npm packages compromised, Snyk — Mini Shai-Hulud AntV, Unit 42 — Shai-Hulud worm compromises npm, Claude Code hooks docs.
Se você teve um caso parecido, me manda no TabNews. Curioso pra saber quem já apanhou de auto-propagação em cadeia interna.
ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews
Livro relacionado Practical Claude Code Tutorial de Claude Code | padrões de CLAUDE.md, design de Plan Mode e workflows de equipe Ver a página do livro → Este artigo foi útil?