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-Hostopenclaw-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: false und 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, -r
  • jq: --argfile, --from-file, --library-path, --rawfile, --slurpfile, -L, -f
  • sort: --compress-program, --files0-from, --output, --random-source, --temporary-directory, -T, -o
  • wc: --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

Thematools.exec.safeBinsAllowlist (exec-approvals.json)
ZielEnge stdin-Filter automatisch erlaubenBestimmte Executables explizit vertrauen
Match-TypExecutable-Name + Safe-Bin-argv-PolicyAufgelöstes Executable-Pfad-Glob-Muster
ArgumentbereichEingeschränkt durch Safe-Bin-Profil und Literal-Token-RegelnNur Pfad-Match; Argumente liegen in deiner Verantwortung
Typische Beispielejq, head, tail, wcpython3, node, ffmpeg, benutzerdefinierte CLIs
Beste NutzungRisikoarme Texttransformationen in PipelinesJedes Tool mit breiterem Verhalten oder Seiteneffekten

Konfigurationsort:

  • safeBins kommt aus der Konfiguration (tools.exec.safeBins oder pro-Agent agents.list[].tools.exec.safeBins).
  • safeBinTrustedDirs kommt aus der Konfiguration (tools.exec.safeBinTrustedDirs oder pro-Agent agents.list[].tools.exec.safeBinTrustedDirs).
  • safeBinProfiles kommt aus der Konfiguration (tools.exec.safeBinProfiles oder pro-Agent agents.list[].tools.exec.safeBinProfiles). Pro-Agent-Profilschlüssel überschreiben globale Schlüssel.
  • Allowlist-Einträge liegen in der host-lokalen ~/.openclaw/exec-approvals.json unter agents.<id>.allowlist (oder über Control UI / openclaw approvals allowlist ...).
  • openclaw security audit warnt mit tools.exec.safe_bins_interpreter_unprofiled, wenn Interpreter/Runtime-Bins in safeBins ohne explizite Profile erscheinen.
  • openclaw doctor --fix kann fehlende benutzerdefinierte safeBinProfiles.<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 askFallback zurü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 in exec-approvals.json gespeichert.
  • 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 finished
  • Exec 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 /exec nicht verwenden.
  • /exec security=full ist eine Sitzungs-Level-Komfortfunktion für autorisierte Operatoren und überspringt Genehmigungen bewusst. Um Host-Exec hart zu blockieren, setze die Genehmigungssicherheit auf deny oder verweigere das exec-Tool über Tool-Policy.

Verwandt: