Secret-Caches wandern ins Profil-Root: das Sandbox-Loch, das ein Ordner-Umbenennen aufreißt

Du hast Hermes mit Bitwarden verbunden, damit es das Datenbank-Passwort selbst holt, statt dass du es jedes Mal eintippst. Vorsichtig wie du bist, hast du das Ganze in eine Sandbox gepackt und cache/bws_cache.json als gesperrten Pfad markiert – die Datei enthält schließlich den entschlüsselten Klartext-Cache der Schlüssel.
Dann stellt sich heraus, dass die Sperre mit einem einzigen Handgriff fällt: Benenne den Ordner cache/ in cache2/ um, und die blockierte Datei reist mit. Liest du sie am neuen Pfad, erkennt der Schutz sie nicht mehr.
Das ist kein Versehen einer einzelnen Person, sondern eine Lehrbuch-Diskrepanz der Grenzen: Die Sandbox sperrt per Pfad, während der Elternordner dieses Pfads im Schreibbereich des Agenten liegt. Am 2026-10-31 hat Hermes die vier Credential-Cache-Dateien an die Spitze des Profil-Homes verschoben und damit die Umgehung beseitigt, statt sie zu überpflastern.
Das Problem war nicht „zu flach versteckt“, sondern „in einem umbenennbaren Ordner versteckt“
Das lohnt sich richtig zu verstehen, denn die Lehre überlebt den Bug.
Unter Windows blockiert die MXC-Sandbox (die das OpenShell-Plugin nutzt) Dateien über deniedPaths. Dieser Mechanismus setzt voraus, dass die gesperrte Datei direkt im freigegebenen Home liegt. Liegt sie in einem Unterordner, und der Agent darf diesen Unterordner anlegen, beschreiben und umbenennen, ist die Sperre reine Dekoration:
- Die Sandbox sagt,
home/cache/bws_cache.jsondarf nicht gelesen werden. - Der Agent hat Schreibzugriff auf
home/cache/und benennt das Verzeichnis inhome/cache-old/um. - Die Datei wandert mit ihrem Verzeichnis: Sie ist jetzt
home/cache-old/bws_cache.json. - Dieser Pfad steht nicht auf der Sperrliste. Lesen. Fertig.
Der Pull Request sagt es unverblümt: Die Umgehung funktioniert auf MXC 1.0.0 und 1.0.1, so gemessen. Das frühere Versprechen – „dieser Pfad ist gesperrt“ – übersteht die Bedingung „die gesperrte Datei liegt in einem beschreibbaren Unterverzeichnis“ also nicht, und alle vier Credential-Caches erfüllten diese Bedingung.
Die Schlussfolgerung ist schlicht: Mit einer längeren Sperrliste lässt sich das nicht beheben. Die Dateien dürfen nicht länger in einem beschreibbaren Unterverzeichnis liegen.
Wohin die vier Dateien gewandert sind
| Was drin steckt | Alter Pfad (in einem beschreibbaren Unterverzeichnis) | Neuer Pfad (Spitze des Profil-Homes) |
|---|---|---|
| Bitwarden-Klartext-Cache | cache/bws_cache.json |
bws_cache.json |
| Verschlüsselter Bitwarden-Cache | cache/bws_cache.enc.json |
bws_cache.enc.json |
| 1Password-Cache | cache/op_cache.json |
op_cache.json |
| Photon-Sidecar-Record (Port, Token, PID) | runtime/photon-sidecar.json |
photon-sidecar.json |
Die Dateinamen sind unverändert; geändert hat sich nur die Verzeichnisebene. Du kannst diese Dateien nicht durch Umbenennen eines Ordners verschieben, weil es keine Dateien in einem Ordner sind – sie sind direkte Kinder des Homes selbst, und eine Sandbox, die sie sperrt, sperrt genau diesen Pfad.
Eine altbekannte Lücke wurde im selben Durchgang geschlossen: Der 1Password-Cache war zuvor von keiner Prüfung abgedeckt. Die Änderung ist also nicht nur ein Umzug; die vier Namen stehen jetzt in einer einzigen gemeinsamen Liste (SECRET_CACHE_FILES in hermes_cli/home_data_layout.py), und jede Stelle, die wissen muss „diese Dateien sind Credentials“, liest diese eine Liste.
Die alten Kopien: ungelesen gelöscht
Die naheliegende Frage nach dem Upgrade ist, was mit cache/bws_cache.json passiert.
Sie wird bei der ersten Nutzung gelöscht, ohne gelesen zu werden. Der Grund ist einfach: Dieser Pfad liegt in einem Verzeichnis, das der Agent beschreiben kann, sein Inhalt ist also nicht mehr vertrauenswürdig. Ihn zu lesen hieße, möglicherweise manipulierten Daten wieder Einlass zu gewähren. Die Löschung ist idempotent, und die nächste Bitwarden- oder 1Password-Nutzung holt die Daten einfach neu.
Der Preis ist winzig, weil alle vier Caches regenerierbar sind:
- Bitwarden- und 1Password-Cache: höchstens ein zusätzlicher Abruf nach dem Upgrade.
- Der Photon-Sidecar-Record: wird beim nächsten Neustart des Gateways neu aufgebaut.
Es gibt einen ehrlichen Sonderfall. Ein Profil, das seine Bitwarden- oder 1Password-Quelle nie wieder anfasst, behält die alte Datei unter cache/, ungelesen. Sie ist weiterhin von jeder Prüfung abgedeckt, weil die Prüfliste auch die Altpfade enthält. Ein Sandbox-Plugin kann diese Altpfade löschen, bevor es eine Sandbox startet – das OpenShell-Plugin macht genau das.
Die Prüfungen, die mitgewandert sind
Der Umzug ist der leichte Teil. Der schwierige Teil ist jede Stelle, die den alten Ort vorausgesetzt hat. Diese Änderung hat aktualisiert:
- Die Liste der Credential-Pfade (
PROFILE_CREDENTIAL_PATHS): profilbezogene Sicherheitsprüfungen kennen die vier neuen Namen. - Die Datei-Sicherheitsschicht (
agent/file_safety): Lese- und Schreibsperren, nicht nur Lesen. - Die Media-Delivery-Sperrliste des Gateways: damit eine Credential-Datei nicht über einen Anhang oder einen Media-Pfad herausgereicht werden kann.
- Die Files-API des Dashboards: Die vier Namen sind versteckte Namen und tauchen im Datei-Browser nie auf.
- Backups: Backups überspringen die vier Namen auf oberster Ebene. Das ist wichtig – ein Credential-Cache soll nicht per Backup auf eine andere Maschine reisen.
- Die
.gitignoreder Flat-Installation: Die vier Namen auf oberster Ebene werden ignoriert, damit sie nicht versehentlich committet werden.
Die Designentscheidung dahinter ist nachahmenswert: nicht „einen Sonderfall hinzufügen“, sondern „eine Liste zur einzigen Wahrheitsquelle machen“. Kommt später ein weiterer Credential-Store dazu, greift jede Prüfung automatisch – deutlich verlässlicher, als ihn an sechs Stellen auszuschreiben.
Was du nach dem Upgrade siehst
~/.hermes/bws_cache.json,~/.hermes/op_cache.jsonund Verwandte erscheinen an der Spitze des Homes (oder unter~/.hermes/profiles/<name>/, wenn du mehrere Profile fährst).- Bei der ersten Bitwarden- oder 1Password-Nutzung verschwinden die alten Kopien unter
cache/und der neue Cache erscheint am neuen Pfad. - Backups enthalten diese Dateien nicht mehr.
- Die Dateiliste des Dashboards zeigt sie nicht.
- Innerhalb einer Sandbox verschiebt ein umbenanntes Unterverzeichnis sie nicht mehr.
Wenn du ein Skript hast, das cache/bws_cache.json direkt liest, braucht es den neuen Pfad. Das ist eine brechende Änderung – aber was sie bricht, ist genau der unsichere Ort.
Kannst du es heute schon nutzen
Die Änderung ist am 2026-10-31 auf main gelandet (PR #146715, mit Label type/security) und mit v0.22.6 (2026-11-02) in ein Release gekommen – nach dem Update über Installer oder hermes update liegen die Caches im Profil-Root.
Bis zur Auslieferung gilt: Wenn du nicht vertrauenswürdigen Code durch die MXC-Sandbox laufen lässt – besonders unter Windows mit dem OpenShell-Plugin –, dann behandle „ich habe den Cache-Pfad in deniedPaths eingetragen“ nicht als Sicherheitsgarantie. Der Umbenennungstrick oben hebelt sie aus. Die belastbare Antwort ist, hochwertige Credentials und nicht vertrauenswürdigen Sandbox-Code nicht im selben Profil zu halten.
Für den größeren Zusammenhang, wie Hermes mit Credentials umgeht, sind zwei Begleitartikel nützlich: wie Schlüssel verschlüsselt werden und wo der Keychain-Kompromiss liegt und wie Secrets auf dem Weg in Logs und Nachrichten geschwärzt werden. Dort geht es darum, wie Schlüssel gespeichert werden und wie sie lecken; hier geht es darum, wo die Datei mit ihnen liegt.