~/beer-and-code
▪ próximo evento Workshop: Loop Engineering — Pare de Ser o Operador do Agente · 19 Ago · 19h (horário de Brasília) — duração de 2 a 4 horas, ao vivo via Google Meet garantir vaga
~ / noticias / claude-code-vazando-email-curl-user-agent $
Notícias

Claude Code vazando email no curl — e o Auto Mode vira padrão dia 14

LS Lucas Souza · · 11 min de leitura
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 curl com o e-mail real do usuário no header User-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.

▪ Clã Beer and Code

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 é denyaskallow. 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, nem URL=http://github.com && curl $URL.
  • Bash(command:curl *) não funciona: o Claude Code ignora regras param:value no campo de conteúdo primário e emite warning no startup.
  • WebFetch(domain:*.example.com) não cobre example.com sozinho.

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.

Lucas Souza
Escrito por
Lucas Souza

{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.

▪ Clã Beer and Code

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ã
Conheça o Clã Beer and Code
tocando