diff --git a/docs/Security-Konzept.md b/docs/Security-Konzept.md new file mode 100644 index 0000000..6b93239 --- /dev/null +++ b/docs/Security-Konzept.md @@ -0,0 +1,425 @@ +# 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:** `bwrap` unter 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. + +## 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](Orchestrator-Erweiterungskonzept-2026.md). + +### 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 + `web` oder das Suffix `:online` am Modellnamen). Das ist ein Netzweg, an dem weder + Staging noch Audit vorbeikommen. **Voreinstellung aus**; ein Modellname mit `:online` + wird abgelehnt, solange der Schalter aus ist. +- **Datennutzung beim Anbieter:** `data_collection: deny` als Voreinstellung (das Feld + ist in `ProviderPreferences` schon 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_parameters` bleibt 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. + +## 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.py` in das Arbeitsverzeichnis + legte, die beim Import eines Standardmoduls mitgeladen wurde („confused environment"). + Ein freigegebenes Skript läuft deshalb **aus einer schreibgeschützten, sauberen Kopie**, + mit `python -I` (kein Arbeitsverzeichnis, kein `PYTHONPATH` im 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:** + 1. **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 aber `requests`"). + 2. **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. + 3. **Freigabe durch den Menschen**, mit Vorprüfung, Einschätzung und Diff zur vorigen + Fassung vor Augen. +- **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 + `:online` bei ausgeschalteter Websuche", „Agent darf Skripte schreiben, Runner fehlt". + Vorbild `openclaw 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 | + +1. **#651 mit #659, #652, #653** — größter Nutzen je Aufwand, braucht nur das Vorhandene und die + Messenger-Freigabe (#644). +2. **#654** — harte Vorbedingung für Skripte, Shell (#196) und MCP-stdio-Server (#197); + steht deshalb vor beiden. +3. **#655** und **#656**. +4. **#657** — mit #198, weil Skripte mit den Skills kommen. +5. **#658** — zuletzt, auf #204 aufbauend. Bis dahin prüft bei Skripten der Mensch + allein, mit der deterministischen Vorprüfung.