Sicherheitsrunde dokumentiert: vier offene Entscheidungen, Kleinkram, bewusste Nicht-Befunde

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
marcusH
2026-07-19 23:50:35 +02:00
parent e56b5698d6
commit 3bb30dbddd
+73
View File
@@ -43,6 +43,79 @@
Shell schreiben. Das Markdown-Rendering ist jetzt entschärft
(`src/markdown.ts`), aber eine echte CSP wäre die Schranke dahinter.
Braucht eine Runde Prüfen, was inline benötigt wird (Themes, xterm).
Schon ein `default-src 'self'` würde auswärtige Requests und die
Fremdnavigation unabhängig vom Sanitizer abschneiden.
## Aus der Sicherheitsrunde 2026-07-19 (vier Angriffsflächen geprüft)
Behoben und gepusht (6d44f77): Befehlsinjektion im SessionStart-Hook über den
Projektpfad, ungeprüfter Pool-Name als `CLAUDE_CONFIG_DIR`, `check_name` gegen
Steuerzeichen (`.desktop`-Injektion), Bild-Beacon im Panel. Dazu `cargo audit`
nachgeholt: `plist` auf 1.10.0, `quick-xml` auf 0.41.0 im Laufzeitpfad.
Offen sind die vier Punkte, die eine Designentscheidung brauchen:
- [ ] **`term_start` prüft das Fenster-Label nicht (`terminal.rs:96-211`).**
Jedes Fenster des Terminal-Prozesses kann sich selbst in die Terminals-Map
eintragen (Schlüssel ist `window.label()`, Zeile 207-210) und danach per
`term_write` in eine frisch gestartete Shell schreiben. Damit ist auch das
abgelöste Panel-Fenster gefährlich, nicht nur das angedockte — und jedes
Skript im Webview wird zu Codeausführung, auch ohne XSS.
Zu entscheiden: Soll das Panel-Fenster je ein eigenes Terminal starten
dürfen? Wenn nein, ist die Prüfung auf `term-*` ein enger Fix.
Strukturell dahinter: Die Fenster-ACL scheint für App-Commands nicht zu
greifen (`gen/schemas/acl-manifests.json` enthält kein App-Manifest) —
**vor dem Bauen darauf verifizieren**, die beiden Prüfagenten waren sich
in diesem Punkt uneins.
- [ ] **`write_panel(path)` liest jede Datei, ohne Rückfrage (`mcp.rs:256-259`).**
Keine Prüfung gegen Projektordner oder Archiv-Home. Das Tool steht in
`PANEL_PERMISSIONS` (`pool.rs:185-188`), läuft also prompt-frei — und
umgeht damit das Read-Permission-Modell von Claude Code (`~/.ssh/id_rsa`,
`.credentials.json`, fremde `.env`). Rückkanal zum Modell besteht über
`write_panel``archive_panel``search_archive`.
Zu entscheiden: Allowlist (Projektordner + Archiv-Home, nach
`canonicalize`) oder `path` aus der prompt-freien Freigabe nehmen.
Zusätzlich fehlt ein Größenlimit (`path=/dev/zero` hängt den Prozess).
- [ ] **`archive_panel(dir)` vergibt dauerhaft Schreibrechte (`archive.rs:33-91`).**
`dir` ist nicht nur Ablageort: Über `set_project_archive_home`
`add_archive_permission` landet `additionalDirectories += dir` **und**
`allow += "Edit(dir/**)"` in der `.claude/settings.json` des Projekts.
Der einzige Guard (archive.rs:41) lehnt nur Vorfahren des Home ab —
`~/.claude` passiert, womit die nächste Session eigene **Hooks** schreiben
darf. `create_dir_all` legt das Ziel vorher an.
Vorschlag: `dir` aus dem MCP-Tool entfernen, Archiv-Home nur über die UI.
- [ ] **Nicht-atomare Schreibvorgänge auf fremde Dateien.**
Überall `fs::write` (truncate + write), nirgends temp + `rename`.
Betrifft u. a. die `.claude/settings.json` der Projekte, Claudes
`.claude.json` in den Pools (`pool.rs:289`), die Registry und die
App-Settings. Die Leseseite haben wir gehärtet, die Schreibseite nicht:
Absturz oder volle Platte hinterlässt abgeschnittenes JSON in Dateien,
die der App nicht gehören.
Kleinere Punkte aus derselben Runde, bewusst zurückgestellt:
`panel_file` und Geschwister (`paths.rs:55-84`) ohne `check_name` (zweite
Linie); `write_secret_file` (`unix.rs:48-55`) schreibt erst mit umask-Rechten
und setzt danach 0600, `create_new` mit Modus löst das samt Symlink-Frage;
API-Key steht unter macOS kurz in der Prozess-Kommandozeile
(`macos.rs:101-103`, `ps`-sichtbar, Linux/Windows nicht betroffen); die PTY-Umgebung
wird nicht bereinigt (`terminal.rs:134-144`, kein `env_clear` — ein
`ANTHROPIC_API_KEY` aus dem Shell-Profil sticht den Pool-`apiKeyHelper`);
Bidi-/Zero-Width-Zeichen in den Befehlskacheln (`commands-view.ts:123`), was
Anzeige und Zwischenablage auseinanderlaufen lässt.
Ausdrücklich **kein** Handlungsbedarf (Stand 2026-07-19): `sync_all_desktops`
räumt `aicontrol-*.desktop` auf — der Präfix gehört uns. Falls es je stört,
wäre `art.lintus.`-Präfix die saubere Variante.
Nicht als Sicherheitsgrenze missverstehen: Pools trennen Konfiguration, nicht
Zugriff. Die Keychain-Einträge sind bewusst über `/usr/bin/security` angelegt,
damit der `apiKeyHelper` promptfrei liest — womit jeder Prozess des Nutzers
jeden Pool-Key lesen kann. Beim Design so gewollt, aber nichts, worauf man
Isolationsversprechen bauen sollte.
- [ ] **`write_app_setting` verliert die übrigen App-Settings (`settings.rs:71`).**
Dieselbe Fehlerklasse wie die `.claude.json` in `pool.rs`, nur eine Datei