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 dumpimprime 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-keysmostra os quatro primeiros e os quatro últimos caracteres.hermes debug shareempacota 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:
- Prefira
--nousa um paste público. Quando alguém precisa ler seus logs,hermes debug share --nousos 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. - Não use
--no-redactpor 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). - 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 dumpimprimia valores deapi_keye credenciais dentro dabase_url, por causa de uma chamadastr()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-redactsignifica “abrir mão da proteção”, não “mais detalhe”. Cole o dump, não o seu arquivo de config.