Zum Inhalt springen
covey

Wo liegt das Passwort, mit dem ein Agent sich beim Ticketsystem anmeldet? Die naheliegende Antwort ist eine Umgebungsvariable im Container.

Von dort taucht sie wieder auf: in jedem Absturzprotokoll, in jedem Backup des Containers, in jeder Log-Zeile, die sie versehentlich mitschreibt.

Das ist die unbequemste Frage, die man einer Agenten-Installation stellen kann. Die übliche Antwort ist der Grund, warum ein Sicherheitsteam nein sagt.

Bei covey hat ein Agent kein Passwort. Er hat eine Identität.

Eine Identität statt eines Passworts

Ein Agent legt bei jeder Anfrage seine eigene Identität vor, nicht ein geteiltes Geheimnis. Die Control Plane prüft, ob er für das Zielsystem und den angefragten Geltungsbereich berechtigt ist, gegen die ACCESS.md des Agenten und gegen die geltenden Freigaberegeln.

Erst danach tauscht sie diese Identität gegen ein Zugriffstoken: begrenzt auf ein System, einen Geltungsbereich und eine kurze Gültigkeitsdauer. Der Tausch nach RFC 8693 gegen ein Drittsystem setzt dabei voraus, dass ein externer OIDC-Provider konfiguriert ist. Die eingebaute Variante ist dabei der Normalfall — Keycloak und Vault sind optional, keine Voraussetzung — und stellt stattdessen signierte JWTs aus.

Die Begrenzung selbst gilt in beiden Fällen. Diese Entscheidung trifft die Control Plane. Nicht der Agent, nicht der Dämon.

Das Geheimnis dahinter bleibt an einer Stelle liegen

Irgendwo muss der ursprüngliche Zugang zum Zielsystem trotzdem gespeichert sein — ein GitHub-Token etwa oder ein API-Schlüssel für Zammad. Covey legt ihn verschlüsselt in einer Postgres-Spalte ab, mit AES-GCM als Verfahren und dem COVEY_MASTER_KEY als Schlüssel.

Der Schlüssel selbst steht — anders als die verschlüsselten Werte — nur in der Umgebung der Control Plane, nicht in der Datenbank. Jeder gespeicherte Wert ist zusätzlich an seine Organisation gebunden, sodass ein Chiffretext aus der einen Organisation in einer anderen keinen Klartext ergibt.

Aus der Oberfläche lässt sich ein gespeichertes Geheimnis ersetzen, aber nicht mehr anzeigen. Ein Wert, den man auslesen kann, landet früher oder später in einer Chat-Nachricht.

Ein Checkout zeigt, wie eng das sitzt

Ein Beispiel macht das konkret. Soll ein Agent einen Fehlerbericht mit einer Stelle im Code belegen, ruft er checkout auf.

Nicht die Laufzeitumgebung lädt daraufhin das Repository-Archiv, sondern der Dämon, über GET /repos/:owner/:repo/tarball/:ref, mit dem gebrokerten Token. Das Token bleibt im Arbeitsspeicher des Dämons, und es landet nie im Dateisystem der Sandbox.

Ein gewöhnliches git clone — mit einer Credential-Remote als Zugang — würde dasselbe Token dauerhaft in .git/config schreiben. Genau das vermeidet covey.

Der Dämon hält das Token, die Laufzeit sieht es nie

In jeder Sandbox läuft ein schlanker Dämon, der ein einheitliches Protokoll spricht. Er startet die eigentliche Laufzeitumgebung über einen dünnen Adapter, bei covey meist Claude Code.

inject_credentials ist eine der Nachrichten in diesem Protokoll, und sie reicht ein kurzlebiges, begrenztes Token für ein Zielsystem an den Dämon weiter.

Sie geht an den Dämon, nicht an die Laufzeit. Das Sprachmodell, das den Prompt liest und den Text schreibt, bekommt das Token nicht in seinen Kontext. Es sieht nur das Ergebnis.

Ganz verschwindet das Token damit nicht, denn der Dämon hält es, für die Dauer eines Aufrufs, in seinem Arbeitsspeicher.

Die Genauigkeit der Behauptung liegt also nicht darin, dass nichts in der Sandbox je ein Zugangsdatum berührt. Sie liegt darin, dass es nie in den Kontext des Modells gelangt und nie auf die Platte geschrieben wird.

Was eine verlorene Sandbox verliert

Wird eine Sandbox verloren oder kompromittiert, begrenzen Isolation und die kurze Lebensdauer der Rechenumgebung den Schaden. Kritischer Zustand liegt ohnehin nicht in der Sandbox.

Ein ausgeleitetes Token, das die Sandbox verlässt, ist durch seinen Geltungsbereich und seine kurze Gültigkeitsdauer eingegrenzt. Der Container selbst erbt nichts aus der Umgebung seines Hosts — er sieht nur das, was die Control Plane hineingelegt hat.

Geht die Sandbox verloren, baut covey sie aus der Konfiguration und dem persistenten Home-Verzeichnis neu auf. Ein Zugriffstoken übersteht das nicht. Keins ist dafür gedacht.

Selbst der Runner sieht das Token nicht

Eine Ebene tiefer liegt der Runner — die Maschine, die den Container tatsächlich startet. Er bekommt bei start_sandbox das COVEY_DAEMON_TOKEN des Agenten und ein Egress-Token, um beides in den Container zu reichen.

Damit könnte er im Prinzip jeden Agenten imitieren, den er hostet. Was er nicht bekommt: die gebrokerten Zielsystem-Zugangsdaten selbst. Die gehen direkt an den Dämon, am Runner vorbei.

Die Grenze liegt woanders, als man zuerst vermutet. Nicht zwischen Sandbox und Außenwelt, sondern innerhalb derselben Sandbox: zwischen dem Dämon, der ein Token kurz hält, und der Laufzeit, die es nie zu sehen bekommt.

Zurück zur Übersicht