fix(node-host): fail closed on unbound interpreter approvals

This commit is contained in:
Peter Steinberger
2026-03-11 02:35:47 +00:00
parent 72b0e00eab
commit daaf211e20
6 changed files with 201 additions and 32 deletions

View File

@@ -104,6 +104,7 @@ Treat Gateway and node as one operator trust domain, with different roles:
- A caller authenticated to the Gateway is trusted at Gateway scope. After pairing, node actions are trusted operator actions on that node.
- `sessionKey` is routing/context selection, not per-user auth.
- Exec approvals (allowlist + ask) are guardrails for operator intent, not hostile multi-tenant isolation.
- Exec approvals bind exact request context and best-effort direct local file operands; they do not semantically model every runtime/interpreter loader path. Use sandboxing and host isolation for strong boundaries.
If you need hostile-user isolation, split trust boundaries by OS user/host and run separate gateways.
@@ -370,6 +371,7 @@ If a macOS node is paired, the Gateway can invoke `system.run` on that node. Thi
- Requires node pairing (approval + token).
- Controlled on the Mac via **Settings → Exec approvals** (security + ask + allowlist).
- Approval mode binds exact request context and, when possible, one concrete local script/file operand. If OpenClaw cannot identify exactly one direct local file for an interpreter/runtime command, approval-backed execution is denied rather than promising full semantic coverage.
- If you dont want remote execution, set security to **deny** and remove node pairing for that Mac.
## Dynamic skills (watcher / remote nodes)

View File

@@ -54,6 +54,15 @@ forwards `exec` calls to the **node host** when `host=node` is selected.
- **Node host**: executes `system.run`/`system.which` on the node machine.
- **Approvals**: enforced on the node host via `~/.openclaw/exec-approvals.json`.
Approval note:
- Approval-backed node runs bind exact request context.
- For direct shell/runtime file executions, OpenClaw also best-effort binds one concrete local
file operand and denies the run if that file changes before execution.
- If OpenClaw cannot identify exactly one concrete local file for an interpreter/runtime command,
approval-backed execution is denied instead of pretending full runtime coverage. Use sandboxing,
separate hosts, or an explicit trusted allowlist/full workflow for broader interpreter semantics.
### Start a node host (foreground)
On the node machine:

View File

@@ -30,9 +30,14 @@ Trust model note:
- Gateway-authenticated callers are trusted operators for that Gateway.
- Paired nodes extend that trusted operator capability onto the node host.
- Exec approvals reduce accidental execution risk, but are not a per-user auth boundary.
- Approved node-host runs also bind canonical execution context: canonical cwd, pinned executable
path when applicable, and interpreter-style script operands. If a bound script changes after
approval but before execution, the run is denied instead of executing drifted content.
- Approved node-host runs bind canonical execution context: canonical cwd, exact argv, env
binding when present, and pinned executable path when applicable.
- For shell scripts and direct interpreter/runtime file invocations, OpenClaw also tries to bind
one concrete local file operand. If that bound file changes after approval but before execution,
the run is denied instead of executing drifted content.
- This file binding is intentionally best-effort, not a complete semantic model of every
interpreter/runtime loader path. If approval mode cannot identify exactly one concrete local
file to bind, it refuses to mint an approval-backed run instead of pretending full coverage.
macOS split:
@@ -259,6 +264,20 @@ For `host=node`, approval requests include a canonical `systemRunPlan` payload.
that plan as the authoritative command/cwd/session context when forwarding approved `system.run`
requests.
## Interpreter/runtime commands
Approval-backed interpreter/runtime runs are intentionally conservative:
- Exact argv/cwd/env context is always bound.
- Direct shell script and direct runtime file forms are best-effort bound to one concrete local
file snapshot.
- If OpenClaw cannot identify exactly one concrete local file for an interpreter/runtime command
(for example package scripts, eval forms, runtime-specific loader chains, or ambiguous multi-file
forms), approval-backed execution is denied instead of claiming semantic coverage it does not
have.
- For those workflows, prefer sandboxing, a separate host boundary, or an explicit trusted
allowlist/full workflow where the operator accepts the broader runtime semantics.
When approvals are required, the exec tool returns immediately with an approval id. Use that id to
correlate later system events (`Exec finished` / `Exec denied`). If no decision arrives before the
timeout, the request is treated as an approval timeout and surfaced as a denial reason.