From 3bb30dbddd55b2b2995a0c5fe20576602672b7b5 Mon Sep 17 00:00:00 2001 From: marcusH Date: Sun, 19 Jul 2026 23:50:35 +0200 Subject: [PATCH] Sicherheitsrunde dokumentiert: vier offene Entscheidungen, Kleinkram, bewusste Nicht-Befunde Co-Authored-By: Claude Opus 4.8 (1M context) --- OFFENE-PUNKTE.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/OFFENE-PUNKTE.md b/OFFENE-PUNKTE.md index 99f5418..1b480d3 100644 --- a/OFFENE-PUNKTE.md +++ b/OFFENE-PUNKTE.md @@ -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