Zurück zu allen Beiträgen
Veröffentlicht am · von Renaud Deraison

Der Symlink verließ den Workspace, und fand nichts, was sich mitzunehmen lohnte

GhostApproval zeigte, wie ein feindliches Repository sechs KI-Coding-Assistenten dazu bringen kann, Dateien außerhalb des Ordners zu schreiben und zu lesen, in dem sie eigentlich bleiben sollten: SSH-Schlüssel pflanzen, den Shell-Start kapern und Cloud-Credentials auf der eigenen Maschine des Entwicklers lesen. Der Bug ist ein Symlink-Folge-Fehler. Weh tut er, weil der Agent auf einer Maschine voller deiner Secrets läuft. Bromure Agentic Coding ändert diese zweite Tatsache.

Ein Coding-Agent ist ein Programm, das du einlädst, Dateien auf deinem Laptop zu lesen und zu schreiben. GhostApproval ist die Geschichte dessen, was passiert, wenn ein feindliches Repository dieses Programm überzeugt, ein wenig über die Linien hinaus zu schreiben: in deine SSH-Schlüssel, deine Shell-Config, deine Cloud-Credentials. Der Bug ist alt und langweilig. Der Schaden kommt von dort, wo der Agent stand.

Am 8. Juli 2026 veröffentlichte das Research-Team von Wiz GhostApproval, einen Bericht über denselben Fehler, gefunden in sechs verschiedenen Formen in sechs populären KI-Coding-Assistenten: Amazon Q Developer, Anthropics Claude Code, Augment, Cursor, Googles Antigravity und Windsurf. Die Details unterscheiden sich je nach Produkt. Die Form nicht. Du öffnest ein Repository, vielleicht ein Tutorial, das jemand verlinkt hat, oder ein Projekt, das ein Kollege dir zum Anschauen gegeben hat, und richtest deinen Coding-Agent darauf. Irgendwo in diesem Repository liegt eine Datei, die keine Datei ist.

Eine Datei, die keine Datei ist.

Der Trick ist ein symbolischer Link, ein Symlink: ein Dateisystem-Eintrag, der aussieht wie eine Datei, aber ein Wegweiser ist, der auf einen anderen Pfad zeigt. Symlinks sind ein normales, vierzig Jahre altes Unix-Feature. Das Sicherheitsproblem, katalogisiert als CWE-61, ist fast genauso alt: Ein Programm, das einen Symlink öffnet, ohne zu prüfen, wohin er zeigt, lässt sich von einem Angreifer zu einer Datei lenken, die der Autor nie gemeint hat.

In GhostApproval liefert ein bösartiges Repository einen Symlink mit harmlos klingendem Namen, sagen wir project_settings.json. Statt Einstellungen enthält er einen Zeiger auf ~/.ssh/authorized_keys, ~/.zshrc oder ~/.aws/credentials, gelegen im Home-Verzeichnis des Entwicklers, weit außerhalb des Repository-Ordners. Ein README, oder der Nutzer, der den Anweisungen des Repos folgt, bittet den Agent dann, project_settings.json zu „aktualisieren“. Der Agent folgt dem Wegweiser, ohne aufzulösen, wohin er führt, und schreibt stattdessen in das echte Ziel.

WORKSPACE — das geklonte Repoproject_settings.jsonsieht aus wie Config — ist ein Symlink„Bitte aktualisiere project_settings.json“— das README des Repos, vom Agent befolgtWORKSPACE-GRENZEals sicher angenommen — die Annahme ist der BugHOME DES ENTWICKLERS (~) — außerhalb des Repos~/.ssh/authorized_keys~/.zshrc~/.aws/credentialsechter Host-Zugriff · echte Cloud-Keys · Shell läuft bei jedem LoginAgent folgt dem LinkCWE-451 — DER PROMPT VERSCHLEIERT, WAS GLEICH PASSIERTEchtes Ziel des Agents: ~/.ssh/authorized_keysDir gezeigt: „project_settings.json editieren? [Ja]“
So funktioniert GhostApproval. Ein geklontes Repository enthält einen als Config-Datei getarnten Symlink; er zeigt aus dem Workspace hinaus ins Home-Verzeichnis des Entwicklers. Wenn der Agent ihn editiert, landet der Schreibzugriff auf ~/.ssh/authorized_keys, ~/.zshrc oder ~/.aws/credentials. Schlimmer noch: In mehreren Produkten zeigte der Bestätigungs-Prompt den harmlosen Namen, den der Agent editieren sollte, nicht den sensiblen Pfad, den er gleich anfassen würde (CWE-451).

Zwei Dinge machen das zu mehr als einer Kuriosität. Das erste ist, was die Ziele tun. Eine Zeile an ~/.ssh/authorized_keys anzuhängen installiert den Schlüssel eines Angreifers für passwortloses SSH auf deine Maschine. In ~/.zshrc zu schreiben führt das Kommando des Angreifers jedes Mal aus, wenn du ein Terminal öffnest. Augments Agent musste nicht einmal schreiben: Nach „AWS-Keys im Projekt“ gefragt, lief er über einen Symlink hinaus zu einer Credentials-Datei und druckte die Secrets in den Chat, ganz ohne Nachfrage.

Das zweite ist ein subtileres Versagen, das Wiz als CWE-451 klassifiziert, Falschdarstellung im User-Interface. Bei Claude Code erkannte das interne Reasoning des Agents die Datei sehr wohl als Shell-Config, und der Bestätigungsdialog fragte trotzdem nur: „Diese Änderung an project_settings.json vornehmen?“ Der eine Moment, in dem ein Mensch die Gefahr hätte bemerken können, zeigte dem Menschen die falsche Information. Windsurf und Amazon Q Developer traf es schlimmer: Sie schrieben die Datei auf die Platte, bevor sie die Bestätigungs-Buttons anzeigten, sodass der Dialog eher ein Rückgängig-Prompt als ein Tor war. Der SSH-Schlüssel des Angreifers war bereits an Ort und Stelle.

Die meisten Hersteller haben ihre Variante inzwischen gefixt: Cursor in v3.0 (CVE-2026-50549), Amazon Q im Language-Server 1.69.0 (CVE-2026-12958), Google in Antigravity v1.19.6, Claude Code mit einer Warnung bei der Symlink-Auflösung. Das ist die richtige Reaktion, und du solltest die Updates einspielen. Aber das Symlink-Handling jedes einzelnen Produkts zu patchen repariert den Mechanismus und lässt unangetastet, was auf dem Spiel steht.

Was auf dem Spiel steht, bestimmt der Standort des Agents.

Jeder einzelne dieser Payloads nimmt dasselbe an: dass es sich lohnt, das Home-Verzeichnis des Entwicklers zu erreichen. Dass ~/.ssh einen Schlüssel hält, der eine echte Maschine öffnet, ~/.aws/credentials ein lebendes Cloud-Token enthält und ~/.zshrc in einer Shell läuft, die du morgen öffnen wirst. Der Symlink ist die Straße. Das Ziel ist ein Laptop mit deinem ganzen Arbeitsleben darauf.

Die meisten Angriffe auf Coding-Agents ruhen auf derselben Annahme. Der Agent ist ein fähiges, offenes Programm, das nicht vertrauenswürdigen Input liest (Repositories, Webseiten, Paket-Tarballs, Tool-Output) und Aktionen auf einer Maschine ausführt, auf der deine Credentials ein paar Verzeichnisse weiter in schlichten Dateien liegen. Härte den Agent, so viel du willst; er teilt ein Dateisystem und einen Schlüsselbund mit allem anderen, das du ausführst. Angreifer werden weiter neue Straßen bauen. Das Ziel ist das Problem.

Bromure Agentic Coding entfernt das Ziel. Der Agent, die Shells, die er spawnt, die Repositories, die er klont, und jeder Code darin laufen innerhalb einer Per-Profil-Linux-VM: einer separaten Maschine, die der Hypervisor von deinem Mac abschottet. Deine echten Credentials betreten sie nie. Warum eine Grenze einen Käfig schlägt, haben wir in warum Bromure Agentic Coding keine Sandbox ist beschrieben; GhostApproval ist ein sauberer Test dieser Idee, denn es entkommt dem Workspace-Ordner, der einen kleinen Grenze, auf die sich die Branche verlassen hat.

Agent auf deinem MacEINE MASCHINE, EIN HOME-DIRAgent + geklontes RepoSymlink → ~/.ssh/authorized_keys~/.ssh/authorized_keysECHT~/.aws/credentialsECHT~/.zshrcECHTErgebnisSSH-Key des Angreifers installiert,Cloud-Keys gelesen, Shell gekapert —auf der Maschine, an der du arbeitest.Bromure Agentic CodingPER-PROFIL-VM — WEGWERFBARAgent + geklontes RepoSymlink → ~/.ssh/authorized_keysSchreibzugriff passiert trotzdem~/.ssh/authorized_keysSTUB~/.aws/credentialsSTUB~/.zshrcGastErgebnisein Key in einem Wegwerf-Gast ergänzt,Platzhalter-Cloud-Keys exfiltriert —dein Mac hat den Raum nie betreten.
Derselbe Symlink-Ausbruch, zwei Maschinen. In einem normalen Setup läuft der Agent neben deinen echten ~/.ssh und ~/.aws, sodass das Folgen des Links lebende Schlüssel und eine Maschine erreicht, deren Übernahme sich lohnt. In Bromure läuft der Agent in einer Per-Profil-VM; der Symlink löst sich weiterhin auf und der Schreibzugriff passiert weiterhin, aber er landet in einem wegwerfbaren Gast, dessen Home-Verzeichnis nur Stubs enthält: Platzhalter-Dateien, die im öffentlichen Internet nichts bedeuten. Das Dateisystem deines Macs liegt unterhalb der Hypervisor-Linie und wird nie in die VM gemountet.

Verfolge denselben Ausbruch innerhalb der VM. Der Symlink löst sich immer noch auf (Bromure muss den Trick nie erkennen oder blockieren), und der Schreibzugriff landet immer noch auf ~/.ssh/authorized_keys. Aber diese Datei lebt im Home-Verzeichnis des Gasts, auf einer wegwerfbaren Maschine ohne Route zu deinem Mac. Der Schlüssel des Angreifers gewährt jetzt Login auf einer Maschine, die du wegwerfen wirst, und die von außen ohnehin nie erreichbar war.

Die Credential-Diebstahl-Variante ist noch antiklimaktischer. Wenn ein kompromittierter Agent über einen Symlink zu ~/.aws/credentials läuft und den Inhalt in den Chat druckt, liest er einen Stub: eine wohlgeformte Credentials-Datei, deren Schlüssel sich bei nichts authentifizieren. Echte Tokens bleiben auf dem Host, hinter einem Broker, der den Platzhalter erst im Moment eines von dir erlaubten ausgehenden Aufrufs gegen das echte Secret tauscht und es aus der Antwort wieder heraustauscht. Eine Dependency oder ein ausgetrickster Agent, der das Dateisystem nach Secrets durchkämmt, findet Attrappen.

Der Prompt, und das zweite Netz.

Bromure begegnet den zwei schärferen Kanten von GhostApproval auf verschiedenen Ebenen.

Die erste ist das Problem mit dem Bestätigungs-Prompt, CWE-451: der Dialog, der project_settings.json sagte, während der Agent wusste, dass ~/.zshrc gemeint war. Bromure lässt den Datei-Schreib-Dialog weg; Schreibzugriffe innerhalb der wegwerfbaren VM berühren eine entbehrliche Platte und brauchen keine Freigabe. Stattdessen setzt Bromure den Menschen an die echte Grenze, für zustandsverändernde Aufrufe, die die VM verlassen: ein git push, ein Datenbank-DROP, ein Cloud-Terminate. Die pausieren auf dem Host und zeigen dir die wörtliche Operation statt einer Zusammenfassung, die der Agent geschrieben hat. Es ist dasselbe Prinzip, das GhostApproval verletzte, angewandt dort, wo es zählt: Der Moment, in dem eine Entscheidung Konsequenzen außerhalb der Sandbox hat, ist der Moment, in dem ein Mensch den echten Aufruf sehen sollte.

Die zweite Kante ist die Anweisung, die den ganzen Angriff startet: ein README, das dem Agent sagt, er solle project_settings.json „aktualisieren“, was das Modell als Kontext liest und als Befehl befolgt. Bromure liest diese nicht vertrauenswürdigen Inhalte zuerst, on-device: Ein lokaler Classifier bewertet eingehende Dateien, Web-Abrufe und Tool-Output auf Anweisungen, die dort nichts zu suchen haben, und die Rules-Dateien, die ein Agent als Daueraufträge behandelt, bekommen eine strengere Prüfung. Der Classifier wird manche Formulierungen verpassen, und die Isolation besiegt diesen Angriff bereits allein; betrachte ihn als zweites Netz unter dem ersten.

Wo die Linie dich nicht rettet.

Isolation ist eine bestimmte Form, und die Form hat Kanten.

Ein Profil lebt lange, also bleibt Persistenz bestehen.

Der ~/.zshrc-Payload wird laufen, wenn sich das nächste Mal eine Shell öffnet, innerhalb der VM dieses Profils. Er läuft in einem Gast ohne Host-Schlüssel und mit nichts als Stub-Credentials, eine Shell in einem leeren Raum, aber er läuft. Wenn dich das bei einer bestimmten Aufgabe beunruhigt, führe sie in einem frischen Profil aus.

Was du mountest, exponierst du.

Die VM enthält standardmäßig nichts von dir. Wenn du absichtlich ein echtes Host-Verzeichnis in ein Profil mountest oder ein lebendes Token in den Gast einfügst, kann ein Symlink-Ausbruch es erreichen. Die Linie hält deine Secrets draußen; sie wieder hineinzulegen ist eine Entscheidung, die nur du treffen kannst.

Scope den Broker mit Absicht.

Stubs bedeuten, dass die Datei auf der Platte wertlos ist, aber der Broker hält weiterhin echte Tokens für die Aufrufe, die du erlaubst. Ein Profil, das ein Repo nur lesen muss, sollte kein Token tragen, das es veröffentlichen kann. Isolation begrenzt die Explosion; das Scoping entscheidet, wie groß sie je werden könnte.

Der Workspace war die falsche Mauer.

GhostApproval ist im Kern eine Geschichte darüber, worauf sich die Branche als Grenze geeinigt hat: den Workspace-Ordner, die Idee, dass „der Agent bleibt im Projektverzeichnis“ eine Sicherheitseigenschaft sei statt eines Defaults, den jeder Wegweiser umgehen kann. Der Symlink selbst ist ein Bug, den die Hersteller patchen können und gepatcht haben. Ziehe deine Grenze an einem Ordner, und du wirst ewig damit verbringen zu beweisen, dass kein Symlink, kein .., kein cleverer Pfad ihn je verlässt. Ziehe sie am Hypervisor, und die Frage hört auf, eine Rolle zu spielen, denn der Ort, an den der Agent entkommt, ist eine wegwerfbare Maschine, die nie etwas von dir enthielt.

Nimm die Hersteller-Patches; sie schließen ein echtes Loch. Aber das Loch tat weh, weil der Agent auf deinem Laptop stand, ein Verzeichnis von deinen Schlüsseln entfernt. Bewege den Agent von deinem Laptop herunter, und der nächste Ausbruch (es wird einen geben) kommt in einem leeren Raum an. Bromure Agentic Coding ist kostenlos, Open Source und heute verfügbar.