Du hast einen hermes dump zum Helfen eingefügt — und darin steckte dein eigener API-Key


Es ist 1 Uhr nachts, dein cron-Job ist schon wieder fehlgeschlagen, also machst du, was du immer machst: hermes dump ausführen, das Ganze mit ein paar Logzeilen in einen Discord-Thread einfügen und um Hilfe bitten. Eine halbe Stunde später schreibt dir jemand eine DM — „hey, dein OpenRouter-Key steht noch im ersten Block.“

Das ist kein hypothetischer Fall. hermes dump existiert genau dafür, „eine kompakte Klartext-Zusammenfassung deines Setups zu erzeugen, die sich in Discord/GitHub kopieren lässt“ — und genau der Teil, der am einfachsten einzufügen war, hat früher den API-Key jedes Fallback-Providers im Klartext ausgegeben. Der Fix (PR #127207, aufgebaut auf #126132 und #126168) ist am 2026-09-29 auf main gelandet und hat die Redaktion von einem einzigen Durchlauf beim Upload auf zwei Durchläufe umgestellt: einen bei der Erzeugung des dumps, einen beim Verlassen des Rechners.

Zuerst: Wissen, was du tatsächlich teilst

Hermes kennt zwei Wege zum Teilen, und sie verschwimmen leicht miteinander:

  • hermes dump gibt eine Konfigurationszusammenfassung aus, die zum Kopieren gedacht ist. Standardmäßig zeigt sie den Zustand eines Keys als gesetzt/nicht gesetzt an; --show-keys zeigt die ersten und letzten vier Zeichen.
  • hermes debug share packt Logs zusammen (standardmäßig die letzten 200 Zeilen pro Logdatei), lädt sie zu einem Paste-Dienst hoch und gibt einen Link aus.

Der zweite Befehl verdient einen genauen Blick:

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

Wohin das Bundle gelangt, verändert den Schadenradius vollständig:

Ziel Sichtbarkeit Aufbewahrung Löschbar
paste.rs öffentlicher Link nach 6 Stunden gelöscht läuft automatisch ab
dpaste.com (Fallback) öffentlicher Link Anzahl der Tage aus --expire (Standard 1) kann nicht gelöscht werden
--nous (S3) nur Nous-Mitarbeiter und allowlistete Mods, hinter einem Viewer mit Google-Login 14 Tage läuft automatisch ab

Ein öffentlicher Paste gibt dir also ein Fenster von sechs Stunden, und wenn der Upload auf dpaste zurückfällt, bleibt der Link so lange bestehen, wie du es bei der Aufbewahrung angefordert hast — und du kannst ihn nicht entfernen. Das vor dem Drücken der Eingabetaste zu entscheiden, ist weit mehr wert als jede Bereinigung danach.

Was schiefging: str() auf einem Objekt mit einem Key

Die Ursache ist fast banal. Ein Block im dump hat die Liste der Fallback-Provider wie jedes andere Objekt gerendert:

overrides["fallback_providers"] = str(fallbacks)

str() hat brav das api_key-Feld jedes Eintrags mit expandiert, dazu alle in seiner base_url eingebetteten Zugangsdaten (denk an https://user:token@gateway). Dann kam die zweite Ebene: _capture_dump() hat das Bundle ganz ohne Redaktion zurückgegeben — die Redaktion beim Upload lief nur über die Log-Snapshots, also reiste der Konfigurationsabschnitt nackt.

Du kannst ein Bundle, das du schon hast, mit einem einzigen grep prüfen (führe ihn nur nicht in einem öffentlichen Kanal aus):

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

Wenn du einen vollständigen api_key: sk-...-Wert siehst statt ***, ist dieses Bundle nicht sicher zu veröffentlichen.

Nach dem Fix: zwei erzwungene Durchläufe und drei Formen, die früher durchgerutscht sind

Der Patch macht drei Dinge, und jedes einzelne erklärt, warum das Einfügen wieder sicher ist.

Erstens: Der dump wird schon bei seiner Erzeugung redigiert. Einträge von Fallback-Providern durchlaufen jetzt zuerst eine Maskierung auf Feldebene und dann einen erzwungenen Textdurchlauf mit strikten Regeln für URL-Zugangsdaten:

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

Zweitens: Die Upload-Grenze redigiert noch einmal eigenständig. _capture_dump() erzwingt jetzt die Redaktion des dumps und berücksichtigt --no-redact — selbst wenn ein Aufrufer es vergisst, wird das Bundle vor dem Verlassen noch einmal geprüft. Cloud-Signatur-Keys sind jetzt ebenfalls erfasst: GCS X-Goog-Signature, Azure SAS sig und X-Amz-Signature zählen alle als URL-Zugangsdaten.

Drittens: Die Maskierung auf Feldebene schließt drei blinde Flecken der Textredaktion. Das ist der subtile Punkt und der nützlichste zum Verstehen. Textregeln allein haben drei api_key-Formen übersehen:

  • einen Key ohne Anführungszeichen, der numerisch ist (eine YAML-Ganzzahl, kein String);
  • einen Key, der als Mapping statt als Skalar geschrieben wurde;
  • einen Key, der bereits *** enthielt, was der Redaktor als schon maskiert behandelt.

Daher die Reihenfolge: zuerst nach Feldnamen maskieren, dann die Einträge in Text verwandeln. Dreh die Reihenfolge um, und es leckt weiterhin.

Was du auf deiner eigenen Maschine tun solltest

Drei Gewohnheiten, auf die man sich erst nach diesem Fix verlassen kann:

  1. Zieh --nous einem öffentlichen Paste vor. Wenn jemand deine Logs lesen muss, legt hermes debug share --nous sie in einen Speicher, der zum Ansehen ein Login verlangt und sich nach 14 Tagen selbst löscht. Greif nur dann auf einen öffentlichen Paste zurück, wenn die andere Person keinen internen Zugang hat, und akzeptiere das Fenster von sechs Stunden.
  2. Greif nicht beiläufig zu --no-redact. Seine Bedeutung ist „vor dem Upload nicht redigieren“, und der Befehl gibt einen Warnbanner aus, der genau das sagt. Benutze ihn nur, wenn du den Inhalt Zeile für Zeile geprüft hast und wirklich Rohbytes brauchst (etwa um einem Token-Präfix nachzugehen, den die Maskierung verdeckt hat).
  3. Füge den dump in Issues ein, nie config.yaml. Der dump ist darauf ausgelegt, gesetzt/nicht gesetzt zu melden; die Konfigurationsdatei trägt alles. Es ist dieselbe Regel, die wir im Leitfaden zum Session-Export ausgeführt haben: Redaktion auf einem Export- oder Share-Weg ist der Standard, und das Einzige, was du tun musst, ist, sie nicht abzuschalten.

Anzumerken: --show-keys „zeigt deine Keys“ auch nicht — es zeigt die ersten und letzten vier Zeichen, damit du bestätigen kannst, welcher Key im Einsatz ist, und nicht, um ihn zu kopieren.

Die eigene Installation kurz prüfen

Wenn du vor Ende September ein Bundle geteilt hast, sind zwei Minuten Prüfung billig:

hermes --version                          # v0.21.5 oder neuer; main trägt den Fix bereits
hermes dump | grep -c "api_key: \*\*\*"   # erwartet größer als 0, d. h. die Feldmaskierung ist aktiv

Wenn der erste Befehl einen älteren Build meldet, aktualisiere und prüfe erneut. Und wenn schon ein öffentlicher dpaste-Link draußen ist, ist die einzige echte Abhilfe, diesen Key beim Provider zu rotieren — genau deshalb ist Hinschauen vor dem Einfügen besser als jeder Patch.

Für den umgebenden Mechanismus — Session-Spiegel sowie Egress-Regeln für Platform-Chat und Bot-Chat — siehe den Artikel zu den Redaktions-Spuren; die vollständige Flag-Liste findest du unter hermes dump und hermes debug.

Die Kurzfassung

  • Die Liste der Fallback-Provider in hermes dump hat früher api_key-Werte und Zugangsdaten innerhalb von base_url ausgegeben — wegen eines str()-Aufrufs und eines nicht redigierten dump-Pfads.
  • Jetzt gibt es zwei erzwungene Durchläufe: einen bei der Erzeugung des dumps (Feldmaskierung plus strikte URL-Zugangsdaten-Regeln), einen an der Upload-Grenze (kennt --no-redact).
  • Die drei Formen, die die Textredaktion übersehen hat — numerische Keys, Mapping-Keys, Keys mit *** — werden durch die Maskierung nach Feldnamen zuerst abgedeckt.
  • Zieh --nous (privat, 14 Tage) für geteilte Logs vor; öffentliche Pastes geben dir sechs Stunden, und der dpaste-Fallback lässt sich nicht löschen.
  • --no-redact bedeutet „den Schutz aufgeben“, nicht „mehr Details“. Füge den dump ein, nicht deine Konfigurationsdatei.