Vous avez collé un dump hermes pour obtenir de l'aide — et il transportait votre propre clé API

Il est 1 h du matin, votre tâche cron a encore échoué, alors vous faites ce que vous faites toujours : lancer hermes dump, le coller dans un fil Discord avec quelques lignes de log, et demander de l’aide. Une demi-heure plus tard, quelqu’un vous écrit en privé : votre clé OpenRouter est encore dans le premier bloc.
Ce n’est pas un cas d’école. hermes dump existe justement pour produire un résumé compact en texte brut de votre configuration, copiable-collable dans Discord ou GitHub — et la partie la plus facile à coller affichait mot pour mot la clé API de chaque provider de fallback. Le correctif (PR #127207, bâti sur les #126132 et #126168) a été fusionné sur main le 2026-09-29 et a fait passer la redaction d’une seule passe au moment de l’upload à deux passes : une là où le dump est généré, une là où il quitte la machine.
D’abord, sachez ce que vous partagez vraiment
Hermes propose deux chemins de partage, et il est très facile de les confondre :
hermes dumpaffiche un résumé de configuration destiné au copier-coller. Par défaut, il indique si une clé est définie ou non ;--show-keysmontre les quatre premiers et les quatre derniers caractères.hermes debug shareregroupe les logs (200 dernières lignes par fichier de log par défaut), les téléverse vers un service de paste et affiche un lien.
La seconde commande mérite une lecture attentive :
--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
L’endroit où le bundle atterrit change complètement l’ampleur des dégâts :
| Destination | Visibilité | Conservation | Suppression |
|---|---|---|---|
| paste.rs | lien public | supprimé après 6 heures | expiration automatique |
| dpaste.com (fallback) | lien public | nombre de jours fixé par --expire (1 par défaut) |
impossible |
--nous (S3) |
réservé à l’équipe Nous et aux modérateurs autorisés, derrière une visionneuse avec connexion Google | 14 jours | expiration automatique |
Un paste public vous laisse donc une fenêtre de six heures, et si l’upload bascule sur dpaste, le lien reste en ligne pendant toute la durée de conservation demandée — et vous ne pouvez pas le supprimer. Trancher la question avant d’appuyer sur Entrée vaut bien plus que n’importe quel nettoyage après coup.
Ce qui a mal tourné : str() sur un objet contenant une clé
La cause racine est presque banale. Un bloc du dump rendait la liste des providers de fallback comme n’importe quel autre objet :
overrides["fallback_providers"] = str(fallbacks)
str() dépliait consciencieusement le champ api_key de chaque entrée, ainsi que tout identifiant intégré à son base_url (pensez https://user:token@gateway). Puis venait la seconde couche : _capture_dump() renvoyait le bundle sans aucune redaction — celle-ci ne s’appliquait qu’aux instantanés de logs, si bien que la section de configuration voyageait à nu.
Vous pouvez vérifier un bundle que vous détenez déjà avec un simple grep (à condition de ne pas le lancer dans un canal public) :
hermes dump | grep -n -i "api_key\|base_url\|token\|signature"
Si vous voyez une valeur complète de type api_key: sk-... au lieu de ***, ce bundle ne peut pas être publié.
Après le correctif : deux passes forcées et trois formes qui passaient entre les mailles
Le correctif fait trois choses, et chacune explique pourquoi coller un dump est redevenu sûr.
Un : le dump est expurgé au moment de sa construction. Les entrées de providers de fallback passent d’abord par un masquage au niveau des champs, puis par une passe de texte forcée avec les règles strictes sur les identifiants d’URL activées :
overrides["fallback_providers"] = redact_sensitive_text(
str(_mask_fallback_keys(fallbacks)), force=True, redact_url_credentials=True
)
Deux : la frontière d’upload applique elle-même une nouvelle redaction. _capture_dump() force désormais la redaction du dump et respecte --no-redact — ainsi, même si un appelant l’oublie, le bundle est vérifié une fois de plus avant de partir. Les clés de signature cloud entrent elles aussi dans le périmètre : X-Goog-Signature de GCS, sig d’Azure SAS et X-Amz-Signature comptent tous comme identifiants d’URL.
Trois : le masquage au niveau des champs comble trois angles morts de la redaction textuelle. C’est le point le plus subtil, et le plus utile à comprendre. Les règles textuelles seules laissaient passer trois formes de api_key :
- une clé numérique sans guillemets (un entier YAML, pas une chaîne) ;
- une clé écrite sous forme de mapping plutôt que de scalaire ;
- une clé contenant déjà
***, que le redacteur considère comme déjà masquée.
D’où l’ordre des opérations : masquer par nom de champ d’abord, puis convertir les entrées en texte. Inversez l’ordre et la fuite persiste.
Ce qu’il faut faire sur votre propre machine
Trois habitudes sur lesquelles on ne pouvait pas compter sans risque avant ce correctif :
- Préférez
--nousà un paste public. Quand quelqu’un doit lire vos logs,hermes debug share --nousles dépose dans un stockage qui exige une connexion pour être consulté et s’efface au bout de 14 jours. Ne vous rabattez sur un paste public que si votre interlocuteur n’a aucun accès interne, en acceptant la fenêtre de six heures. - N’utilisez pas
--no-redactà la légère. Sa signification est ne pas expurger avant l’upload, et la commande affiche un bandeau d’avertissement en ce sens. Réservez-le aux cas où vous avez relu le contenu ligne par ligne et avez réellement besoin des octets bruts (par exemple pour traquer un préfixe de token que le masquage a caché). - Collez le dump dans les issues, jamais
config.yaml. Le dump est conçu pour indiquer si une valeur est définie ou non ; le fichier de configuration, lui, contient tout. C’est la même règle que celle détaillée dans le guide d’export de session : la redaction sur un chemin d’export ou de partage est le comportement par défaut, et la seule chose à faire est de ne pas la désactiver.
À noter : --show-keys n’affiche pas vos clés non plus — il montre les quatre premiers et les quatre derniers caractères, de quoi confirmer quelle clé est utilisée, pas de quoi la copier.
Vérifier votre propre installation
Si vous avez partagé un bundle avant la fin septembre, deux minutes de vérification ne coûtent pas cher :
hermes --version # v0.21.5 ou plus récent : le correctif est déjà sur main
hermes dump | grep -c "api_key: \*\*\*" # attendu > 0, autrement dit le masquage par champ est actif
Si la première commande renvoie une version plus ancienne, mettez à jour puis vérifiez de nouveau. Et si un lien dpaste public circule déjà, le seul vrai remède est de faire tourner cette clé chez le provider — raison de plus pour regarder avant de coller plutôt que de compter sur un correctif.
Pour la machinerie qui entoure tout cela — miroirs de session, règles de sortie du chat de plateforme et du bot-chat — voir l’article sur les voies de redaction ; la liste complète des options se trouve sur hermes dump et hermes debug.
En bref
- La liste des providers de fallback dans
hermes dumpaffichait les valeursapi_keyet les identifiants contenus dansbase_url, à cause d’un appelstr()et d’un chemin de dump non expurgé. - Il existe désormais deux passes forcées : une à la génération du dump (masquage des champs plus règles strictes sur les identifiants d’URL), une à la frontière d’upload (tenant compte de
--no-redact). - Les trois formes manquées par la redaction textuelle — clés numériques, clés en mapping, clés contenant
***— sont couvertes par le masquage par nom de champ appliqué en premier. - Préférez
--nous(privé, 14 jours) pour les logs partagés ; un paste public vous laisse six heures, et le repli dpaste ne peut pas être supprimé. --no-redactsignifie renoncer à la protection, pas plus de détails. Collez le dump, pas votre fichier de configuration.