You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ein neues form-Feld bzw. eine Feld-Capability: ein typisiertes Eingabefeld, dessen Wert beim Submit (affirmativer Button, nicht Cancel) in eine vom Agent vorgegebene Datei geschrieben wird. secret ist einer der Eingabetypen.
Ziel ist Bequemlichkeit: dem Agent einen sauberen Weg geben, User-Input (besonders Secrets) an seinen Bestimmungsort zu bringen — statt fragiler, geratener Shell-Scripte (siehe Praxisbeispiel unten) oder Arbeitsverweigerung, weil ein Secret nicht in die Session darf. Kein garantierter Schutz vor Agent-Zugriff (wer das braucht, trägt das Secret selbst ein), sondern QoL mit ehrlich dokumentierten Grenzen.
Constraint: secret ⇒ nur schreiben, Wert wird nie an den Agent zurückgegeben. Für non-secret ist der File-Write reiner Komfort (der Agent hat den Wert ohnehin). → target ist eine optionale Eigenschaft pro Feld, orthogonal zum Typ.
Schreib-Modi (explizit, NICHT aus Datei-Existenz abgeleitet)
Modus aus „Datei existiert?" abzuleiten ist ein Footgun: bei Pfad-Tippfehler/Race kippt sonst still das Verhalten. Daher deklariert der Agent mode explizit; Existenz ist nur geprüfte Vorbedingung:
mode
Vorbedingung
Verhalten
Fehlerfall
create
Datei fehlt (oder overwrite:true)
Datei = roher Eingabewert
existiert ohne overwrite → Fehler
substitute
Datei da, Platzhalter genau 1×
ersetzt den Agent-vorgegebenen Platzhalter durch den Wert; format-agnostisch (YAML/TOML/JSON/INI/…), da reine String-Substitution
Kein beliebiger Host. Das einzige zulässige Schreibziel ist die Maschine, auf der die Agent-Session läuft:
Lokale Session → lokaler Dateipfad auf dem Mac (aiui schreibt direkt).
Remote-Session (SSH) → genau der registrierte Remote, auf dem der Agent läuft (aiui schreibt via vorhandenem SSH-Pfad dorthin zurück; der Wert reist Keyboard → lokales aiui → scp → Remote-Datei, nie durch den Agent-Kontext).
Damit ist Exfiltration auf einen fremden Host strukturell ausgeschlossen — der Agent kann target nicht auf attacker@evil:/exfil zeigen.
Pflicht: User-Freigabe pro Dateioperation
Jede Schreiboperation wird dem User im Dialog zur Freigabe vorgelegt — der affirmative Button ist die Freigabe. Angezeigt wird das aufgelöste Ziel + Modus + Preview:
Schreibe secret nach byte5ai-host:~/.config/foo/key (mode: create, 0600) — [Speichern] [Abbrechen]
Begründung (der eigentliche Sicherheits-Gedanke): aiui ist ein privilegierter Mittelsmann. aiui schreibt mit der SSH-/Datei-Identität des Users; ein sandboxed Agent könnte über aiui Pfade erreichen, die sein eigener direkter Zugriff oder sein Approval-Gate blockiert — klassischer Confused-Deputy. Die zwingende User-Freigabe pro Op schließt diese Lücke: der User ist der Autorisierungs-Backstop und sieht zudem einen falschen Pfad, bevor er bestätigt.
Mechanik
Wert bei Submit in-memory unter opakem Handle, kein Plaintext-tmp-File.
aiui schreibt atomar (tmp + rename lokal; analog remote).
Tool-Result: {written:true, target, bytes} — bei secretohne Wert; bei non-secret optional Wert + Status.
Fehler (Permission, Host weg, Platzhalter nicht gefunden, create auf existierende Datei ohne overwrite) → {written:false, error} an den Agent und sichtbar im Dialog. Kein stiller Erfolg.
In-memory-Eintrag verfällt direkt nach dem Write (oder per TTL) → kein Cleanup-Problem.
Umsetzung: form erweitern, kein neues Widget
Forms haben bereits Button(s), Validierung, Layout, Submit/Cancel. „Referenzierter Button" = affirmativer Submit (Cancel → kein Write). Neu: optionale Feld-Eigenschaft target + Eingabetyp secret. Spart eine parallele Code-Fläche.
Ein Agent präsentierte dieses Snippet, um einen PAT „am Chat vorbei" zu speichern:
touch ~/.github_tokens && chmod 600 ~/.github_tokens
read -s -p "GitHub PAT für byte5ai: " PAT &&echo
( grep -v '^byte5ai='~/.github_tokens 2>/dev/null;printf'byte5ai=%s\n'"$PAT" ) >~/.github_tokens.tmp
mv ~/.github_tokens.tmp ~/.github_tokens
chmod 600 ~/.github_tokens
unset PAT
Auf dem Host ist ~/.github_tokens aber ein Verzeichnis mit je einer Datei pro Token, keine flache key=value-Datei. Das Snippet hätte: chmod 600 aufs Verzeichnis (→ x-Bit weg → alle Token unlesbar), eine falsch formatierte stray-Datei im Verzeichnis angelegt und den PAT nie am richtigen Ort gespeichert. Der Agent hielt das Secret per read -s/unset bereits aus dem Kontext — das Problem ist nicht Geheimhaltung, sondern dass der Agent die Storage-Konvention raten muss und danebenliegt. Das secret-Feld ersetzt das durch einen nativen Dialog + korrekten, atomaren Write, dessen Ziel der User vorher sieht.
Phasing
v1: lokal create + substitute; Remote create (scp auf den Agent-Host).
v1.1: Remote substitute (read-modify-write über ssh) — der teurere, sensiblere Teil.
Offene Fragen
Session→Remote-Mapping: Bei Remote-Sessions kommt die /render-Anfrage über den Reverse-Tunnel von 127.0.0.1 — wie mappt aiui sie auf den richtigen registrierten Remote? Vermutlich muss das mcp-stdio-Child sich selbst identifizieren. Implementierungs-Detailfrage.
Mehrere Felder mit target: mehrere Writes; bei selber Datei mehrere Platzhalter in einem Pass; Per-Target-Ergebnis + Reihenfolge/Atomarität über mehrere Dateien.
Validierung von int/float/string clientseitig vor Button-Enable.
Was & warum (QoL, nicht Security-Garantie)
Ein neues
form-Feld bzw. eine Feld-Capability: ein typisiertes Eingabefeld, dessen Wert beim Submit (affirmativer Button, nicht Cancel) in eine vom Agent vorgegebene Datei geschrieben wird.secretist einer der Eingabetypen.Ziel ist Bequemlichkeit: dem Agent einen sauberen Weg geben, User-Input (besonders Secrets) an seinen Bestimmungsort zu bringen — statt fragiler, geratener Shell-Scripte (siehe Praxisbeispiel unten) oder Arbeitsverweigerung, weil ein Secret nicht in die Session darf. Kein garantierter Schutz vor Agent-Zugriff (wer das braucht, trägt das Secret selbst ein), sondern QoL mit ehrlich dokumentierten Grenzen.
Zwei orthogonale Achsen
string(maxlen, optional pattern),int(min/max),float(min/max),secret(maskiert), …Constraint:
secret⇒ nur schreiben, Wert wird nie an den Agent zurückgegeben. Für non-secret ist der File-Write reiner Komfort (der Agent hat den Wert ohnehin). →targetist eine optionale Eigenschaft pro Feld, orthogonal zum Typ.Schreib-Modi (explizit, NICHT aus Datei-Existenz abgeleitet)
Modus aus „Datei existiert?" abzuleiten ist ein Footgun: bei Pfad-Tippfehler/Race kippt sonst still das Verhalten. Daher deklariert der Agent
modeexplizit; Existenz ist nur geprüfte Vorbedingung:createoverwrite:true)overwrite→ FehlersubstituteZielort — IMMER der Host, auf dem der Agent läuft
Kein beliebiger Host. Das einzige zulässige Schreibziel ist die Maschine, auf der die Agent-Session läuft:
Damit ist Exfiltration auf einen fremden Host strukturell ausgeschlossen — der Agent kann
targetnicht aufattacker@evil:/exfilzeigen.Pflicht: User-Freigabe pro Dateioperation
Jede Schreiboperation wird dem User im Dialog zur Freigabe vorgelegt — der affirmative Button ist die Freigabe. Angezeigt wird das aufgelöste Ziel + Modus + Preview:
Begründung (der eigentliche Sicherheits-Gedanke): aiui ist ein privilegierter Mittelsmann. aiui schreibt mit der SSH-/Datei-Identität des Users; ein sandboxed Agent könnte über aiui Pfade erreichen, die sein eigener direkter Zugriff oder sein Approval-Gate blockiert — klassischer Confused-Deputy. Die zwingende User-Freigabe pro Op schließt diese Lücke: der User ist der Autorisierungs-Backstop und sieht zudem einen falschen Pfad, bevor er bestätigt.
Mechanik
{written:true, target, bytes}— beisecretohne Wert; bei non-secret optional Wert + Status.createauf existierende Datei ohneoverwrite) →{written:false, error}an den Agent und sichtbar im Dialog. Kein stiller Erfolg.Umsetzung:
formerweitern, kein neues WidgetForms haben bereits Button(s), Validierung, Layout, Submit/Cancel. „Referenzierter Button" = affirmativer Submit (Cancel → kein Write). Neu: optionale Feld-Eigenschaft
target+ Eingabetypsecret. Spart eine parallele Code-Fläche.{ "kind": "secret", "name": "github_pat", "label": "GitHub PAT für byte5ai", "target": { "mode": "create", "path": "~/.github_tokens/byte5ai", "perm": "0600", "overwrite": true } }Praxisbeispiel (Motivation)
Ein Agent präsentierte dieses Snippet, um einen PAT „am Chat vorbei" zu speichern:
Auf dem Host ist
~/.github_tokensaber ein Verzeichnis mit je einer Datei pro Token, keine flachekey=value-Datei. Das Snippet hätte:chmod 600aufs Verzeichnis (→ x-Bit weg → alle Token unlesbar), eine falsch formatierte stray-Datei im Verzeichnis angelegt und den PAT nie am richtigen Ort gespeichert. Der Agent hielt das Secret perread -s/unsetbereits aus dem Kontext — das Problem ist nicht Geheimhaltung, sondern dass der Agent die Storage-Konvention raten muss und danebenliegt. Dassecret-Feld ersetzt das durch einen nativen Dialog + korrekten, atomaren Write, dessen Ziel der User vorher sieht.Phasing
create+substitute; Remotecreate(scp auf den Agent-Host).substitute(read-modify-write über ssh) — der teurere, sensiblere Teil.Offene Fragen
/render-Anfrage über den Reverse-Tunnel von127.0.0.1— wie mappt aiui sie auf den richtigen registrierten Remote? Vermutlich muss das mcp-stdio-Child sich selbst identifizieren. Implementierungs-Detailfrage.is_valid_host_alias+--end-of-options (sonst kommt die SSH option injection via unvalidated host_alias from Settings UI #52-Option-Injection-Fläche zurück), auch bei Beschränkung auf registrierte Remotes.target: mehrere Writes; bei selber Datei mehrere Platzhalter in einem Pass; Per-Target-Ergebnis + Reihenfolge/Atomarität über mehrere Dateien.int/float/stringclientseitig vor Button-Enable.