OpenClaw / Software Protected Execution¶
Audience: operators governing an AI-agent tool executor (OpenClaw or any untrusted proposer) with ADK — #1310 Phase 4. This is the software instance of the domain-neutral Protected Execution Boundary model: the same manifest contract that isolates a ROS actuator or a Kubernetes mutation isolates a privileged local executor.
OpenClaw agent ADK Governed tool executor shell / fs / API
(proposal-only, its own user) ──▶ authorizes ──▶ (owns a private socket) ──▶ side effect
The agent process must NOT directly hold shell/filesystem/deployment credentials or a privileged RPC endpoint. The governed executor listens on a private Unix domain socket it owns; the agent reaches it only by proposing to ADK, which authorizes one action the executor performs.
Validate-only¶
The builtin.unix_permissions provider never chowns, chmods, creates sockets,
or mints credentials (§26). It stats the declared socket and validates its
ownership + mode against the manifest — the security property is that the socket
is owner/group-only (no world access), so the agent’s user cannot connect.
Step 1 — Run the executor under its own user, owning a private socket¶
The governed tool executor runs as a dedicated user (e.g. autonomyops-enforcer).
The simplest provably-safe posture is an owner-only socket — no group or
world access, so no other user can connect:
# executor process, as autonomyops-enforcer:
umask 077 # 0600 socket: owner-only
# … listen on /run/autonomyops/shell-executor.sock …
The OpenClaw agent runs as a different user with no access to that socket and no shell/deployment credentials of its own.
If you need group access (0660 — e.g. so a sidecar in a shared group can
connect), you MUST also declare proposer_identity so the provider can prove the
agent’s user is outside the socket’s group. Group access without that proof
fails closed: a group member could otherwise be the agent itself.
Step 2 — Declare the boundary (deployment manifest, schema v1.8)¶
schema_version: "1.8"
execution_boundaries:
- id: shell_execution
action_kinds: [tool.shell.exec]
adapter:
id: governed_shell_executor
identity: autonomyops-enforcer # the socket's owner
target:
kind: unix.execution_socket
resource: /run/autonomyops/shell-executor.sock
protection:
provider: builtin.unix_permissions
provider_version: "1"
configuration:
socket_path: /run/autonomyops/shell-executor.sock
socket_owner: autonomyops-enforcer
mode: "0600" # owner-only: provably safe
# For 0660 (group access) instead, also declare:
# socket_group: autonomyops-runtime
# proposer_identity: openclaw-agent # proven to be OUTSIDE the group
requirements:
exclusive_enforcement_principal: true
proposer_has_no_direct_access: true
preflight_validation: required
runtime_attestation:
mode: periodic
interval: 30s
Step 3 — Verify (activation + attestation)¶
At activation the provider checks, fail-closed:
the socket exists and is a socket (
socket_unreadable/not_a_socket);it is not world-accessible — no world permission bit lets the agent’s user connect (
world_accessible), so the proposer is blocked;if it grants group access, a declared
proposer_identityis proven to be outside the socket’s group (group_access_unverifiedwhen none is declared,group_bypasswhen the proposer is in the group);it is owned by the declared enforcer (
adapter_not_authorizedotherwise);its mode matches the declaration (
mode_mismatchcatches drift).
A boundary that fails refuses activation with an execution-boundary: reason. If
runtime_attestation is set, the provider re-stats the socket periodically and
marks the boundary unhealthy on drift (e.g. someone chmod o+rw’d it) — which
stops authorizing executable actions until it is corrected and re-attested.
Failure modes¶
Symptom |
Cause |
Fix |
|---|---|---|
|
The socket has world permission bits — any user (the agent) can connect. |
|
|
The socket grants group access ( |
Use owner-only |
|
The declared proposer is in the socket’s group and can connect directly. |
Remove the proposer from the group, or use |
|
The socket is owned by a different user than the declared enforcer. |
|
|
The declared |
Fix |
|
The socket mode drifted from the declared value. |
Restore the declared mode, or update the manifest. |
|
The executor isn’t running, or the path isn’t a socket. |
Start the governed executor so it creates its private socket. |
Note on enforcement¶
ADK validates this boundary; the OS enforces it. The private-socket pattern (a dedicated executor user + an owner/group-only socket + a separate agent user) is what actually prevents the agent from executing directly. ADK’s role is to prove that isolation is in place, bind each governed decision to it, and fail closed when it is not — it does not itself own the credential or the socket.