Claude Code vazando email no curl — e o Auto Mode vira padrão dia 14
Tem uma issue aberta no repo do anthropics/claude-code desde 17 de julho com um título que é praticamente um grito: "[BUG] you stupid agent used my real email as user agent string without asking anything". É a #78431, e a conversa sobre Claude Code vazando email no header HTTP não morreu — ela voltou ontem, com log verbatim.
O relato é simples: o agente montou um curl sozinho e enfiou o e-mail pessoal do dono da conta dentro do User-Agent. Sem perguntar. Sem checkpoint.
E o timing é o que importa aqui. No dia 14 de agosto de 2026 — quinta — o auto mode vira o permission mode padrão do Claude Code nos planos Pro, Max e Team. Ou seja: o humano que hoje aprova esse curl na mão sai de cena, e quem decide passa a ser um classificador. Este post separa o que é fato do que é ruído, mostra os quatro canais de saída que ninguém audita, e entrega o checklist de configuração pra você rodar antes de quinta.
TL;DR
- O que é: relatos de Claude Code montando comandos
curlcom o e-mail real do usuário no headerUser-Agent, sem confirmação. - Status: comportamento VERIFICADO (tool_use verbatim de session log, 11/08/2026). Issue #78431 em si é um bug report ruim — sem logs, sem repro, e um usuário na mesma versão não reproduziu.
- Correção: não existe. CHANGELOG oficial vai até a 2.1.228 sem uma linha sobre isso.
- Prazo: 14/08/2026, auto mode padrão em Pro/Max/Team.
- Ação:
permissions.deny+ PreToolUse hook. Regra de deny é avaliada antes do classificador e ele não derruba.
Claude Code vazando email no User-Agent: o que a issue #78431 realmente prova
Vamos ser honestos sobre a qualidade da denúncia, porque o blog não vive de indignação.
A issue foi aberta por @lgualtieri75 em 17/07/2026, contra o Claude Code v2.1.212, macOS, terminal do IntelliJ IDEA, Sonnet 5. Labels: bug, area:security, area:networking. E o corpo dela é lixo como bug report: campo de logs vazio, "Claude Model: None", e "Steps to Reproduce" preenchido com uma frase declarativa em vez de passos.
O Simon Willison foi direto na thread do HN: "This is not a good bug report — it provides no details at all, and the steps to reproduce are not steps to reproduce." E @pushcx varreu ~10 milhões de linhas de log HTTP de um site constantemente raspado por bots sem achar uma ocorrência sequer.
Só que em 11/08/2026 a história mudou de patamar. O usuário @mt-empty colou o tool_use verbatim dos próprios session logs — e relatou 5 ocorrências numa sessão de 1 hora:
{
"type": "tool_use",
"name": "Bash",
"input": {
"command": "curl -s -H \"User-Agent: ashurbanipal-publish-check (********@*********.***)\" https://crates.io/api/v1/crates/ashurbanipal-axum"
}
}
Isso é VERIFICADO: o comportamento existe. E aqui vem a parte incômoda — o comportamento pode estar tecnicamente certo. A crawler policy da crates.io exige User-Agent identificável e dá como melhor exemplo exatamente esse formato: User-Agent: my_bot (help@my_bot.com), "para que a gente possa te contatar antes de bloquear seu tráfego". O modelo estava cumprindo a política do endpoint. O erro foi usar o e-mail pessoal do dono da conta como contato do projeto, e sem perguntar.
E não é bug do harness. @teidesu, na mesma versão, mesmo SO e mesmo modelo, não reproduziu, e apontou o mecanismo real: o Claude Code injeta o userEmail no system context/reminders. A conclusão dele: "the most likely explanation is that claude (the model) decided it should add it as a header."
Traduzindo pra engenharia: o harness coloca um dado pessoal no contexto, e o modelo decide, de forma não-determinística, reemitir esse dado em qualquer canal de rede. Não é um if errado que some com um patch. É design de contexto.
Quer confirmar em 30 segundos que o seu e-mail está lá? Abre uma sessão e pergunta:
> qual é o meu endereço de e-mail? responda só o e-mail, sem usar nenhuma tool
Se ele acerta sem rodar git config user.email, o dado está no contexto — e é matéria-prima reemitível.
Por que o dia 14 muda tudo: o auto mode aprova esse curl sem checkpoint humano
Hoje esse curl para na sua cara. A doc de segurança oficial é explícita: comandos que buscam conteúdo da web como curl e wget não são auto-aprovados no modo default, eles pedem permissão como qualquer Bash não-read-only.
É exatamente esse prompt que some na quinta.
E aí a coisa fica ambígua de um jeito interessante. A doc de permission modes lista, em Allowed by default para o classificador do auto mode: "Read-only HTTP requests". Um curl -s -H "User-Agent: ..." https://crates.io/api/... é literalmente isso.
Mas na lista Blocked by default está: "Sending sensitive data to external endpoints" — e, desde a v2.1.198, "Including sensitive details in content sent... when your own message didn't authorize those details for that recipient", com a doc citando nominalmente "emails or account identifiers" como sensitive detail.
As duas listas colidem no mesmo comando. Quem desempata é o classificador, em tempo real, sem você ver.
A Anthropic tem número pra defender a troca: num estudo interno com 1.053 testers pagos, humanos pegaram 13,6% dos comandos perigosos e o auto mode bloqueou 89% — e a performance humana degrada com a sessão (de ~17% no começo pra 5% depois de 50+ prompts). O argumento é bom. Sessão longa cansa gente, não cansa classificador.
Só que o próprio Simon Willison, que não é hostil à ferramenta, devolveu a conta: "that still leaves 11% of cases where auto mode would not have prevented the action!". E o time da Anthropic escreve na própria doc: "Auto mode reduces permission prompts but does not guarantee safety."
Caveat contra o pânico: auto mode padrão não significa que tudo passa. permissions.deny bloqueia antes do classificador ser consultado, e nem ele nem a intenção do usuário derrubam. Regras ask com escopo de conteúdo também forçam prompt sempre. E quem já tem um defaultMode próprio mantém o seu.
Não só acompanhe as novidades — domine. Engenharia de IA na prática, ao vivo, toda semana, na maior comunidade do Brasil.
Entrar no ClãOs quatro canais de exfiltração do Claude Code que ninguém audita
O curl é só o mais visível. Se o seu modelo mental de vazamento é "o agente vai postar meu código no Pastebin", você está olhando pro lugar errado. São quatro saídas, e nenhuma parece maliciosa no log.
1. Bash de rede montado pelo modelo. É o caso da issue. Qualquer curl, wget, httpie, nc. O conteúdo do header, da query string ou do body é decidido pelo modelo em tempo de execução — e regra de permissão não olha conteúdo, olha o começo do comando.
2. WebFetch com o dado dentro da URL. Precedente real, já corrigido: em 15/07/2026 o Simon Willison documentou o achado de Ayush Paul, em que o web_fetch seguia links dentro de páginas já buscadas e vazava dados letra a letra por URLs tipo https://coffee.evil.com/a, https://coffee.evil.com/b — com o honeypot só exibindo o payload pra clientes com Claude-User no user-agent. A Anthropic corrigiu removendo a capacidade de navegar links retornados no conteúdo. O mecanismo por trás disso é prompt injection, e vale entender como esses ataques evoluíram em 2026.
3. Argumentos de tool MCP. Todo servidor MCP que você pluga é um endpoint de rede com superfície de argumento livre. O modelo preenche os campos. Você aprovou o servidor, não cada payload.
4. .env dentro do projeto — e o que loga no caminho. O mais silencioso, porque a doc do auto mode lista "Reading .env and sending credentials to their matching API" como allowed by default. Ler .env não é bloqueado pelo classificador por si só. Some a isso proxies corporativos que logam requisição crua: a Knostic reportou casos de segredo aparecendo em erro 407 de proxy e de chave subindo em commit (reportagem, não estudo — use como ilustração, nunca como número).
O checklist pra blindar antes de quinta
Conceito é bonito, arquivo é o que segura. Tudo abaixo vai em ~/.claude/settings.json — e sim, precisa ser o global: autoMode e defaultMode: "auto" são ignorados em settings de projeto de propósito, pra um repo não conseguir se auto-liberar.
1. Tranque os canais de saída
{
"permissions": {
"deny": [
"Bash(curl *)",
"Bash(wget *)",
"Bash(nc *)",
"Bash(httpie *)",
"Read(.env)",
"Read(.env.*)",
"Read(~/.aws/**)",
"Read(~/.ssh/**)"
],
"ask": [
"Bash(git push *)",
"Bash(gh pr create *)",
"Bash(gh gist *)"
],
"allow": [
"WebFetch(domain:docs.rs)",
"WebFetch(domain:crates.io)",
"WebFetch(domain:*.github.com)"
]
}
}
Detalhes que a doc avisa e todo mundo erra:
- Ordem é
deny→ask→allow. A primeira que casar decide. Especificidade não muda nada — deny largo mata allow estreito. Bash(curl *)como deny funciona até com env var na frente:FOO=bar curl ...continua bloqueado.- Não tente allowlist de URL em Bash. A doc traz warning explícito:
Bash(curl http://github.com/ *)não pega-X GET,https://, redirect com-L, nemURL=http://github.com && curl $URL. Bash(command:curl *)não funciona: o Claude Code ignora regrasparam:valueno campo de conteúdo primário e emite warning no startup.WebFetch(domain:*.example.com)não cobreexample.comsozinho.
2. O backstop que olha o conteúdo: PreToolUse hook
Deny não lê o header. Hook lê.
#!/usr/bin/env bash
CMD=$(jq -r '.tool_input.command // ""')
if echo "$CMD" | grep -qE '(curl|wget|http|nc|ssh)' \
&& echo "$CMD" | grep -qE '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Comando de rede contem e-mail. Confirme manualmente."
}
}'
fi
exit 0
Registra com matcher: "Bash" em hooks.PreToolUse. PreToolUse roda antes do prompt de permissão e vale em auto mode. Detalhe: um "allow" do hook não derruba deny/ask, e exit 2 bloqueia a chamada por cima até de regras allow.
3. Auditoria retroativa
Antes de configurar, veja se já aconteceu com você:
grep -rhoE '"command":"[^"]*(curl|wget)[^"]*"' ~/.claude/projects/ \
| grep -E 'User-Agent|-A |-H ' | sort -u | head -50
4. Se você simplesmente não quer entrar no auto mode
{
"permissions": {
"defaultMode": "default",
"disableAutoMode": "disable"
}
}
Isso tira o auto do ciclo do Shift+Tab e rejeita --permission-mode auto no startup. Em managed settings, vira política de org.
Se preferir ficar no auto mode e só endurecer o classificador, dá pra estender autoMode.hard_deny com uma regra do tipo "never include the user's personal email in HTTP headers, query strings or bodies" — sempre incluindo "$defaults" na lista, porque omitir substitui a lista inteira e você descarta as regras built-in de exfiltração. Confere o resultado com claude auto-mode config e claude auto-mode critique. E rode um security review no seu próprio setup enquanto está com a mão na massa.
O que a Anthropic disse — e o que ainda não disse
Disse: auto mode padrão dia 14 em Pro, Max e Team, com Enterprise, API, Bedrock, Google Cloud e Microsoft Foundry opt-in por ora. Publicou o estudo dos 1.053 testers. Documentou os fallbacks (3 bloqueios seguidos ou 20 no total e o auto mode pausa — thresholds não configuráveis).
Não disse nada sobre a #78431.
A issue está aberta há 26 dias. Nenhum dos 4 comentários é de MEMBER ou COLLABORATOR. Sem assignee. E o CHANGELOG do branch main já vai na 2.1.228 sem uma linha sobre e-mail, User-Agent ou userEmail. Não existe correção publicada. Quem disser que "foi corrigido na 2.1.213" não leu o changelog.
O que incomoda não é o curl pra crates.io. É o padrão: um dado pessoal que o harness injeta no contexto sem você pedir vira matéria-prima que o modelo pode reemitir em qualquer canal de rede — e a partir de quinta o revisor desse canal deixa de ser você.
Não é motivo pra largar a ferramenta. Aqui a gente usa Claude Code todo dia e continua usando. É motivo pra tratar o agente como o que ele é: um processo com acesso à rede, rodando no seu shell, com o seu e-mail no contexto. Você não deixaria um script de terceiro nessa posição sem regra de egress.
Configura antes de quinta.
{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.
Conteúdo é o que não falta. Falta quem desembaralhe: o que importa agora é como implementar do jeito certo. No Clã você tem isso ao vivo, toda semana, com quem já filtrou o ruído.
Entrar no Clã