27 KiB
Security-Konzept: Einschließen, Regeln, Überwachen
Rolle: Bauplan. Stand 2026-09-19, entstanden aus dem Orchestrator-Vergleich (OpenClaw, Grok Bot, Claude Code/Codex, OpenHands, LlamaFirewall, CaMeL) und der Abstimmung mit dem Nutzer. Reihenfolge und Status stehen im Deploymentcenter, nicht hier.
1 — Das Ziel in einem Satz
Ein bösartiger Agent — auch einer, der durch eingeschleusten Text übernommen wurde — darf seinen Workspace nicht verlassen und nichts Schädliches tun. Das muss auch dann gelten, wenn Agenten eigene Skripte schreiben und ausführen.
2 — Der Grundsatz: das Modell ist nie die Grenze
Ein Überwachungsagent kann einen Ausbruch nicht verhindern, nur hinterher bemerken. Und er ist selbst angreifbar: Er liest genau die Verläufe, in denen der eingeschleuste Text steht. Deshalb vier Schichten, nach Kosten sortiert — die unteren drei sind deterministisch und kosten keine Tokens, erst die oberste fragt ein Modell:
| Schicht | Was | Kosten | Verhindert / erkennt |
|---|---|---|---|
| 0 Einschließen | Sandbox-Runner für jede Codeausführung | keine Tokens | verhindert |
| 1 Regeln vor dem Aufruf | PermissionGate, Staging, Herkunftsregel, Netzprofil | keine Tokens | verhindert |
| 2 Regelbasierte Überwachung | Detektoren über das Audit, Köderwerte | keine Tokens | erkennt sofort |
| 3 Security-Agent | Einschätzung auf Anlass, Skriptprüfung, Stichprobe | gedeckelt | erkennt, bewertet |
So machen es die Systeme, die tragen: Claude Code und Codex setzen die Grenze im Betriebssystem (bubblewrap bzw. Landlock + seccomp) und prüfen mit einem Modell nur zusätzlich. OpenClaw zeigt die Gegenseite — dort ist die Sandbox optional, und die Vorfälle mit ClawHub kamen genau daher.
Warum das jetzt dran ist
Heute laufen alle Agenten in einem Prozess unter einem Linux-Benutzer. Die
Workspace-Grenze ist C#-Code in den Werkzeugen (PathBoundary); #373 hat gezeigt, wie
leicht sie bricht. Das trägt, solange Agenten keinen eigenen Code ausführen. Ein
Python-Skript fragt PathBoundary nicht — open('/home/...') geht am Werkzeug vorbei.
Und der Hauptprozess hält den entsperrten Hauptschlüssel.
Regel, nicht verhandelbar: Fremder Code läuft nie im Hauptprozess. Kein Skript, keine Shell, kein MCP-stdio-Server ohne den Runner aus Schicht 0.
Das Bedrohungsmodell wird um eine Klasse erweitert
Bisher: rein interner Betrieb; Schutz gegen Ordner-Kopieren und gegen Schadsoftware, die nach Zugangsdaten sucht. Das bleibt. Neu: Der Angreifer ist Inhalt, keine Person — eine Webseite, eine Mail, eine Chatnachricht, ein Tool-Ergebnis, das einen Agenten umsteuert. Interner Betrieb schützt davor nicht, weil die Agenten Fremdinhalt lesen, sobald sie ihre Arbeit tun.
3 — Schicht 0: Sandbox-Runner
Ein gemeinsamer Runner für alles, was Code ausführt: Shell (#196), freigegebene Skripte
(Abschnitt 7), MCP-stdio-Server (#197) und die heutigen yt-dlp/ffmpeg-Aufrufe des
SocialMediaManagerTool.
Garantien, jede mit einem Test, der den Ausbruch versucht:
-
Dateisystem: Nur der Workspace des Agenten ist beschreibbar und sichtbar; System schreibgeschützt,
$HOME, Instanzverzeichnis, Schlüsselbund und die Workspaces anderer Agenten sind nicht vorhanden (eigener Mount-Namespace, nicht bloß gesperrt). -
Erbe: Keine Umgebungsvariablen, keine offenen Dateideskriptoren, keine Secrets des Hauptprozesses. Was ein Skript braucht, bekommt es ausdrücklich übergeben.
-
Netz: Standardmäßig kein Netz (eigener Netz-Namespace). Freigabe nur über den Egress-Proxy, siehe Abschnitt 5.
-
Grenzen: Laufzeit, Speicher, Prozesszahl, Ausgabegröße; seccomp-Filter; kein Rechteerwerb (
no_new_privs). -
Umsetzung:
bwrapunter Linux. Ein eigener Linux-Benutzer je Agent ist die spätere Stufe, falls die Namespace-Trennung einmal nicht reicht. -
Nichts, was der Hauptprozess liest, ist in der Sandbox beschreibbar. Task-Dateien, Skills, Identity/Soul, Skript-Manifeste, Gedächtnis-Importe und jede Konfiguration liegen außerhalb des beschreibbaren Bereichs oder sind dort schreibgeschützt eingebunden. Das ist die Lehre aus CVE-2026-25725 bei Claude Code: Code in der Sandbox legte Hooks an, die beim nächsten Start mit vollen Rechten liefen. Eine Sandbox, die Dateien schreiben darf, die draußen ausgeführt oder als Anweisung gelesen werden, ist keine Grenze, sondern ein verzögerter Ausbruch. Ein Test gehört dazu: Die Sandbox versucht jede dieser Dateien zu schreiben.
Unter Windows gibt es keinen Runner und damit keine Codeausführung — die Funktion fehlt dort, statt schwächer zu sein.
Gebaut am 2026-09-25 (#654), geprüft unter Ubuntu 26.04 mit bwrap 0.11.1 auf der Test-VM. Was beim Bau dazukam und in keinem Handbuch steht:
- Die Wurzel der Sandbox ist beschreibbar, wenn man nichts tut: bwrap baut sie als
eigenes tmpfs. Erst
--remount-ro /nach allen Einbindungen macht daraus „nur/workund/tmp“. Der Ausbruchstest hatte unter/etceine Datei angelegt. - Der seccomp-Deskriptor wird weitergereicht. bwrap liest den Filter über fd 3 und lässt ihn im Programm offen; die innere Shell schließt ihn vor dem Start.
- Die Prozessgrenze (RLIMIT_NPROC) wird innerhalb des eigenen User-Namensraums
gesetzt. Dort zählt sie nur die Prozesse der Sandbox, nicht die Threads der Instanz
(auf der VM über tausend unter demselben Benutzer). Das ist mit einem Gegenfall
belegt: 5 von 10 gehen, 12 nicht. dash kennt dafür
ulimit -p, bashulimit -u. --die-with-parenthängt am Thread, nicht am Prozess. Das Elternsterbe-Signal des Kernels feuert, wenn der Thread endet, der den Prozess gestartet hat. .NET startet aus einem Threadpool-Thread, und unter Last baut der Threadpool Threads ab. Folge auf der VM: bwrap bekam mitten im Lauf SIGKILL, und starb er noch im Aufbau, lebte das Innere als Waise weiter. Alle Sandboxen starten deshalb aus einem eigenen, dauerhaften Thread. Zum Beenden wird der ganze Baum unter bwrap aus/proceingesammelt und getötet, samt PID 1 des Namensraums, dessen Tod den Rest mitnimmt.- Erster Nutzer ist ffmpeg im SocialMediaManager, weil es heruntergeladene Medien zerlegt. yt-dlp braucht Netz und kommt mit dem Egress-Proxy (#655) in die Sandbox; bis dahin läuft es wie bisher und das Protokoll sagt es.
4 — Schicht 1: Regeln vor dem Aufruf
Vorhanden: PermissionGate (Werkzeug je Agent), Staging mit Plan-Freeze, PathBoundary,
UrlGuard, SqlGuard. Neu:
4.1 Herkunftsregel
Vorbild CaMeL, in der einfachsten Form. Sobald ein Lauf Fremdinhalt gelesen hat — WebFetch, Mail, Chat, eine Datei, die nicht der Agent selbst geschrieben hat, das Ergebnis eines MCP-Servers —, gilt der Lauf als belastet. Ab dann ist jede Aktion mit Außenwirkung freigabepflichtig, egal was die Policy sonst sagt: Mail senden, posten, FTP-Upload, Schreiben in die Datenbank, Nachricht an andere Agenten, Task an andere Agenten.
Das kostet nichts und nimmt einer übernommenen Anweisung genau die Wirkung, um die es
geht: Sie kann lesen und vorschlagen, aber nicht handeln. Welche Werkzeuge Fremdinhalt
liefern und welche Außenwirkung haben, erklärt jedes Werkzeug selbst (wie
StagingAktion seit #609). Die Freigabe-Nachricht (#644) nennt die Quelle, die den Lauf
belastet hat.
Freigabemüdigkeit ist der eigentliche Gegner dieser Regel. Der Sicherheitsvergleich vom 2026-09-19 hat sie als realistischstes Einfallstor ausgemacht: Fast jeder Agent liest Fremdinhalt, fast jeder Lauf wird belastet, und wer 40 Freigaben am Tag abnickt, ist selbst der Umgehungsweg. Deshalb gehört zur Regel:
- Feste Ziele sind ausgenommen. Außenwirkung an Ziele, die ein Mensch vorab
eingerichtet hat — die eigenen Kanäle,
@human, fest hinterlegte Empfänger je Agent — bleibt ohne Freigabe. Eine Injection kann dorthin schreiben, aber niemanden erreichen, den der Betreiber nicht selbst ausgewählt hat. - Muster-Freigabe auf Zeit. Ein wiederkehrender Aufruf (gleicher Agent, gleiches Werkzeug, gleiches Ziel) kann für eine begrenzte Frist freigegeben werden, statt jeden Einzelfall zu bestätigen. Nie für hohe Risiken, nie ohne Ablauf.
- Die Freigabequote wird sichtbar (Abschnitt 10). Wer 100 % durchwinkt, hat keine Kontrolle mehr, sondern eine Verzögerung — das soll man sehen, nicht vermuten.
- Die Vorschau zeigt Herkunft. Argumente, die Daten aus sensiblen Quellen tragen
(Gedächtnis, Datenbank, Dateien außerhalb von
out/), werden in der Freigabe hervorgehoben — sonst geht ein Abfluss, versteckt in einem langen Argument, durch die Freigabe hindurch.
4.2 Schutz vor Amoklauf
Rate-Limits je Werkzeug und Agent, Circuit-Breaker bei gehäuften Fehlern oder Ablehnungen — der Übergang zur Quarantäne (Abschnitt 6). Aus dem Erweiterungskonzept.
4.3 Belastung wandert mit
Die Lücke, die der Vergleich aufgedeckt hat und die kein anderes Konzept schließt: Ein belasteter Lauf schreibt einen Gedächtniseintrag, einen Skill-Entwurf oder einen Task. Ein späterer, unbelasteter Lauf lädt ihn — und die eingeschleuste Anweisung wirkt jetzt ohne Herkunftsmarke. Die Herkunftsregel wäre über einen Umweg ausgehebelt.
Deshalb: Was ein belasteter Lauf hinterlässt, trägt die Marke weiter — Gedächtnis, Skill-Entwürfe, Tasks und Task-Kommentare, Dateien im SharedWorkspace. Die Engine stempelt sie, nicht der Agent. Wer einen markierten Eintrag lädt, wird selbst belastet. Ein Mensch kann einen Eintrag nach Prüfung entlasten; das steht im Audit. Skill-Entwürfe aus belasteten Läufen sind in der Freigabe (#198) ausdrücklich markiert.
5 — Netzprofil je Agent
Ein Agent hat drei getrennte Wege ins Netz. Sie werden oft in einen Topf geworfen, sind aber verschieden gefährlich und brauchen eigene Schalter.
| Weg | Wer ruft auf | Wer wählt das Ziel | Heute | Einstellung |
|---|---|---|---|---|
| Modell | die Engine, zu OpenRouter | niemand — immer OpenRouter | fest | Modell-Netzprofil (5.1) |
| Werkzeuge | der Hauptprozess (WebFetch, Mail, MCP …) | der Agent, im Rahmen der Allowlist | WebFetch mit Domain-Allowlist, muss je Agent freigegeben werden | bleibt je Werkzeug |
| Sandbox | ein Skript oder Shell-Befehl | der Code | gibt es noch nicht | aus; Freigabe je Skript (5.2) |
Der Weg zu OpenRouter ist kein Internetzugang des Agenten: Die Engine spricht mit genau einem Ziel, der Agent kann weder Adresse noch Inhalt der Verbindung bestimmen. Er wird aber dann zum Internetzugang, wenn das Modell selbst suchen darf.
5.1 Modell-Netzprofil (je Agent, in den Modelleinstellungen)
- Websuche des Modells: OpenRouter kann dem Modell eine eigene Websuche geben (Plugin
weboder das Suffix:onlineam Modellnamen). Das ist ein Netzweg, an dem weder Staging noch Audit vorbeikommen. Voreinstellung aus; ein Modellname mit:onlinewird abgelehnt, solange der Schalter aus ist. - Datennutzung beim Anbieter:
data_collection: denyals Voreinstellung (das Feld ist inProviderPreferencesschon vorhanden, wird aber noch nicht gesetzt); optional nur Anbieter ohne Datenspeicherung. - Anbieter-Allowlist und Ausweichen: Welche Anbieter ein Agent nutzen darf, ob auf
andere ausgewichen werden darf (
allow_fallbacks). require_parametersbleibt an (#550).
5.2 Sandbox-Netz
Standard: kein Netz. Braucht ein Skript Netz, deklariert es die Ziele in seinem Manifest (Abschnitt 7), und die Freigabe des Skripts umfasst diese Ziele. Durchgesetzt wird es vom Egress-Proxy: nur die deklarierten Domains, nur HTTPS, jeder Abruf im Audit. Ein Skript, das etwas anderes erreichen will, scheitert und erzeugt einen Befund.
Der Egress-Proxy ist gebaut (2026-09-25, mit #712), die Anbindung an Skript-Manifeste noch nicht (#655, #695). So umgesetzt:
- Die Sandbox teilt nie das Netz des Hosts. Mit geteiltem Netz sähe sie alles, was der
Host auf Loopback anbietet, darunter den Port der Weboberfläche und eine Datenbank. Sie
sähe außerdem abstrakte Unix-Sockets wie ein X11-Display, denn die gehören zum
Netz-Namensraum, nicht zum Dateisystem. Die Sandbox behält ihr Netz mit nur Loopback. Ein
Starter in der Sandbox (die Anwendung mit
--sandbox-launch) lauscht dort auf127.0.0.1:3128und reicht jede Verbindung an einen Unix-Socket weiter. Der Socket ist eingebunden, dahinter steht der Proxy im Hauptprozess. - Nur
CONNECT host:port, also ein TLS-Tunnel. Klartext-HTTP wird abgewiesen. Der Host muss auf der Liste stehen (host,host:port,*.domainnur für Subdomains). Adressliterale stehen nie auf der Liste. - Namen löst der Proxy auf, nicht die Sandbox. Löst ein gelisteter Name auch nur teilweise auf eine nicht-öffentliche Adresse auf, wird er ganz abgewiesen. Das betrifft Loopback, private Netze, CGNAT, Link-Local (Metadaten-Dienste), Multicast und IPv6-Hüllen wie 6to4 und NAT64. So kommt kein DNS-Rebinding auf die Instanz.
- Jede Verbindung und jede Abweisung steht im Log. Im Audit steht sie noch nicht, das kommt mit den Manifesten.
Geprüft unter Linux in der echten Sandbox (SandboxLaunchTests): Ein gelisteter Host
antwortet, ein anderer bekommt 403, --noproxy findet kein Netz, und ein Dienst auf dem
Loopback des Hosts ist nicht erreichbar.
6 — Befunde und Quarantäne
6.1 Zwei Stufen
| Stufe | Beispiele | Reaktion | Aufheben |
|---|---|---|---|
| Niedrig | gehäufte Ablehnungen, Kostensprung, neue Zieldomain, Änderung an Identity/Soul | Nachricht über den Kanal (#644) mit Quarantäne-Vorschlag — per Button bestätigen oder verwerfen | im Messenger oder in der Oberfläche |
| Hoch | Köderwert in einem ausgehenden Aufruf, Ausbruchsversuch aus der Sandbox, Zugriff auf fremde Workspaces, Skript weicht vom freigegebenen Hash ab | sofortige Quarantäne, Nachricht über den Kanal ohne Schaltfläche | nur in der Oberfläche, nach Prüfung |
Warum hoch nicht per Messenger: Der Messenger ist ein Kanal, über den auch Fremdinhalt kommt, und ein Telefon geht leichter verloren als der Zugang zur Oberfläche. Wer einen Agenten nach einem Köder-Treffer wieder freilässt, soll die Belege vor sich haben.
6.2 Was Quarantäne heißt
- Der Agent nimmt keine neuen Läufe an (Scanner überspringt ihn, Chat wird abgewiesen).
- Ein laufender Lauf endet beim nächsten Schritt; Sandbox-Prozesse des Agenten werden beendet.
- Alle ausgehenden Nachrichten des Agenten werden zurückgehalten.
- Seine offenen Freigabe-Vorschläge werden gesperrt, nicht gelöscht.
- Alles ist umkehrbar und steht im Audit. Nichts wird gelöscht.
6.3 Ausnahmen für bekannte Befunde
Damit dieselbe Meldung nicht jeden Tag wiederkommt:
- Jeder Befund hat einen Fingerabdruck aus Detektor, Agent, Werkzeug und normalisiertem Ziel. Gleiche Fingerabdrücke innerhalb eines Zeitfensters werden zu einem Befund mit Zähler zusammengefasst, statt neu gemeldet zu werden.
- Eine Ausnahme gilt für einen Fingerabdruck, trägt Begründung, Urheber und ein Ablaufdatum und steht im Audit. Ausnahmen ohne Ablauf gibt es nicht.
- Ausnahmen für niedrige Befunde gehen auch im Messenger („nicht mehr melden, 30 Tage"), für hohe nur in der Oberfläche.
- Nie ausnehmbar: Köder-Treffer und Sandbox-Ausbruchsversuche.
7 — Skripte, die Agenten selbst schreiben
Vorgabe: Freigegebene Agenten dürfen eigene Skripte schreiben. Ausgeführt wird nur, was geprüft ist; jede Änderung, auch ein Bugfix, braucht eine neue Prüfung.
- Wer darf: nur Agenten mit der Fähigkeit „Skripte schreiben". Standard aus.
- Form: Das Skript liegt im Workspace unter
scripts/, daneben ein Manifest: Zweck, Interpreter, Eingaben, Ausgaben, Netzziele (5.2), Laufzeitgrenze. - Bindung: Die Freigabe gilt für den SHA-256 von Skript und Manifest und die Interpreter-Fassung — nach dem Vorbild von OpenClaws Exec-Freigaben, die an Befehl, Arbeitsverzeichnis und Datei-Hashes gebunden sind. Ändert sich ein Byte, passt der Hash nicht mehr: nicht ausführbar, neue Prüfung. Versucht ein Agent, ein verändertes Skript auszuführen, ist das ein hoher Befund.
- Saubere Umgebung. Der Hash allein reicht nicht: Im August 2026 wurde Claude Codes
Auto-Modus umgangen, indem ein Archiv eine Datei
struct.pyin das Arbeitsverzeichnis legte, die beim Import eines Standardmoduls mitgeladen wurde („confused environment"). Ein freigegebenes Skript läuft deshalb aus einer schreibgeschützten, sauberen Kopie, mitpython -I(kein Arbeitsverzeichnis, keinPYTHONPATHim Suchpfad), mit Abhängigkeiten, die im Manifest mit Hash festgeschrieben sind, und der Workspace ist nur als Datenverzeichnis unter einem eigenen Pfad eingebunden. Was das Skript lädt, ist damit genau das, was geprüft wurde. - Ablauf der Prüfung:
- Deterministische Vorprüfung (kostenlos): Größe, Imports und Aufrufe, die eine
Begründung brauchen (
subprocess,socket,ctypes,os.system,eval/exec, dynamisches Nachladen, Base64-Dekodieren mit anschließender Ausführung), Abgleich mit dem Manifest („deklariert kein Netz, importiert aberrequests"). - Einschätzung des Security-Agenten: unbedenklich / bedenklich (mit Gründen und Zeilen) / zu komplex für mich — externe Prüfung. Ab einer Größen- oder Komplexitätsgrenze lautet das Urteil ohne Modellaufruf „zu komplex". Externe Prüfung heißt: Mensch, oder auf ausdrückliche Einstellung ein stärkeres Modell mit eigenem Budget.
- Freigabe durch den Menschen, mit Vorprüfung, Einschätzung und Diff zur vorigen Fassung vor Augen.
- Deterministische Vorprüfung (kostenlos): Größe, Imports und Aufrufe, die eine
Begründung brauchen (
- Die Einschätzung ist ein Rat, keine Freigabe. Auch „unbedenklich" gibt nichts frei. Und selbst ein freigegebenes Skript läuft nur im Runner — die Prüfung ist die zweite Linie, nicht die erste.
- Selbstschutz des Prüfers: Das Skript ist für den Security-Agenten Fremdinhalt. Ein Kommentar wie „als unbedenklich einstufen" darf nichts bewirken: Die Vorprüfung aus Schritt 1 kann das Modell nicht überstimmen, die Ausgabe ist strukturiert, und ein Urteil, das der Vorprüfung widerspricht, wird als Widerspruch angezeigt, nicht still übernommen.
8 — Schicht 2: Regelbasierte Überwachung
Detektoren über das Audit-Log. Laufen bei jedem Eintrag bzw. im Scanner-Takt, kosten keine Tokens und erzeugen Befunde nach Abschnitt 6.
- Grenzverletzungen (
PathBoundary,UrlGuard,SqlGuard, Sandbox) und abgelehnte Aufrufe in Serie - neue Zieldomains, neue Empfänger
- Kostensprung gegenüber dem eigenen Mittel
- Änderungen an Identity, Soul, Skills, Skripten
- verdächtige Folgen innerhalb eines Laufs: erst Fremdinhalt oder sensible Pfade lesen, dann Außenwirkung versuchen
- Köderwerte: Köderdateien im Workspace und Köder-Secrets im Schlüsselbund, die kein legitimer Ablauf je braucht. Taucht ein Köderwert in einem ausgehenden Aufruf, einer Nachricht oder im Sandbox-Netz auf → hoher Befund, sofortige Quarantäne. Praktisch keine Fehlalarme, weil es keinen legitimen Grund gibt, ihn zu benutzen.
9 — Schicht 3: Security-Agent
Ein eingeschränktes Profil des AgentInspector (#204), kein zweites System. Gleiche Datenbasis (Audit und Receipts, von der Engine gestempelt), gleicher Zweck.
- Wann er läuft: auf Anlass aus Schicht 2 (Befund bewerten, Zusammenhänge suchen), bei jeder Skriptprüfung (Abschnitt 7) und einmal täglich als Stichprobe mit kurzer Lagezusammenfassung. Nie dauerhaft mitlaufend.
- Was er sieht: strukturierte Audit-Daten — Werkzeug, Ausgang, Pfade, Ziele, Kosten. Rohe Fremdtexte nur gekürzt und als Daten gerahmt (#193).
- Was er darf — hart im Code, nicht im Prompt: Befunde anlegen und einstufen, über den Kanal melden, Quarantäne vorschlagen (niedrig) oder verhängen (hoch), Skripte einschätzen. Nie: freigeben, Quarantäne aufheben, Ausnahmen anlegen, Regeln oder Einstellungen ändern, Werkzeuge mit Außenwirkung benutzen.
- Kosten: günstiges Modell, eigenes Tagesbudget im Budget-Guard mit hartem Deckel. Ist der Deckel erreicht, laufen Schicht 0 bis 2 unverändert weiter, nur Einschätzungen bleiben aus — und das wird im Sicherheitsbereich angezeigt. Planbar wird es durch den Deckel und dadurch, dass Schicht 2 vorfiltert.
10 — Sicherheitsbereich in Oberfläche und WebUI
Eigener Menüpunkt auf Instanzebene, in Avalonia und in der Weboberfläche gleich aufgebaut:
- Freigabequote je Agent und Werkzeug: wie viel wird freigegeben, wie schnell, wie oft abgelehnt. Eine Quote nahe 100 % bei hoher Zahl ist selbst ein Befund.
- Lage: Sandbox verfügbar, Schlüsselbund dicht, Agenten in Quarantäne, offene Befunde, offene Skriptprüfungen, Kanalzustand (#645), Budget des Security-Agenten.
- Befunde: Liste mit Stufe, Fingerabdruck, Zähler, Beleg aus dem Audit; Quarantäne aufheben (hoch: nur hier), Ausnahme anlegen.
- Skripte: ausstehende Prüfungen mit Vorprüfung, Einschätzung und Diff; freigegebene Skripte mit Hash und Freigabe-Datum.
- Richtlinien je Agent: Netzprofil (Abschnitt 5), Herkunftsregel, Skript-Fähigkeit, Sandbox-Grenzen.
- Ausnahmen: mit Ablauf, Urheber, Begründung.
- Selbstprüfung auf Drift: „Sandbox konfiguriert, aber nicht verfügbar", „Modell mit
:onlinebei ausgeschalteter Websuche", „Agent darf Skripte schreiben, Runner fehlt". Vorbildopenclaw security audit; die Prüfungen gehören zu den Bausteinen von #648.
Zwei Regeln:
- Agenten kommen an diesen Bereich nicht heran — auch AgentEditor und ein Personalmanager-Agent nicht. Seine Einstellungen liegen außerhalb dessen, was ein Werkzeug schreiben kann.
- Wer eine Regel lockert, bestätigt ausdrücklich, und die Änderung steht im Audit. In der Weboberfläche verlangt das eine erneute Anmeldung.
11 — Zugangsdaten: der Agent sieht sie nie
Ergänzt am 2026-09-22 nach einem Vorschlag des Nutzers.
Heute bekommt ein Werkzeug seine Zugangsdaten aus der Konfiguration des Agenten. Wo ein Agent eine fremde API bedienen soll, steht der Schlüssel in Reichweite dessen, was in seinen Kontext geraten kann.
Der Vorschlag: eine Zugangsdatenverwaltung in ClawdDotNet. Der Agent bekennt nie einen Wert zu sehen, sondern schreibt einen Platzhalter; ClawdDotNet setzt ihn im Werkzeug ein, kurz bevor der Aufruf hinausgeht.
Agent: DirectAPI, Header: { "Authorization": "Bearer {{secret:amazon-sp-api}}" }
ClawdDotNet: ersetzt beim Aufruf, protokolliert die Benutzung, nie den Wert
Antwort: wird auf dem Rückweg maskiert, bevor sie in den Kontext geht
Das ist der richtige Ansatz, und er löst ein echtes Problem. Er löst aber nicht so viel, wie er auf den ersten Blick verspricht — und die Lücken dazwischen sind die eigentliche Arbeit.
Wo es klemmt
1. Ein Platzhalter darf nicht überall ersetzt werden.
Ein stumpfes Suchen-und-Ersetzen über alle Argumente wäre die größte Falle: Dann schreibt
ein Agent {{secret:amazon-sp-api}} in einen Dateiinhalt, in ein SQL-Statement, in eine
Nachricht oder in eine URL — und der Wert landet dort, wo ihn jeder lesen kann. Die
Ersetzung gehört an benannte Stellen je Werkzeug (etwa DirectAPI.headers,
Database.connection), nie an beliebige Zeichenketten.
2. Der Platzhalter schützt den Schlüssel, nicht das Ziel.
Auch mit (1): Ein Agent, der den Schlüssel im Kopf Authorization verwenden darf, kann
die Anfrage an eine beliebige Adresse richten — und schickt das Geheimnis dorthin. Die
Verwaltung muss deshalb jedes Geheimnis an ein Ziel binden: „dieser Schlüssel gilt nur
gegen sellingpartnerapi.amazon.com". Ohne diese Bindung gibt der Platzhalter ein
falsches Gefühl von Sicherheit. Das Netzprofil je Agent (Abschnitt 5) ist die Hälfte
davon; die andere gehört an den Eintrag selbst.
3. Die Antwort kann das Geheimnis enthalten.
Manche Dienste spiegeln Token in Fehlermeldungen zurück, manche Bibliotheken schreiben
die Verbindungszeichenfolge in die Ausnahme (Password=…). Dann steht der Wert im
Werkzeugergebnis, im Kontext und im Transkript. Die Maskierung auf dem Rückweg ist
keine Zugabe, sondern die zweite Hälfte des Mechanismus — der allgemeine Fall ist #192,
der Anfang steht in #660.
4. Was gilt als Verwendung durch einen Fremden? Ein Agent, der nie den Wert sieht, kann ihn nicht verraten — aber er kann ihn benutzen, und dazu lässt sich ein Agent überreden. Der Platzhalter schützt gegen Diebstahl der Zugangsdaten, nicht gegen Missbrauch der Befugnis. Dagegen helfen die Zielbindung, die Freigaberegeln und die Herkunftsregel (#651) — nicht der Platzhalter.
5. Die Verwaltung erbt die Schwäche des Hauptschlüssels. Eine Zugangsdatenverwaltung ist ein Tresor. Solange #190 offen ist — der Hauptschlüssel liegt unter Linux im Klartext —, legt man damit mehr Eier in einen Korb, von dem man weiß, dass er offen steht. Der Tresor macht den Betrieb ordentlicher, die Sicherheit verbessert er erst nach #190. Reihenfolge entsprechend.
6. Nicht verraten, was es gibt.
Fragt ein Agent nach {{secret:buchhaltung-bank}}, das ihm nicht zugeteilt ist, muss das
Werkzeug abweisen — ohne zu sagen, ob dieses Geheimnis existiert. Dieselbe Überlegung
wie beim Hinweis auf den anderen Arbeitsbereich (#662).
7. Zuteilung ist eine Rechteänderung. Wer welches Geheimnis benutzen darf, entscheidet ein Mensch, nie ein Agent — auch keine Abteilungsleitung. Die Zuteilung gehört an die Einheit (siehe Organisation-Konzept, #683/#692), damit sechs Einkäufer sie einmal bekommen und die Buchhaltung den Marktplatzschlüssel nicht sieht.
Was der Tresor dafür zurückgibt
- Eine Stelle zum Wechseln. Ein rotierter Schlüssel wird einmal geändert, alle Agenten arbeiten weiter.
- Benutzungsspuren. Wer hat wann welches Geheimnis gegen welches Ziel verwendet — im Audit, ohne den Wert. Ein nie benutzter Eintrag kann weg; ein plötzlich viel benutzter ist ein Befund.
- Ein sauberer Weg für Skripte. Ein freigegebenes Skript (#657) bekommt sein Geheimnis als Umgebungsvariable vom Läufer, deklariert im Manifest — nie im Quelltext, nie im Aufrufprotokoll (#696).
Urteil
Bauen, ja — aber mit Zielbindung und Rückweg-Maskierung von Anfang an, und nach #190. Ein Platzhalter allein verschiebt das Geheimnis nur von der Agentenkonfiguration in die Werkzeugkonfiguration.
12 — Reihenfolge und Items
| Item | Vorhaben | Abschnitt |
|---|---|---|
| #651 | Herkunftsregel, mit Ausnahmen für feste Ziele, Muster-Freigabe und Herkunft in der Vorschau | 4.1 |
| #659 | Belastung wandert mit (Gedächtnis-Vergiftung) | 4.3 |
| #652 | Befunde und Quarantäne mit zwei Stufen, Ausnahmen | 6 |
| #653 | Regelbasierte Detektoren und Köderwerte | 8 |
| #654 | Sandbox-Runner | 3 |
| #655 | Netzprofil je Agent | 5 |
| #656 | Sicherheitsbereich in Avalonia und Weboberfläche | 10 |
| #657 | Skriptprüfung | 7 |
| #658 | Security-Agent (Profil von #204) | 9 |
- #651 mit #659, #652, #653 — größter Nutzen je Aufwand, braucht nur das Vorhandene und die Messenger-Freigabe (#644).
- #654 — harte Vorbedingung für Skripte, Shell (#196) und MCP-stdio-Server (#197); steht deshalb vor beiden.
- #655 und #656.
- #657 — mit #198, weil Skripte mit den Skills kommen.
- #658 — zuletzt, auf #204 aufbauend. Bis dahin prüft bei Skripten der Mensch allein, mit der deterministischen Vorprüfung.