Você colou um hermes dump pedindo ajuda — e ele levou junto a sua própria API key


É 1 da manhã, seu cron job falhou de novo, então você faz o que sempre faz: roda hermes dump, cola num thread do Discord com algumas linhas de log e pede ajuda. Meia hora depois alguém te chama no privado — “ei, sua key do OpenRouter ainda está no primeiro bloco.”

Isso não é hipotético. O hermes dump existe justamente para produzir “um resumo compacto em texto puro da sua configuração, pronto para colar no Discord/GitHub” — e a parte mais fácil de colar imprimia, ao pé da letra, a API key de cada provider de fallback. O fix (PR #127207, construído sobre #126132 e #126168) chegou à main em 2026-09-29 e transformou a redação de uma única passada no momento do upload em duas passadas: uma na geração do dump, outra na saída da máquina.

Primeiro, saiba o que você está realmente compartilhando

O Hermes tem dois caminhos de compartilhamento, e eles se confundem com facilidade:

  • hermes dump imprime um resumo de configuração feito para copiar e colar. Por padrão, mostra o estado de uma key como definida/não definida; --show-keys mostra os quatro primeiros e os quatro últimos caracteres.
  • hermes debug share empacota logs (as últimas 200 linhas por arquivo de log, por padrão), faz upload para um serviço de paste e imprime um link.

O segundo comando merece uma leitura atenta:

--lines LINES    Lines included per log file (default: 200)
--expire EXPIRE  dpaste.com fallback retention in days (minimum 1; default 1)
--local          Print the report locally instead of uploading
-y, --yes        Skip confirmation and upload (required in scripts/CI)
--no-redact      Disable upload-time secret redaction
--nous           Upload to Nous-internal storage (AWS S3), not a public paste

Para onde o bundle vai muda completamente o raio de impacto:

Destino Visibilidade Retenção Pode ser excluído
paste.rs link público excluído após 6 horas expira automaticamente
dpaste.com (fallback) link público número de dias definido em --expire (padrão 1) não pode ser excluído
--nous (S3) apenas equipe da Nous e mods na allowlist, atrás de um visualizador com login do Google 14 dias expira automaticamente

Ou seja, um paste público te dá uma janela de seis horas, e se o upload cair no fallback do dpaste o link fica no ar pelo tempo de retenção que você pediu — e você não consegue removê-lo. Decidir isso antes de apertar enter vale muito mais do que qualquer limpeza depois.

O que deu errado: str() num objeto que carregava uma key

A causa raiz é quase banal. Um bloco do dump renderizava a lista de providers de fallback como qualquer outro objeto:

overrides["fallback_providers"] = str(fallbacks)

O str() expandia obedientemente o campo api_key de cada entrada, além de qualquer credencial embutida na sua base_url (pense em https://user:token@gateway). Depois veio a segunda camada: _capture_dump() retornava o bundle sem nenhuma redação — a redação no momento do upload só passava pelos snapshots de log, então a seção de configuração viajava nua.

Você pode verificar um bundle que já tem em mãos com um único grep (só não rode isso num canal público):

hermes dump | grep -n -i "api_key\|base_url\|token\|signature"

Se você vir um valor api_key: sk-... completo em vez de ***, esse bundle não é seguro para publicar.

Depois do fix: duas passadas forçadas e três formatos que antes escapavam

O patch faz três coisas, e cada uma explica por que colar voltou a ser seguro.

Um: o dump é redigido no momento em que é construído. Entradas de providers de fallback agora passam primeiro por mascaramento em nível de campo e depois por uma passada de texto forçada, com regras estritas de credenciais em URL ativadas:

overrides["fallback_providers"] = redact_sensitive_text(
    str(_mask_fallback_keys(fallbacks)), force=True, redact_url_credentials=True
)

Dois: a fronteira de upload redige de novo, por conta própria. _capture_dump() agora força a redação do dump e respeita --no-redact — então, mesmo que quem chama esqueça, o bundle é conferido mais uma vez antes de sair. Keys de assinatura de nuvem também entraram no escopo: o X-Goog-Signature do GCS, o sig do SAS do Azure e o X-Amz-Signature agora contam como credenciais de URL.

Três: o mascaramento em nível de campo fecha três pontos cegos da redação de texto. Esse é o ponto sutil, e o mais útil de entender. As regras de texto sozinhas deixavam passar três formatos de api_key:

  • uma key numérica sem aspas (um inteiro YAML, não uma string);
  • uma key escrita como mapping em vez de escalar;
  • uma key que já continha ***, que o redator tratava como já mascarada.

Daí a ordem: mascarar pelo nome do campo primeiro, depois transformar as entradas em texto. Inverta a ordem e você ainda vaza.

O que fazer na sua própria máquina

Três hábitos que só passaram a ser confiáveis depois desse patch:

  1. Prefira --nous a um paste público. Quando alguém precisa ler seus logs, hermes debug share --nous os coloca num armazenamento que exige login para visualizar e se apaga depois de 14 dias. Recorra a um paste público só quando a outra pessoa não tem acesso interno, e aceite a janela de seis horas.
  2. Não use --no-redact por descuido. O significado é “não redigir antes do upload”, e o comando imprime um banner de aviso dizendo isso. Use só quando você tiver revisado o conteúdo linha por linha e realmente precisar dos bytes crus (por exemplo, caçando um prefixo de token que o mascaramento escondeu).
  3. Cole o dump em issues, nunca o config.yaml. O dump foi feito para informar definido/não definido; o arquivo de config carrega tudo. É a mesma regra que detalhamos no guia de exportação de sessão: a redação num caminho de exportação ou compartilhamento é o padrão, e a única coisa que você precisa fazer é não desligá-la.

Vale notar: --show-keys também não “mostra suas keys” — ele exibe os quatro primeiros e os quatro últimos caracteres para você confirmar qual key está em uso, não para copiá-la.

Checando sua própria instalação

Se você compartilhou um bundle antes do fim de setembro, dois minutos de verificação custam pouco:

hermes --version                          # v0.21.5 ou mais recente; a main já traz o fix
hermes dump | grep -c "api_key: \*\*\*"   # espere um valor maior que 0, ou seja, o mascaramento por campo está ativo

Se o primeiro comando reportar um build mais antigo, atualize e confira de novo. E se um link público do dpaste já está por aí, o único remédio real é rotacionar aquela key no provider — que é exatamente por que olhar antes de colar vale mais do que qualquer patch.

Para a maquinaria em volta — espelhos de sessão, regras de egress de chat de plataforma e chat de bot — veja o artigo sobre as faixas de redação; a lista completa de flags está em hermes dump e hermes debug.

A versão curta

  • A lista de providers de fallback no hermes dump imprimia valores de api_key e credenciais dentro da base_url, por causa de uma chamada str() somada a um caminho de dump sem redação.
  • Agora existem duas passadas forçadas: uma quando o dump é gerado (mascaramento por campo mais regras estritas de credenciais em URL), outra na fronteira de upload (ciente de --no-redact).
  • Os três formatos que a redação de texto deixava passar — keys numéricas, keys em mapping, keys contendo *** — estão cobertos pelo mascaramento por nome de campo primeiro.
  • Prefira --nous (privado, 14 dias) para logs compartilhados; pastes públicos te dão seis horas, e o fallback do dpaste não pode ser excluído.
  • --no-redact significa “abrir mão da proteção”, não “mais detalhe”. Cole o dump, não o seu arquivo de config.