Exec-Genehmigungen
Exec-Genehmigungen sind die Companion-App-/Node-Host-Sicherheitsschranke, um einem gesandboxten Agenten
Befehle auf einem echten Host (gateway oder node) ausführen zu lassen. Stell dir das wie eine Sicherheitsverriegelung vor:
Befehle werden nur erlaubt, wenn Policy + Allowlist + (optionale) Benutzer-Genehmigung alle übereinstimmen.
Exec-Genehmigungen gelten zusätzlich zu Tool-Policy und Elevated-Gating (es sei denn, Elevated ist auf full gesetzt, was Genehmigungen überspringt).
Die effektive Policy ist die strengere von tools.exec.* und den Genehmigungsstandards; wenn ein Genehmigungsfeld weggelassen wird, wird der tools.exec-Wert verwendet.
Wenn die Companion-App-UI nicht verfügbar ist, wird jede Anfrage, die einen Prompt erfordert, durch den Ask-Fallback aufgelöst (Standard: deny).
Wo es gilt
Exec-Genehmigungen werden lokal auf dem Ausführungshost durchgesetzt:
- Gateway-Host →
openclaw-Prozess auf dem Gateway-Rechner - Node-Host → Node-Runner (macOS Companion App oder Headless Node Host)
Vertrauensmodell-Hinweis:
- Gateway-authentifizierte Aufrufer sind vertrauenswürdige Operatoren für dieses Gateway.
- Gepaarte Nodes erweitern diese vertrauenswürdige Operator-Fähigkeit auf den Node-Host.
- Exec-Genehmigungen reduzieren versehentliche Ausführungsrisiken, sind aber keine Pro-Benutzer-Auth-Grenze.
- Genehmigte Node-Host-Läufe binden kanonischen Ausführungskontext: kanonisches cwd, exaktes argv, env-Bindung wenn vorhanden und gepinnten Executable-Pfad wenn anwendbar.
- Für Shell-Skripte und direkte Interpreter/Runtime-Dateiaufrufe versucht OpenClaw auch, einen konkreten lokalen Dateioperanden zu binden. Wenn diese gebundene Datei nach der Genehmigung, aber vor der Ausführung geändert wird, wird der Lauf abgelehnt, anstatt veränderten Inhalt auszuführen.
- Diese Dateibindung ist bewusst best-effort, kein vollständiges semantisches Modell jedes Interpreter/Runtime-Loader-Pfads. Wenn der Genehmigungsmodus nicht genau eine konkrete lokale Datei zum Binden identifizieren kann, verweigert er die Erstellung eines genehmigungsgestützten Laufs, anstatt vollständige Abdeckung vorzutäuschen.
macOS-Aufteilung:
- Node-Host-Service leitet
system.runüber lokales IPC an die macOS-App weiter. - macOS-App setzt Genehmigungen durch + führt den Befehl im UI-Kontext aus.
Einstellungen und Speicher
Genehmigungen leben in einer lokalen JSON-Datei auf dem Ausführungshost:
~/.openclaw/exec-approvals.json
Beispielschema:
{
"version": 1,
"socket": {
"path": "~/.openclaw/exec-approvals.sock",
"token": "base64url-token"
},
"defaults": {
"security": "deny",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": false
},
"agents": {
"main": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": true,
"allowlist": [
{
"id": "B0C8C0B3-2C2D-4F8A-9A3C-5A4B3C2D1E0F",
"pattern": "~/Projects/**/bin/rg",
"lastUsedAt": 1737150000000,
"lastUsedCommand": "rg -n TODO",
"lastResolvedPath": "/Users/user/Projects/.../bin/rg"
}
]
}
}
}
Policy-Stellschrauben
Security (exec.security)
- deny: alle Host-Exec-Anfragen blockieren.
- allowlist: nur in der Allowlist eingetragene Befehle erlauben.
- full: alles erlauben (entspricht Elevated).
Ask (exec.ask)
- off: niemals nachfragen.
- on-miss: nur nachfragen, wenn die Allowlist nicht matcht.
- always: bei jedem Befehl nachfragen.
Ask-Fallback (askFallback)
Wenn ein Prompt erforderlich ist, aber keine UI erreichbar, entscheidet der Fallback:
- deny: blockieren.
- allowlist: nur erlauben, wenn die Allowlist matcht.
- full: erlauben.
Allowlist (pro Agent)
Allowlists sind pro Agent. Wenn mehrere Agenten existieren, wechsle in der macOS-App, welchen
Agenten du bearbeitest. Muster sind case-insensitive Glob-Matches.
Muster sollten sich auf Binary-Pfade auflösen (reine Basename-Einträge werden ignoriert).
Legacy-agents.default-Einträge werden beim Laden nach agents.main migriert.
Beispiele:
~/Projects/**/bin/peekaboo~/.local/bin/*/opt/homebrew/bin/rg
Jeder Allowlist-Eintrag verfolgt:
- ID stabile UUID für UI-Identität (optional)
- Zuletzt verwendet Zeitstempel
- Zuletzt verwendeter Befehl
- Zuletzt aufgelöster Pfad
Skill-CLIs automatisch erlauben
Wenn Skill-CLIs automatisch erlauben aktiviert ist, werden von bekannten Skills referenzierte Executables
auf Nodes als allowlisted behandelt (macOS Node oder Headless Node Host). Dies nutzt
skills.bins über den Gateway-RPC, um die Skill-Bin-Liste abzurufen. Deaktiviere dies, wenn du strikte manuelle Allowlists möchtest.
Wichtige Vertrauenshinweise:
- Dies ist eine implizite Komfort-Allowlist, getrennt von manuellen Pfad-Allowlist-Einträgen.
- Es ist für vertrauenswürdige Operator-Umgebungen gedacht, in denen Gateway und Node in der gleichen Vertrauensgrenze liegen.
- Wenn du striktes explizites Vertrauen benötigst, behalte
autoAllowSkills: falseund verwende nur manuelle Pfad-Allowlist-Einträge.
Safe Bins (nur stdin)
tools.exec.safeBins definiert eine kleine Liste von stdin-only Binaries (zum Beispiel jq),
die im Allowlist-Modus ohne explizite Allowlist-Einträge laufen können. Safe Bins lehnen
positionelle Dateiargumente und pfadartige Tokens ab, sodass sie nur auf dem eingehenden Stream arbeiten können.
Behandle dies als einen engen Schnellpfad für Stream-Filter, nicht als eine allgemeine Vertrauensliste.
Füge keine Interpreter- oder Runtime-Binaries (zum Beispiel python3, node, ruby, bash, sh, zsh) zu safeBins hinzu.
Wenn ein Befehl Code auswerten, Unterbefehle ausführen oder Dateien lesen kann, bevorzuge explizite Allowlist-Einträge und halte Genehmigungsprompts aktiviert.
Benutzerdefinierte Safe Bins müssen ein explizites Profil in tools.exec.safeBinProfiles.<bin> definieren.
Die Validierung ist deterministisch allein aus der argv-Form (keine Host-Dateisystem-Existenzprüfungen), was
Datei-Existenz-Oracle-Verhalten durch Allow/Deny-Unterschiede verhindert.
Dateiorientierte Optionen werden für Standard-Safe-Bins abgelehnt (zum Beispiel sort -o, sort --output,
sort --files0-from, sort --compress-program, sort --random-source,
sort --temporary-directory/-T, wc --files0-from, jq -f/--from-file,
grep -f/--file).
Safe Bins erzwingen auch explizite pro-Binary-Flag-Policy für Optionen, die stdin-only-Verhalten brechen
(zum Beispiel sort -o/--output/--compress-program und grep-Rekursiv-Flags).
Long Options werden in safe-bin-Modus fail-closed validiert: unbekannte Flags und mehrdeutige
Abkürzungen werden abgelehnt.
Abgelehnte Flags nach Safe-Bin-Profil:
grep:--dereference-recursive,--directories,--exclude-from,--file,--recursive,-R,-d,-f,-rjq:--argfile,--from-file,--library-path,--rawfile,--slurpfile,-L,-fsort:--compress-program,--files0-from,--output,--random-source,--temporary-directory,-T,-owc:--files0-from
Safe Bins erzwingen auch, dass argv-Tokens zur Ausführungszeit als literaler Text behandelt werden (kein Globbing
und keine $VARS-Expansion) für stdin-only-Segmente, sodass Muster wie * oder $HOME/... nicht
genutzt werden können, um Dateilesevorgänge einzuschleusen.
Safe Bins müssen auch aus vertrauenswürdigen Binary-Verzeichnissen aufgelöst werden (Systemstandards plus optionales
tools.exec.safeBinTrustedDirs). PATH-Einträge werden nie automatisch als vertrauenswürdig eingestuft.
Standard-vertrauenswürdige Safe-Bin-Verzeichnisse sind bewusst minimal: /bin, /usr/bin.
Wenn deine Safe-Bin-Executable in Paketmanager-/Benutzerpfaden liegt (zum Beispiel
/opt/homebrew/bin, /usr/local/bin, /opt/local/bin, /snap/bin), füge sie explizit
zu tools.exec.safeBinTrustedDirs hinzu.
Shell-Verkettung und Umleitungen werden im Allowlist-Modus nicht automatisch erlaubt.
Shell-Verkettung (&&, ||, ;) ist erlaubt, wenn jedes Top-Level-Segment die Allowlist erfüllt
(einschließlich Safe Bins oder Skill-Auto-Allow). Umleitungen bleiben im Allowlist-Modus nicht unterstützt.
Befehlssubstitution ($() / Backticks) wird beim Allowlist-Parsing abgelehnt, auch innerhalb
doppelter Anführungszeichen; verwende einfache Anführungszeichen, wenn du literalen $()-Text brauchst.
Auf macOS-Companion-App-Genehmigungen wird roher Shell-Text mit Shell-Steuer- oder Expansionssyntax
(&&, ||, ;, |, `, $, <, >, (, )) als Allowlist-Miss behandelt, es sei denn
die Shell-Binary selbst ist in der Allowlist.
Für Shell-Wrapper (bash|sh|zsh ... -c/-lc) werden anforderungsbezogene env-Überschreibungen auf eine
kleine explizite Allowlist reduziert (TERM, LANG, LC_*, COLORTERM, NO_COLOR, FORCE_COLOR).
Für Allow-Always-Entscheidungen im Allowlist-Modus speichern bekannte Dispatch-Wrapper
(env, nice, nohup, stdbuf, timeout) innere Executable-Pfade anstelle von Wrapper-
Pfaden. Shell-Multiplexer (busybox, toybox) werden ebenfalls für Shell-Applets (sh, ash,
etc.) entpackt, sodass innere Executables statt Multiplexer-Binaries gespeichert werden. Wenn ein Wrapper oder
Multiplexer nicht sicher entpackt werden kann, wird kein Allowlist-Eintrag automatisch gespeichert.
Standard-Safe-Bins: jq, cut, uniq, head, tail, tr, wc.
grep und sort sind nicht in der Standardliste. Wenn du dich dafür entscheidest, behalte explizite Allowlist-Einträge für
ihre Nicht-stdin-Workflows.
Für grep im Safe-Bin-Modus gib das Muster mit -e/--regexp an; die positionelle Musterform wird
abgelehnt, damit Dateioperanden nicht als mehrdeutige Positionsargumente eingeschmuggelt werden können.
Safe Bins versus Allowlist
| Thema | tools.exec.safeBins | Allowlist (exec-approvals.json) |
|---|---|---|
| Ziel | Enge stdin-Filter automatisch erlauben | Bestimmte Executables explizit vertrauen |
| Match-Typ | Executable-Name + Safe-Bin-argv-Policy | Aufgelöstes Executable-Pfad-Glob-Muster |
| Argumentbereich | Eingeschränkt durch Safe-Bin-Profil und Literal-Token-Regeln | Nur Pfad-Match; Argumente liegen in deiner Verantwortung |
| Typische Beispiele | jq, head, tail, wc | python3, node, ffmpeg, benutzerdefinierte CLIs |
| Beste Nutzung | Risikoarme Texttransformationen in Pipelines | Jedes Tool mit breiterem Verhalten oder Seiteneffekten |
Konfigurationsort:
safeBinskommt aus der Konfiguration (tools.exec.safeBinsoder pro-Agentagents.list[].tools.exec.safeBins).safeBinTrustedDirskommt aus der Konfiguration (tools.exec.safeBinTrustedDirsoder pro-Agentagents.list[].tools.exec.safeBinTrustedDirs).safeBinProfileskommt aus der Konfiguration (tools.exec.safeBinProfilesoder pro-Agentagents.list[].tools.exec.safeBinProfiles). Pro-Agent-Profilschlüssel überschreiben globale Schlüssel.- Allowlist-Einträge liegen in der host-lokalen
~/.openclaw/exec-approvals.jsonunteragents.<id>.allowlist(oder über Control UI /openclaw approvals allowlist ...). openclaw security auditwarnt mittools.exec.safe_bins_interpreter_unprofiled, wenn Interpreter/Runtime-Bins insafeBinsohne explizite Profile erscheinen.openclaw doctor --fixkann fehlende benutzerdefiniertesafeBinProfiles.<bin>-Einträge als{}scaffolden (überprüfe und verschärfe danach). Interpreter/Runtime-Bins werden nicht automatisch scaffolded.
Beispiel für benutzerdefiniertes Profil:
{
tools: {
exec: {
safeBins: ["jq", "myfilter"],
safeBinProfiles: {
myfilter: {
minPositional: 0,
maxPositional: 0,
allowedValueFlags: ["-n", "--limit"],
deniedFlags: ["-f", "--file", "-c", "--command"],
},
},
},
},
}
Control-UI-Bearbeitung
Verwende die Control UI → Nodes → Exec-Genehmigungen-Karte, um Standardwerte, pro-Agent- Überschreibungen und Allowlists zu bearbeiten. Wähle einen Scope (Standardwerte oder einen Agenten), passe die Policy an, füge Allowlist-Muster hinzu/entferne sie, dann Speichern. Die UI zeigt zuletzt verwendet-Metadaten pro Muster, damit du die Liste sauber halten kannst.
Der Zielselektor wählt Gateway (lokale Genehmigungen) oder einen Node. Nodes
müssen system.execApprovals.get/set ankündigen (macOS App oder Headless Node Host).
Wenn ein Node Exec-Genehmigungen noch nicht ankündigt, bearbeite seine lokale
~/.openclaw/exec-approvals.json direkt.
CLI: openclaw approvals unterstützt Gateway- oder Node-Bearbeitung (siehe Approvals CLI).
Genehmigungsablauf
Wenn ein Prompt erforderlich ist, sendet das Gateway exec.approval.requested an Operator-Clients.
Die Control UI und macOS App lösen es über exec.approval.resolve auf, dann leitet das Gateway die
genehmigte Anfrage an den Node Host weiter.
Für host=node enthalten Genehmigungsanfragen einen kanonischen systemRunPlan-Payload. Das Gateway verwendet
diesen Plan als autoritative Befehls-/CWD-/Sitzungskontextquelle beim Weiterleiten genehmigter system.run-
Anfragen.
Interpreter/Runtime-Befehle
Genehmigungsgestützte Interpreter/Runtime-Läufe sind bewusst konservativ:
- Exakter argv/cwd/env-Kontext wird immer gebunden.
- Direkte Shell-Skript- und direkte Runtime-Dateiformate werden best-effort an einen konkreten lokalen Datei-Snapshot gebunden.
- Gängige Paketmanager-Wrapper-Formen, die sich dennoch auf eine direkte lokale Datei auflösen (zum Beispiel
pnpm exec,pnpm node,npm exec,npx), werden vor der Bindung entpackt. - Wenn OpenClaw nicht genau eine konkrete lokale Datei für einen Interpreter/Runtime-Befehl identifizieren kann (zum Beispiel Paketskripte, eval-Formen, Runtime-spezifische Loader-Ketten oder mehrdeutige Multi-Datei- Formen), wird genehmigungsgestützte Ausführung abgelehnt, anstatt semantische Abdeckung zu behaupten, die nicht vorhanden ist.
- Für diese Workflows bevorzuge Sandboxing, eine separate Host-Grenze oder einen expliziten vertrauenswürdigen Allowlist-/Full-Workflow, bei dem der Operator die breitere Runtime-Semantik akzeptiert.
Wenn Genehmigungen erforderlich sind, kehrt das Exec-Tool sofort mit einer Genehmigungs-ID zurück. Verwende diese ID zur
Korrelation späterer Systemereignisse (Exec finished / Exec denied). Wenn keine Entscheidung vor dem
Timeout eintrifft, wird die Anfrage als Genehmigungstimeout behandelt und als Ablehnungsgrund angezeigt.
Der Bestätigungsdialog enthält:
- Befehl + Argumente
- cwd
- Agent-ID
- Aufgelöster Executable-Pfad
- Host- + Policy-Metadaten
Aktionen:
- Einmal erlauben → jetzt ausführen
- Immer erlauben → zur Allowlist hinzufügen + ausführen
- Ablehnen → blockieren
Genehmigungsweiterleitung an Chat-Kanäle
Du kannst Exec-Genehmigungsprompts an jeden Chat-Kanal weiterleiten (einschließlich Plugin-Kanäle) und
sie mit /approve genehmigen. Dies nutzt die normale ausgehende Zustellpipeline.
Konfiguration:
{
approvals: {
exec: {
enabled: true,
mode: "session", // "session" | "targets" | "both"
agentFilter: ["main"],
sessionFilter: ["discord"], // Teilstring oder Regex
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}
Im Chat antworten:
/approve <id> allow-once
/approve <id> allow-always
/approve <id> deny
Eingebaute Chat-Genehmigungsclients
Discord und Telegram können auch als explizite Exec-Genehmigungsclients mit kanalspezifischer Konfiguration fungieren.
- Discord:
channels.discord.execApprovals.* - Telegram:
channels.telegram.execApprovals.*
Diese Clients sind Opt-in. Wenn ein Kanal keine Exec-Genehmigungen aktiviert hat, behandelt OpenClaw diesen Kanal nicht als Genehmigungsoberfläche, nur weil die Konversation dort stattfand.
Gemeinsames Verhalten:
- Nur konfigurierte Genehmiger können genehmigen oder ablehnen
- Der Anfordernde muss kein Genehmiger sein
- Wenn Kanalzustellung aktiviert ist, enthalten Genehmigungsprompts den Befehlstext
- Wenn keine Operator-UI oder konfigurierter Genehmigungsclient die Anfrage annehmen kann, fällt der Prompt auf
askFallbackzurück
Telegram verwendet standardmäßig Genehmiger-DMs (target: "dm"). Du kannst auf channel oder both wechseln, wenn
du möchtest, dass Genehmigungsprompts auch im ursprünglichen Telegram-Chat/Topic erscheinen. Für Telegram-Forum-
Topics behält OpenClaw das Topic für den Genehmigungsprompt und das Post-Genehmigungs-Follow-up bei.
Siehe:
macOS IPC-Flow
Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)
Sicherheitshinweise:
- Unix-Socket-Modus
0600, Token inexec-approvals.jsongespeichert. - Same-UID-Peer-Check.
- Challenge/Response (Nonce + HMAC-Token + Request-Hash) + kurze TTL.
Systemereignisse
Der Exec-Lebenszyklus wird als Systemnachrichten angezeigt:
Exec running(nur wenn der Befehl den Running-Notice-Schwellenwert überschreitet)Exec finishedExec denied
Diese werden nach der Meldung des Events durch den Node in die Sitzung des Agenten gepostet.
Gateway-Host-Exec-Genehmigungen senden die gleichen Lebenszyklus-Events, wenn der Befehl beendet ist (und optional wenn er länger als der Schwellenwert läuft).
Genehmigungsgesteuerte Execs verwenden die Genehmigungs-ID als runId in diesen Nachrichten zur einfachen Korrelation.
Implikationen
- full ist mächtig; bevorzuge Allowlists, wenn möglich.
- ask hält dich in der Schleife und ermöglicht dennoch schnelle Genehmigungen.
- Pro-Agent-Allowlists verhindern, dass die Genehmigungen eines Agenten in andere durchsickern.
- Genehmigungen gelten nur für Host-Exec-Anfragen von autorisierten Absendern. Nicht autorisierte Absender können
/execnicht verwenden. /exec security=fullist eine Sitzungs-Level-Komfortfunktion für autorisierte Operatoren und überspringt Genehmigungen bewusst. Um Host-Exec hart zu blockieren, setze die Genehmigungssicherheit aufdenyoder verweigere dasexec-Tool über Tool-Policy.
Verwandt: