Die Sandbox, die den Schlüssel verwahrte
Am 18. Mai 2026 hat Lasso Security zwei Angriffe gegen Nvidias NemoClaw veröffentlicht — die Sandbox, in der der autonome Coding-Agent OpenClaw läuft. Die Sandbox arbeitete genau so, wie Nvidia sie beschrieben hatte. Der Agent in der Sandbox schob trotzdem das GitHub-Token des Nutzers an einen vom Angreifer kontrollierten Pull Request, als Emoji codiert, um an GitHubs statischem Secret-Scanner vorbeizurutschen. Die interessante Frage ist nicht, ob die Sandbox kaputt ist. Sie lautet: war eine Sandbox mit einer Klartext-Credential-Datei darin überhaupt jemals eine Sandbox in einem architektonisch nützlichen Sinn — und was bedeutet die Antwort für alle, die 2026 einen Coding-Agent ausliefern.
Zwei Dinge können gleichzeitig wahr sein. Das erste ist, dass
Nvidias NemoClaw-Sandbox, die den autonomen Coding-Agent OpenClaw
in einem K3s-Cluster innerhalb eines privilegierten Docker-Containers
einkapselt, exakt so funktioniert hat, wie Nvidia es dokumentiert
hatte. Das zweite ist, dass Lasso Security am 18. Mai eine
Veröffentlichung publiziert hat, in der ein bösartiges
npm-postinstall-Script — laufend innerhalb dieser Sandbox, mit nichts
als dem, was die Sandbox laut Konfiguration erlauben sollte — das
GitHub-Token des Nutzers aus einer Klartext-Konfigurationsdatei las,
es als Emoji codierte, um GitHubs Secret-Scanner auszuhebeln, und das
Ergebnis per gh-Binary, das die Egress-Policy freundlicherweise auf
die Allowlist gesetzt hatte, an einen vom Angreifer kontrollierten
Pull Request schickte. Nvidia antwortete, das falle aus dem Scope des
Bug-Bounty-Programms heraus, mit der Begründung, die Sandbox habe
sich exakt so verhalten, wie sie konfiguriert war. Das ist, in einer
Variante, die den meisten Security-Leuten vertraut sein dürfte,
zugleich korrekt und am Punkt vorbei.
Hier ist die Geschichte in drei Sätzen. Am 18. Mai 2026 hat Lasso
Security eine
Veröffentlichung
über eine Angriffskette gegen NemoClaw publiziert, Nvidias Sandbox für
den Betrieb von OpenClaw — einem autonomen Coding-Agent, der wie
Claude Code oder der Cursor-Agent oder Codex CLI im Namen des Nutzers
npm install, gh pr create und git push ausführen darf. Die Kette
hat zwei Hälften: eine Credential-Exfiltrations-Hälfte, in der ein
bösartiges Paket /sandbox/.openclaw/openclaw.json las (eine
Klartext-Datei, die das GitHub-Token des Nutzers zusammen mit
Schlüsseln für Anthropic, OpenAI, Gemini und Nvidia-Dienste enthält),
das Token mit Hilfe einer zur Laufzeit aufgebauten Lookup-Tabelle in
eine Folge von Emojis umschrieb und die codierte Nutzlast über das
allowlistete gh-Binary in einen öffentlichen PR pushte; und eine
Persistenz-Hälfte, in der eine in einer ganz normal aussehenden
Quelldatei platzierte Prompt-Injection den Agent dazu brachte, seine
eigene SOUL.md — OpenClaws Verhaltens-Memory-Datei — mit einer
Hintertür zu überschreiben, die jede nachfolgende Session überlebt.
BDTechTalks
berichtete am selben Tag über die Offenlegung; Nvidias Antwort,
zitiert in beiden Veröffentlichungen, lautete, die Sandbox habe sich
exakt so verhalten, wie sie konfiguriert war, und die Szenarien
fielen aus dem Scope des Programms heraus.
Die Antwort von Nvidia ist in einem engen technischen Sinn richtig.
Die Sandbox ist eine Sandbox. Der K3s-Pod ist ein K3s-Pod. Die
Egress-Policy, die gh erlaubt, mit github.com zu sprechen, ist eine
Policy, die gh erlaubt, mit github.com zu sprechen. Nichts ist aus
seinen Capability-Grenzen ausgebrochen. Nichts wurde eskaliert. Der
Container ist nicht ausgebrochen. Aus Sicht der Runtime hat jedes
Byte, das die Sandbox verließ, sie über ein Binary verlassen, von dem
der Nutzer zugestimmt hatte, dass es kommunizieren darf, zu einem
Ziel, von dem der Nutzer zugestimmt hatte, dass es erreichbar sein darf.
Nur war das Byte, das die Sandbox verließ, das GitHub-Token des Nutzers, geschrieben mit Cartoon-Gesichtern.
Der langweilige Teil der Kette.
Gehen wir die Credential-Hälfte langsam durch, denn die Mechanik ist
das ganze Argument. Der Agent erhält eine Aufgabe — etwas Unauffälliges,
„Richte dieses neue Projekt anhand der GitHub-README ein" — und die
README enthält irgendwo in ihren Anweisungen einen Schritt, der auf
npm install some-helpful-package hinausläuft. Das Paket ist bösartig,
aber auf die unauffällige Art, in der mittlerweile hundert npm-Pakete
pro Woche bösartig sind: es ist ein Typosquat oder eine transitive
Abhängigkeit eines kürzlich kompromittierten Pakets, und es bringt ein
postinstall-Script mit. Das postinstall-Script tut drei Dinge, die
einzeln erlaubt sind und in Kombination katastrophal.
Es liest /sandbox/.openclaw/openclaw.json. Diese Datei liegt auf dem
Sandbox-Dateisystem; das Script läuft innerhalb der Sandbox; niemand
hat dem Dateisystem gesagt, dass es nicht lesbar sein soll, denn wie
sollte sonst der Agent selbst das GitHub-Token nutzen, wenn er die
Datei, in der das GitHub-Token wohnt, nicht lesen kann? Es extrahiert
den ghp_…-Wert.
Es lädt eine emoji_map.json, die mit dem bösartigen Paket ausgeliefert
wird und jedem alphanumerischen Zeichen ein Emoji zuordnet — eine
vollkommen gewöhnliche JSON-Datei, beim statischen Scan völlig
harmlos, die Art Datei, die ein Markdown-Formatter oder ein Chat-Client
legitim mitliefern könnte. Das Script läuft Zeichen für Zeichen durch
das Token und produziert eine Zeichenfolge wie 🍕🍔🌮🍟…, ein Emoji pro
Zeichen.
Es führt gh pr create gegen ein vom Angreifer kontrolliertes
Repository aus, mit dem Emoji-String als PR-Body. Aus Sicht der
Egress-Policy ist das gh, das mit github.com spricht, also genau
das einzige, was gh auf der Allowlist tun darf. Der PR wird angelegt.
Auf der Angreiferseite liest ein Script den PR-Body, invertiert die
Map und rekonstruiert ghp_…. GitHubs Secret-Scanner sieht den
PR-Body ebenfalls — aber GitHubs Secret-Scanner sucht nach
ghp_[A-Za-z0-9]{36}, nicht nach 🍕🍔🌮🍟.
Der Lasso-Forscher Noy Pearl formuliert es in der Offenlegung
unverblümt: „Emoji-Codierung war die Technik, die wir gewählt haben,
um GitHubs statische Scans zu umgehen" und „solange der Agent eine
Verbindung zur Außenwelt hat, kann kein statischer Mechanismus dich
vollständig schützen." Das ist der Teil, an dem man nickt und sagt:
ja, offensichtlich, du kannst kein Protokoll auf die Allowlist setzen,
das beliebige Bytes tragen kann, und dann überrascht sein, wenn
beliebige Bytes hindurchgehen. Eine L7-Allowlist, die gh erlaubt,
ist eine L7-Allowlist, die alles erlaubt, was sich in einen PR-Body
serialisieren lässt — also alles.
Die Persistenz-Hälfte — SOUL.md — ist mechanisch anders, aber
philosophisch dieselbe. OpenClaw, laut Lassos Veröffentlichung, hält
eine Verhaltens-Memory-Datei namens SOUL.md, die der Agent zu Beginn
jeder Session liest: Regeln, Systemanweisungen, gesammelter Kontext zu
den Vorlieben des Nutzers. Der Agent kann diese Datei auch schreiben,
weil die ganze Prämisse langlaufender Memory ist, dass der Agent seine
eigenen Überzeugungen aktualisieren können soll. Eine Prompt-Injection,
platziert in einer völlig normal wirkenden Quelldatei, die der Agent
im Rahmen einer Routineaufgabe verarbeitet — Lassos Beispiel ist eine
Textdatei, die einfach Anweisungen enthält, formuliert in derselben
Sprache, wie Trainingsdaten formuliert sind — bringt den Agent dazu,
eine Backdoor-Regel an SOUL.md anzuhängen. Nachfolgende Sessions
laden SOUL.md. Die Hintertür ist jetzt, in der Selbstbeschreibung
des Agents, seine Präferenz. Pearls Formulierung gegen Nvidias
„verhielt sich wie konfiguriert"-Verteidigung ist die schärfste:
„Die Sandbox verhielt sich wie konfiguriert ist ein feines Argument,
wenn das, was darin läuft, ein deterministisches Programm ist. Es
überlebt den Kontakt mit LLM-getriebenen Agents nicht, deren Verhalten
zur Laufzeit von jedem Stück Text geformt wird, das sie aufnehmen."
Ein Token in einer Datei ist ein Token in einer Datei.
Der architektonische Satz, den ich hier hinschreiben möchte, bevor ich darauf eingehe, was Bromure an irgendetwas davon ändert, lautet: ein langlebiges Secret, das als Klartext-Datei innerhalb desselben Blast Radius liegt wie der Code, den der Agent ausführt, ist für jeden Angreifer, der Code in diesem Blast Radius ausführen kann, äquivalent zu einem öffentlichen Secret. Die Sandbox ändert daran nichts. Der K3s-Pod ändert daran nichts. Die Egress-Allowlist ändert daran nichts, denn die Egress-Allowlist darf mit GitHub sprechen — und mit GitHub sprechen ist, per Design, per Nutzerwille, aus dem ganzen Grund, aus dem der Agent überhaupt existiert, derselbe Kanal, den das bösartige Paket nutzen wird.
Es gibt eine gut verstandene Lösung dafür, sie ist Jahrzehnte älter als KI-Agents, und die Security-Branche nutzt sie seit den 1990er-Jahren still und leise. Die Lösung besteht darin, das Secret auf die andere Seite einer Prozessgrenze zu legen und seine Verwendung zu vermitteln, niemals seinen Wert.
Das kanonische Beispiel ist ssh-agent. Dein SSH-Private-Key lebt in
einem Speicherbereich, der dem ssh-agent-Prozess gehört. Wenn ssh
sich authentifizieren muss, sagt es nicht „gib mir den Schlüssel";
es schickt die Challenge-Bytes über einen Unix-Domain-Socket und
bekommt eine Signatur zurück. Der Schlüssel überquert den Socket nie.
Ein bösartiges Binary, das unter demselben Nutzer läuft, kann
ssh-agent darum bitten, Dinge zu signieren — das ist der ganze
Zweck des Agents — aber es kann den Schlüssel nicht lesen, nicht
kopieren, nicht exfiltrieren, nicht nach Hause schicken. Wenn die
Session endet, stirbt der Schlüssel mit dem Prozess. WebAuthn macht
strukturell dasselbe für Browser: der Private Key lebt im TPM oder in
der Secure Enclave, die Seite bittet den Browser, eine Challenge zu
signieren, die Seite sieht den Schlüssel nie. Die jahrzehntelange
Migration der Branche weg von Passwörtern in localStorage ist, wenn
man die Augen leicht zusammenkneift, dieselbe Migration, die NemoClaw
machen muss. Nur ein Stockwerk höher.
Und es funktioniert auch für GitHub. Die gh-CLI bringt einen
Credential-Helper mit, der unter macOS das Token in der Keychain
speichern kann statt in einer Klartext-Konfigurationsdatei. Für den
Sandbox-Fall noch nützlicher: GitHub Apps geben Installation-Tokens
heraus, die kurzlebig sind (typischerweise eine Stunde), auf
spezifische Repositories gescopt sind und widerrufbar bleiben; ein
Signing-Proxy, der außerhalb der Sandbox läuft, kann auf Anforderung
eines dieser Tokens prägen, es an eine vom Agent erzeugte Anfrage
anhängen und das Ergebnis weiterreichen. Die Sandbox sieht eine
generische HTTP-Antwort. Die Sandbox sieht das Token nicht. Ein
bösartiges postinstall-Script, das den brokerten Endpunkt darum bittet,
das Token herauszurücken, bekommt im besten Fall ein einstündiges,
auf ein Repo gescoptes Token zurück — genug, um das zu erledigen, was
der Agent tatsächlich im Namen des Nutzers tun wollte, nicht genug,
um sich die Exfiltration zu lohnen.
Das Muster hat in jeder Domäne, die es verwendet, einen Namen — ssh-agent, WebAuthn, HSM-gestütztes Signieren, der Credential-Helper von gh, AWS IAM Roles Anywhere — und die zugrundeliegende Eigenschaft ist immer dieselbe: der Konsument des Credentials ist ein anderer Prozess als der Halter des Credentials, und sie kommunizieren über einen Kanal, der enger ist als „lies die Bytes". Es ist der Unterschied zwischen „der Agent kann sich gegenüber GitHub authentifizieren" und „der Agent kann das GitHub-Token lesen". Eine Sandbox, die das falsch macht, ist eine Sandbox, die den Haustürschlüssel auf dieselbe Seite der Tür gelegt hat wie die Leute, vor denen man sich gesorgt hat.
Genau das macht Bromure, um unmissverständlich zu sein, für die VM
pro Profil, in der dein Coding-Agent läuft. Der Agent innerhalb der
VM authentifiziert sich gegenüber GitHub, indem er auf dem macOS-Host
mit einem Credential-Broker über einen weitergeleiteten
Unix-Domain-Socket spricht; das GitHub-Token (oder, besser, der
Private Key der GitHub App, der kurzlebige scope-limitierte Tokens
prägt) liegt auf der Host-Seite des Hypervisors, in der macOS
Keychain, wo die VM ihn nicht sehen kann. Der Agent liest den
Secret-Wert nie, er verwendet ihn nur über den Proxy. Ein
postinstall-Script, das cat /sandbox/.openclaw/openclaw.json
ausführt, findet nichts; eines, das env | grep TOKEN ausführt, findet
nichts; eines, das den Broker bittet „bitte gib mir das Token", findet
heraus, dass das RPC-Vokabular des Brokers dieses Verb nicht kennt.
Dieselbe Haltung, angewandt auf den GitHub-Agent so, wie sie seit
dreißig Jahren auf SSH angewandt wird.
Eine höfliche Empfehlung ist kein Perimeter.
Lassos Emoji-Trick ist, in einem tiefen Sinn, ein Kommentar zu
Allowlists. Die Egress-Policy erlaubte gh, mit github.com zu
sprechen. Die implizite Annahme war, dass das, was gh mit github.com
tun würde, das wäre, was ein vernünftiger Entwickler tun möchte —
clone, push, PRs öffnen, Issues kommentieren. Aber
gh pr create --body "$ANYTHING" ist konstruktionsbedingt ein
Primitive, das beliebige Bytes an ein öffentlich lesbares Ziel trägt.
Man kann dieses Primitive nicht auf die Allowlist setzen und gleichzeitig
verhindern, dass beliebige Bytes hindurchgehen. Die Allowlist tut, was
sie versprochen hat. Sie tut nur nicht das, was du dachtest, was sie
versprochen hatte.
Das ist der Teil der Lasso-Veröffentlichung, der jeden, der einen Agent in Produktion betreibt, dazu bringen sollte, sich hinzusetzen. Eine L7-Allowlist, die ein Protokoll zulässt, das beliebige Bytes tragen kann, ist kein Perimeter. Sie ist eine höfliche Empfehlung, dass die Bytes im Protokoll die Bytes sein mögen, die du dir vorgestellt hast. Ob die Bytes im PR-Body, in einer Commit-Message, in einem Issue-Kommentar, in einem git-LFS-Blob, in den Metadaten eines als Release-Asset hochgeladenen Tarballs liegen — das Protokoll ist das Leck. Es gibt keinen statischen Filter, der den Unterschied zwischen einem legitimen emoji-lastigen PR („unser Team nutzt 🍰, um Release zu meinen") und einem emoji-codierten GitHub-Token „versteht", denn der Unterschied ist semantisch und der Filter ist syntaktisch.
Was würde das also erkennen? Die ehrliche Antwort ist, dass kein einzelner Trick es tut; die Struktur, die es tut, ist eine Kombination, und jedes einzelne Stück ist für sich genommen uninteressant.
Das erste Stück sind Egress-Byte-Budgets pro Session. Eine Session, deren Auftrag „behebe einen Typo in der README.md" lautet, sollte niemals 14 Kilobyte binären Blob in einen PR-Body schieben, niemals, aus keinem Grund. Du musst nicht wissen, was die Bytes sind; du musst wissen, was die Session ausliefern sollte. Die Diskrepanz zwischen Auftragsform und Egress ist berechenbar — aber nur, wenn etwas außerhalb des Agents Auftrag und Egress am selben Ort führt. Die Selbstauskunft des Agents reicht nicht; der Agent ist das, was unter Verdacht steht.
Das zweite ist Content-Shape-Anomalieerkennung auf ausgehenden git-Operationen. Ein PR, dessen Body zu 95 % aus Emoji besteht, oder zu 95 % aus Base64, oder zu 95 % aus Hex, in einem Repository, dessen Historie null solcher PRs enthält, ist eine Flagge. Es ist kein Beweis; es ist eine Flagge. Der richtige Ort, diese Flagge zu berechnen, ist der Egress-Proxy, der die ausgehende Anfrage sieht, bevor sie den Host verlässt. Bromures Proxy auf Hypervisor-Ebene ist der Ort, an dem das ohne Vertrauen in den Gast berechnet werden kann — denn der Gast ist genau das, was unter Verdacht steht.
Das dritte sind Session-Ende-Diffs zwischen dem, was die Box
verlassen hat, und dem, was die Session produzieren sollte. Am Ende
einer Session hat die VM eine Menge ausgehender HTTP-Requests
produziert, eine Menge Datei-Writes ins gemountete Projekt, eine
Menge git-Commits. Wenn der Session-Auftrag „behebe einen Typo"
lautete und die ausgehenden Requests
POST /repos/attacker-handle/random-repo/pulls enthalten, ist das
ein Diff, das man einem Menschen in zwei Zeilen zeigen kann. Nicht
notwendigerweise blockiert — manchmal müssen Agents wirklich
überraschende Dinge tun — aber gezeigt. Der aktuelle Default 2026
quer durch die meisten Coding-Agent-Produkte ist „vertrau mir, hat
geklappt", und der Nutzer hat kein Artefakt zur Inspektion, selbst
wenn er es wollte.
Die Audit-Pipeline ist das Artefakt.
Hier ist der Punkt, an dem es sich lohnt, laut auszusprechen, was
Bromure Enterprise tatsächlich liefert — weil die Alternative,
nämlich sich auf die eigenen Logs des Agents zu verlassen, NemoClaw
überhaupt erst in diese Lage gebracht hat. Die Logs des Agents werden
vom Agent geschrieben. Wenn dem Agent von einer vergifteten SOUL.md
gesagt wurde zu lügen, was er getan hat, dann werden die Logs des
Agents darüber lügen, was er getan hat. Es gibt genau einen Ort, der
einen wahrheitsgetreuen Bericht über das, was ein Agent getan hat,
produzieren kann, und das ist die Ebene unterhalb des Agents.
Bromure Enterprise zeichnet auf der Host-Seite des Hypervisors „die volle Session — Tool-Aufrufe, Shell-Kommandos, Datei-Edits, Exit-Codes" als JSON Lines auf. Tracing ist standardmäßig an; Engineers müssen sich nicht aktiv einschreiben; der Agent in der VM ist ein unverändertes Claude Code oder Codex oder Cursor. Der Stream wird „außerhalb der VM in einem manipulationsresistenten JSON-Lines-Stream erfasst und an die Log-Senke geliefert, die du ohnehin schon befüllst (SIEM, Data Lake, Retention-Archiv)." Eine kompromittierte Abhängigkeit innerhalb der VM kann ihn nicht löschen, weil die Writes auf der anderen Seite der Hypervisor-Grenze geschehen, die die Abhängigkeit nicht überqueren kann.
Die interessanten Konsequenzen:
- „Hat diese Session in ein Repo gepusht, das nicht das Repo des Nutzers war" ist ein grep. Kein metaphorisches grep. Ein buchstäbliches grep gegen die JSON Lines von gestern.
- „Hat diese Session einen PR mit einem Body geöffnet, der nicht wie Prosa aussieht" ist ein Regex gegen die erfasste Tool-Call-Nutzlast.
- „Hat irgendetwas
SOUL.mdmodifiziert" ist eine Abfrage über Datei-Edit-Events. Wenn einpostinstall-Script die Identitätsdatei des Agents überschrieben hat, lebt dieser Fakt im Trace, ob der Agent selbst es jemals erwähnt hat oder nicht. - Replay. Traces hängen an einem Pull Request. Der Reviewer liest den Diff und die Sequenz aus Prompts, Tool-Aufrufen und Shell-Kommandos, die den Diff erzeugt haben. Oder, in der Sprache der Bromure-Produktseite: „replay the day the model decided to delete the migrations folder." Forensisches Replay ist der Teil dieser Geschichte, den es sonst nirgends gibt, weil es voraussetzt, dass die Inputs, die Outputs und die Modell-Antworten in demselben Stream erfasst wurden — was der Agent selbst nicht produzieren kann, ohne zuerst dafür Vertrauen geliehen zu bekommen, nicht zu lügen.
Nichts davon erwischt einen entschlossenen Angreifer, der die Exfiltration so formt, dass sie wie Prosa aussieht; es gibt keinen Perimeter gegen einen Gegner, der bereit ist, Bytes für die Tarnung auszugeben. Was es erwischt, ist jeden Angreifer, der das nicht tut, also die meisten, und es produziert die forensische Aufzeichnung, die den nächsten Vorfall aus „wir haben keine Ahnung, was der Agent getan hat" in „wir haben Zeile 14.332 des gestrigen Session-Traces" verwandelt. Der 2026er-Default „der Agent hat gesagt, es war erfolgreich" entspricht dem Betreiben von Produktion auf einem Server ohne Logs.
Was ist mit der Prompt-Injection innerhalb der Session?
Es lohnt sich, klar zu sagen, was VM-Isolation nicht behebt — denn die Menschen, die diesen Post am ehesten lesen, sind dieselben, denen am ehesten von jemandem, der das Gegenprodukt verkauft, gesagt wird, VMs seien ein Allheilmittel. Sind sie nicht.
Die SOUL.md-Backdoor — und jede Prompt-Injection, die während einer Session wirkt — läuft innerhalb der VM, mit dem Scope, den der Nutzer dem Agent gewährt hat. Wenn der Nutzer dem Agent gesagt hat „erstelle einen PR in diesem Repo", kann die Prompt-Injection einen PR in diesem Repo erstellen. Wenn der Agent Schreibzugriff auf den Projektordner hat, kann die Prompt-Injection eine Hintertür in den Projektordner schreiben. Die VM begutachtet den Diff nicht. Was die VM tut, ist, den Diff und seine Herkunft an einem Ort zu behalten, an dem ihn jemand später anschauen kann — und das stellt sich als der Teil heraus, der gefehlt hat.
Was VM-Isolation plus Credential-Brokering behebt, ist der katastrophale Teil — der Teil, in dem ein einziges schlechtes postinstall mit einem dauerhaften GitHub-Token, einem dauerhaften npm-Token, deinen AWS-Credentials und Root auf dem Laptop des Entwicklers davonspaziert. Keines dieser Credentials lebt innerhalb der VM; die Credentials leben in der Host-Keychain und sind nur über einen Proxy erreichbar, dessen RPC-Vokabular „gib mir die Bytes" nicht kennt. Ein Token, das der Agent über einen Proxy nutzen kann, ist ein Token, das der Agent nicht exfiltrieren kann — denn Exfiltration setzt voraus, die Bytes zum Versenden zu haben.
Die verbleibende Angreifer-Fähigkeit innerhalb eines
Bromure-gehosteten OpenClaw-Äquivalents — das, was sie tun können,
sobald sie den Agent prompt-injektiert haben — ist, den Agent
innerhalb des autorisierten Scopes der Session dazu zu bringen,
etwas zu tun, was der Nutzer nicht beabsichtigt hat. Einen PR mit
einem seltsamen Titel öffnen. SOUL.md im Projekt überschreiben.
Ein eigenes postinstall hinzufügen. All das sind beobachtbare
Ereignisse: jeder Datei-Edit landet im JSON-Lines-Audit-Stream, jede
ausgehende Anfrage landet im Egress-Proxy, jeder Prompt und jeder
Tool-Aufruf wird außerhalb des Agents aufgezeichnet. Die VM wird
nicht darum gebeten, den prompt-injektierten Agent daran zu hindern,
in-scope Schaden zu verursachen — sie wird darum gebeten, diesen
Schaden sichtbar zu machen und auf die Session zu begrenzen, sodass
der Host sauber bleibt und der Nutzer einen Trace zum Nachlesen hat.
Persistenz innerhalb der VM ist weiter möglich; Persistenz innerhalb
der VM, die niemand sehen kann, ist es nicht — ein bedeutsamer
Unterschied.
In Kombination mit Credential-Brokering sieht der Worst Case für den Angriff auf einen Bromure-gehosteten Agent so aus: der Agent liefert einen schlechten PR, in dem Repo, für das er ohnehin autorisiert war, mit einem kurzlebigen Installation-Token, und jeder Schritt erscheint in einem manipulationsresistenten Log auf dem Host. Das ist nicht null Schaden. Es ist ein langer Weg entfernt von „der Angreifer hat mein dauerhaftes GitHub-Token, als Emoji exfiltriert, plus eine persistente Hintertür in der Verhaltensdatei des Agents, plus keinerlei Aufzeichnung, dass irgendetwas davon passiert ist."
Was hier wirklich strukturell ist.
Wenn man die Lasso-Veröffentlichung und die Nvidia-Antwort nacheinander liest, geht die Meinungsverschiedenheit nicht eigentlich darum, ob NemoClaw einen CVE-würdigen Bug hat. Nvidia hat recht, dass die Sandbox das getan hat, wofür sie konfiguriert war. Lasso hat recht, dass das, wofür sie konfiguriert war, nicht ausreicht. Die Meinungsverschiedenheit dreht sich darum, wohin die Vertrauensgrenze gehört.
Nvidia zieht die Grenze, in der Antwort, die Pearl zitiert, an „der
konfigurierten Policy". Innerhalb der Policy geht alles; außerhalb
der Policy ist der Kunde auf sich gestellt. Das ist eine normale
Shared-Responsibility-Position für einen Infrastruktur-Anbieter. Sie
ist aber keine Verteidigung gegen den Fehlermodus, den Lasso vorgeführt
hat — denn der Fehlermodus liegt innerhalb der Policy. Die Policy
erlaubt gh. gh kann das Token tragen. Die Policy ist
in sich konsistent und gleichzeitig unzureichend.
Die strukturelle Alternative — die Position, für die die Agentic-Coding-Beiträge auf diesem Blog seit sechs Monaten in verschiedener Sprache argumentieren — ist, die Grenze beim Credential und bei der Beobachtung zu ziehen, nicht beim Binary und beim Ziel. Brokering sagt: das Credential betritt die Sandbox nie. Die Audit-Pipeline auf Hypervisor-Ebene sagt: was immer der Agent innerhalb der Sandbox tut, wird von etwas erfasst, in das der Agent nicht schreiben und das er nicht abschalten kann. Zusammen erzeugen sie eine Sandbox, in der das Schlimmste, was ein bösartiges postinstall anrichten kann, das Schlimmste ist, wozu der Agent autorisiert war, auf dem Repo, das er ohnehin schon angefasst hat, mit Credentials, die er nicht exfiltrieren kann, weil er sie nie hatte — und mit jedem Tastendruck an Beweisen, die in deinem SIEM liegen.
Die Nvidia-Leute liegen nicht falsch. Die OpenClaw-Architektur ist die Architektur jedes Coding-Agents, der dieses Jahr ausgeliefert wird, und das schließt Coding-Agents ein, die nicht in einer Sandbox laufen. Was Lasso in NemoClaw gefunden hat, ist strukturell das, was Wiz und Snyk und Socket alle paar Tage in Cursor und Windsurf und im YOLO-Modus von GitHub Copilot finden. Die Problemklasse ist „langlebige Klartext-Credentials, zugänglich für alles, was der Agent ausführt, ohne Aufzeichnung dessen, was der Agent damit gemacht hat", und die Fix-Klasse ist „brokere das Credential, beobachte die Session, hebe die Belege auf".
Ein letztes Wort.
Es gibt eine Variante dieses Posts, in der die Lehre „vertrau keinen Sandboxes" wäre. Diese Variante ist falsch. Sandboxes sind großartig. Es gibt eine Variante, in der die Lehre „KI-Agents sind zu gefährlich, um sie auszuliefern" wäre. Diese Variante ist, in der Praxis, irrelevant — sie sind ausgeliefert, die Frage ist wie. Die Variante, die hält, ist die, in der die Sandbox aufhört, gebeten zu werden, Arbeit zu leisten, die die Sandbox konstruktionsbedingt nicht leisten kann.
Eine Sandbox kann ein Credential nicht vor einem Prozess verbergen, der innerhalb der Sandbox läuft. Eine Sandbox kann den Unterschied zwischen einem Emoji-PR-Body und einem emoji-codierten Token nicht erkennen. Eine Sandbox kann ein langes allowlistetes Protokoll nicht in ein kurzes verwandeln. Was eine Sandbox kann, ist, die Credentials woanders aufzubewahren, den Agent an einem Ort zu halten, an dem der Hypervisor jede seiner Bewegungen sieht, und diesen Bericht in eine Senke zu schreiben, die der Agent nicht erreichen kann. Das ist die Konfiguration, in der dasselbe bösartige npm-Paket, in derselben Art postinstall-Script, ein leeres Dateisystem vorfindet, einen Credential-Socket, dessen einziges Verb „signiere mir kurz dieses Ding" ist, und einen Hypervisor auf der anderen Seite der Wand, der das ganze Gespräch mitgeschrieben hat.
Bromure Agentic Coding ist die Konfiguration, in der das der Default ist. Es ist kostenlos, Open Source und wird heute ausgeliefert. Das nächste Emoji wird gerade hochgeladen.