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

Der Hook erreichte das Modell nie

Am 31. August hat Token Security auf The Hacker News die neuen Compliance-API-Endpunkte von Anthropic für lokale Claude-Code-Sitzungen durchgesprochen. Sie sind eine echte Verbesserung, und der Text ist präzise darin, wo das Transkript aufhört: Hooks, die feuern, bevor ein Tool läuft, Dateien auf der Platte, Prozesse außerhalb einer Sitzung, alles, was über Bedrock oder Vertex läuft. Der npm-Wurm der vergangenen Woche hat sein ganzes Leben in dieser Lücke verbracht. Bromure Agentic Coding zapft die Leitung zwischen der VM und allem anderen an, damit die Aufzeichnung das erfasst, was passiert ist, und nicht das, was jemand dem Modell gesagt hat.

Ein Transkript kann nur enthalten, was jemand dem Modell gesagt hat. Die interessante Hälfte einer Agenten-Sitzung ist die, die niemand ausspricht.

Den größten Teil dieses Jahres über hatte eine Entwicklungsleitung, die wissen wollte, was Claude Code auf einem Laptop getrieben hatte, zwei Möglichkeiten: den Scrollback der Entwicklerin lesen, oder einen Wrapper von Drittanbietern kaufen. Anthropics Compliance-Endpunkte deckten claude.ai und Claude Desktop ab, und Claude Code kaum.

Das änderte sich am 11. August. Anthropic lieferte drei Compliance-API-Endpunkte für lokale Sitzungen aus: einer listet Sitzungen auf, einer holt die Metadaten einer Sitzung, und der dritte zieht das vollständige Transkript von GET /v1/compliance/apps/sessions/local/{session_id}/messages. Am 31. August veröffentlichte Token Security einen Durchgang durch das, was sie liefern auf The Hacker News.

Token Security hat den Beitrag gesponsert, und er bleibt einer der sorgfältigsten Berichte, die ich darüber gelesen habe, wo der Horizont eines Logs liegt.

Drei Blocktypen, und was sie abdecken

Das Transkript kommt in drei Arten von Blöcken. In den Worten des Artikels: „Was immer dem Modell mitgeteilt wird, wird in drei Blocktypen protokolliert: text, tool_use und tool_result. Zusammen decken sie Nutzer-Prompts, Bash-Kommandos, Lese- und Schreibvorgänge und sogar MCP-Kommandos ab.“

Das ist eine Menge: jedes Shell-Kommando, das das Modell gewählt hat, jede Datei, die es gelesen hat, jedes MCP-Tool, das es aufgerufen hat. Wenn Ihre Frage lautet „was hat dieser Agent am Dienstag zu tun beschlossen“, dann beantwortet das Transkript sie, und zwar von Anthropics Servern aus statt aus einer Datei auf der Maschine, die Sie gerade untersuchen.

Der Teilsatz, der die eigentliche Arbeit leistet, ist der erste: was immer dem Modell mitgeteilt wird.

Der Horizont

Vier Dinge liegen außerhalb dieser Grenze, und der Artikel benennt alle vier.

Hooks. „Hooks sind der klarste Fall: Sie laufen lokal, zwischen der Entscheidung des Modells und dem tatsächlichen Ausführen des Tools, und können verhindern, dass ein Tool ausgeführt oder ein Prompt gesendet wird.“ Ein Hook ist Code auf der Platte der Entwicklerin, der in der Lücke zwischen der Wahl einer Aktion durch das Modell und dem Eintreten dieser Aktion feuert. Das Modell erfährt nie davon, also trägt das Transkript es nie.

Platte. „Keiner von beiden sieht, was auf der Platte liegt: Konfigurationsdateien, installierte Skills und Plugins und ihre .md-Dateien (es sei denn, sie wurden in einer Sitzung benutzt), oder Prozesse, die außerhalb einer Sitzung gestartet wurden.“ Ein Skill, den Sie installieren und nie aufrufen, hinterlässt keine Spur, und ein Hintergrundprozess, den der Agent vor einer Stunde gestartet und dann vergessen hat, ebenso wenig.

Andere Modellanbieter. „Wenn Sie Claude Code auf einem Modell laufen lassen, das nicht von Anthropic ist, erhalten Sie überhaupt keine Abdeckung durch die Compliance API, denn sie protokolliert nur Interaktionen mit Anthropics Modellen. Sitzungen, die auf Bedrock, Foundry oder Google Cloud laufen, werden nicht abgedeckt.“ Die Abdeckung endet bei Anthropics Modellen, womit Codex, Gemini CLI, Grok und was Ihr Team im nächsten Quartal installiert, außen vor bleiben.

Berechtigungsentscheidungen. Die Freigabe eines gefährlichen Kommandos durch eine Entwicklerin, oder ein Bypass-Flag, das einen ganzen Prompt durchgewunken hat, landet in OpenTelemetry statt im Compliance-Transkript.

All das ist korrektes Verhalten. Ein Log, das am Modell verankert ist, hält fest, was das Modell gesehen hat. Die Frage für Ihr nächstes Security-Review ist, ob die Dinge, die Sie am dringendsten sehen müssen, auf der Modellseite dieser Linie liegen.

die Hypervisor-Grenze — Host-Proxy und virtueller Switchjedes Byte, das die VM sendet oder empfängt, aus jedem Prozess, unter jedem Agentenwas das Modell erreichtetext · tool_use · tool_resultNutzer-Promptsgewählte Bash-Kommandoserbetene Lese- und SchreibzugriffeMCP-Tool-Aufrufezwischen den beiden LinienHooks, die feuern, bevordas Tool überhaupt läuftInstall-Skripte und node-gyp,als Kinder eines KommandosTarballs, die eintreffen vonnpm, PyPI, Cargo, Mavendie eigenen ausgehendenAnfragen eines MCP-ServersProzesse, gestartet außerhalbjeder SitzungSitzungen auf Bedrock,Foundry oder VertexBeide Aufzeichnungen sind korrekt. Sie beantworten verschiedene Fragen, weil sie an verschiedenen Grenzen verankert sind.
Zwei Grenzen um dieselbe Agenten-Sitzung. Die innere ist das Modell: alles, was ihm mitgeteilt wird, steht im Transkript der Compliance API. Die äußere ist der Hypervisor: alles, was die VM sendet oder empfängt, kreuzt Bromures Proxy und virtuellen Switch. Die interessante Region ist der Raum dazwischen, in dem Hooks, zur Installationszeit erzeugte Kindprozesse, Paket-Tarballs, der eigene Verkehr von MCP-Servern und Nicht-Anthropic-Backends leben.

Der Wurm der letzten Woche lebte in dieser Lücke

Vor vier Tagen begann ein npm-Codegenerator mit mehr als 150.000 Wochen-Downloads, einen Credential-Stealer auszuliefern. Wir haben die Veröffentlichungskette am Samstag beschrieben: Ein Fremder kommentierte einen Pull Request, der Release-Workflow des Projekts las den Kommentar, ohne zu prüfen, wer ihn geschrieben hatte, und zehn signierte Versionen gingen hinaus.

Lesen Sie diese Malware noch einmal, mit dem Compliance-Transkript in der anderen Hand. Zeichnen Sie nach, wo jeder Schritt auftauchen würde.

Der Agent führt npm install aus. Das ist ein tool_use-Block, und das Transkript hat ihn. Alles danach ist ein Kindprozess.

Die erste Welle deklarierte überhaupt kein Install-Skript. Ihre Nutzlast saß in binding.gyp, der Build-Beschreibung, die node-gyp liest, in einem conditions-Feld, das node-gyp mit Python auswertet. Das Modell kam damit nie an die Reihe und kein Tool-Aufruf benennt sie: ein Python-Ausdruck in einer Build-Datei, ausgeführt als Enkel des einen Kommandos, das das Transkript als völlig gewöhnlich festgehalten hat.

Der Sweep, der folgte, lief über mehr als 150 Glob-Muster im Home-Verzeichnis — auf der Suche nach SSH-Schlüsseln, .env-Dateien, Cloud-Zugangsdaten und Registry-Tokens. Niemand hat das Modell zu irgendetwas davon gefragt.

Dann die Persistenz. In jedem Repository, das er erreichen konnte, schrieb der Wurm eine .claude/settings.json mit einem SessionStart-Hook, der jedes Mal setup.mjs ausführt, wenn eine Entwicklerin das Projekt in Claude Code öffnet. Ein Hook, auf der Platte, feuernd, bevor irgendjemand das Modell konsultiert: zwei der vier blinden Flecken in einer einzigen Datei. Der Angreifer, der sich diese Stelle ausgesucht hat, hatte mit ziemlicher Sicherheit nie das Compliance-Changelog eines Anbieters gelesen.

Das gesamte feindliche Zeitfenster dauerte drei Stunden und elf Minuten, und kein Teil davon hat je ein Modell erreicht.

Wo Bromure den Abgriff setzt

Bromure Agentic Coding betreibt jeden Workspace als eigene virtuelle Maschine auf Apple Silicon, und alles, was diese VM verlässt, geht durch einen Proxy und einen virtuellen Switch, die auf der Mac-Seite des Hypervisors leben. Der Switch leitet die Port-80- und Port-443-Flows der VM in den Proxy um, ohne eine Umgebungsvariable, die gesetzt werden müsste, und ohne irgendetwas, das der Gast abschalten könnte — die Aufzeichnung hängt also nicht davon ab, dass der Agent kooperiert, oder dass der Agent überhaupt weiß, dass der Proxy da ist.

Ab der Trace-Stufe Nur Aktivität aufwärts erhält jede Anfrage einen Metadaten-Eintrag: Zeitstempel, Host, Port, Methode, Pfad, Statuscode, Latenz, Anfrage-Bytes gemessen vor jedem Austausch von Zugangsdaten, Antwort-Bytes, welche Zugangsdaten der Proxy auf dem Weg nach draußen ersetzt hat, und eine Warnung, wenn die Anfrage ein Bearer-Token trug, das Bromure nicht ausgestellt hat. Dieser Eintrag existiert, ob die Anfrage nun vom Agenten kam, von einem postinstall-Skript, von einem MCP-Server, der sein eigenes Ding macht, oder von einem Prozess, den jemand vor drei Stunden gestartet und vergessen hat.

Das Fenster Security Timeline (Window → Security Timeline…) steht daneben und beantwortet eine andere Frage. Der Trace Inspector sagt Ihnen, was der Agent gesendet hat; die Timeline sagt Ihnen, was Bromures Engines entschieden haben. Eine chronologische Tabelle, die neueste zuerst, farbcodiert: grün für erlaubt, rot für blockiert, blau für informativ — Credential-Brokering, Firewall, Lieferkette, Guardrails, Prompt-Injection, Zugangsdaten verwendet, Upstream-TLS. Sie hält 5.000 Zeilen im Speicher. Die dauerhafte Kopie sind die verschlüsselten Sitzungs-Traces unter ~/Library/Application Support/BromureAC/traces/, mit AES-GCM versiegelt unter demselben Keychain-Schlüssel wie Ihre Workspace-Geheimnisse.

Dieselbe Installation liest sich in einem Bromure-Workspace so.

Security TimelineEngineEntscheidung20:31:02Lieferkettenpm [email protected] — blockiertVersion ist 9 Minuten alt, Schranke steht auf 2 Tage20:31:02Lieferkettenpm [email protected] — umgeschriebenInstall-Skripte entfernt, Metadaten-Hash aktualisiert20:31:07Firewallobjects.githubusercontent.com:443 tcp — blockiertkeine Regel, nicht zugeordneter Verkehr ist Verweigern20:31:09Credential-Brokeringbrm_a1b2… → paste.example — blockiertExfiltrationsversuch, VM pausiert20:31:09Guardrailsgit-receive-pack github.com — blockiertGitHub ist für diesen Workspace schreibgeschützt20:33:41Prompt-Injectionrules FLAG source=/repo/AGENTS.md
Was eine Bromure Security Timeline während der Installation aufzeichnet, die das Transkript als einen einzigen tool_use-Block gesehen hat. Jede Zeile stammt von einer Engine auf der Host-Seite, die die Leitung beobachtet, also hängt nichts davon ab, dass die Nutzlast durch das Modell läuft, und nichts davon lässt sich durch Code innerhalb der VM verändern.

Keine einzige dieser Zeilen verlangt, dass die Nutzlast durch ein Modell gegangen ist, und keine von ihnen lässt sich durch Code innerhalb der VM verändern, denn die Engines, die sie schreiben, laufen auf dem Mac, und der Gast hat keine Route zu ihnen.

Dieselben Zeilen, egal welchen Agenten Sie fahren

Ein Team standardisiert auf Claude Code. Dann bringt jemand für ein Projekt Codex mit, die Plattformgruppe leitet einen Workspace für Datenresidenz über Bedrock, und eine Forscherin fängt an, Grok laufen zu lassen. Nach dem Bericht des Artikels selbst produzieren drei dieser vier nichts in der Compliance API.

Ein Proxy, der TLS-Servernamen liest, sieht alle vier auf dieselbe Weise, und dieselben Ereignisse llm.request, tool.use, command.run, file.read und file.write kommen aus jedem von ihnen heraus — aus dem Verkehr gezogen statt von einem Anbieter gewährt. Auf einem Mac, der bei einem bromure.io-Workspace angemeldet ist, strömen sie über gegenseitiges TLS zur Organisation, neben egress.firewall für jedes Firewall-Urteil, credential.exfiltration, wenn ein Köder-Zugangsdatum zu einem Host abgeht, für den es nie ausgestellt wurde, und supply_chain.fetch für jedes Paket, das der Workspace gezogen hat. Letzteres feuert selbst dann, wenn jede Durchsetzungsebene der Lieferkette abgeschaltet ist, denn Bromure trennt Beobachten vom Blockieren. Der Strom trägt keine rohen Prompts. Er beantwortet, was der Agent getan hat, nicht, was die Entwicklerin gefragt hat.

Claude Code · Anthropicin der Compliance APIClaude Code · Bedrocknicht abgedecktCodex · OpenAInicht abgedecktGrok · xAInicht abgedecktHost-Proxy + Switchliest TLS-Servernamen,keine Konto-IDsein Ereignisstromllm.request · tool.usecommand.run · file.readegress.firewallsupply_chain.fetchcredential.exfiltration
Vier Workspaces auf vier verschiedenen Backends. Eine an Anthropics Modellen verankerte Aufzeichnung deckt den ersten ab. Eine an der Leitung verankerte Aufzeichnung deckt alle vier ab, weil sie aus dem Verkehr gewonnen und nicht von dem Anbieter gewährt wird, der die Tokens gerade liefert.

Die Zeile, mit der der Artikel endet

Der schärfste Satz des Textes lässt die Abdeckung hinter sich: „Aktivitätslogs allein können Ihnen nicht sagen, ob der Zugriff eines Agenten legitim ist.“

Das gilt für jedes Log, und genau deshalb schreiben Bromures Engines die Timeline selbst, statt die Aufgabe einem separaten Beobachter zu überlassen. Jede rote Zeile in diesem Fenster hält eine Entscheidung fest, die bereits gefallen ist. Eine Lieferketten-Zeile bedeutet ein Paket, das der Agent nie erhalten hat. Eine Firewall-Zeile bedeutet eine Verbindung, die sich nie geöffnet hat. Die Guardrails-Zeile ist ein Push, den der Host mit einem 403 abgelehnt hat und den der Agent als gewöhnlichen API-Fehler gelesen hat, und die Credential-Brokering-Zeile ist ein Köder, der nie ein echtes Geheimnis wurde, weil das echte nie in der VM war.

Sie müssen die Richtlinie immer noch selbst festlegen. Aber Sie beantworten „war dieser Zugriff legitim“ beim Konfigurieren des Workspace, nicht Wochen später beim Lesen von Zeilen.

Wohin mit Ihrem Abgriff

Wenn Sie Coding-Agenten in irgendeinem Maßstab betreiben, schalten Sie die Compliance API ein. Vor vier Wochen hatte diese Fläche fast gar keine Sichtbarkeit, und eine Woche Transkripte wird Ihnen Dinge über Ihr eigenes Team erzählen, die Sie nicht wussten.

Dann stellen Sie die zweite Frage: Was tun Sie mit einer Maschine, deren Transkript sauber aussieht? In einem Bromure-Workspace steht die Antwort schon auf dem Bildschirm. Öffnen Sie Window → Trace Inspector für die Hosts, Window → Security Timeline für die Urteile, oder führen Sie bromure-cli trace hostnames aus und lesen Sie jede Domain, die dieser Workspace seit dem Start kontaktiert hat.

Der Agent muss nichts davon erwähnen, damit es da ist. Installieren Sie Bromure Agentic Coding, öffnen Sie die Timeline, und sehen Sie sich eine Installation an.