Files
openclaw/docs/gateway/permission-modes.md
Peter Steinberger 68f17b01cc fix(gateway): permission modes work on rootless sessions via workspace default root (#129994)
* fix(gateway): permission modes work on rootless sessions via workspace default root

Session permission modes hard-required a recorded sessionRoot, which only the
sessions.create RPC ever records. Channel sessions, pre-#124909 rows, and
exec-node sessions are rootless, so runs failed closed with 'session permission
mode requires a recorded session root' (rows poisoned before the #128149 guards
were permanently bricked) and operators could not set a mode on channel
sessions at all.

The mode semantics are root-free; every containment consumer already falls
back to the workspace, and the remote worker launcher already derives its
containment root from placement.remoteWorkspaceDir. Make that the canonical
rule: a recorded sessionRoot pins worktree/explicit-cwd boundaries, and a
rootless session's boundary is the agent's canonical workspace resolved where
the run is prepared.

- embedded runner + compaction: default policy root to realpath(workspace)
  instead of throwing/dropping the mode; bricked rows self-heal
- gateway: delete the patch/create/reset rejection guards and
  session-permission-policy.ts entirely
- codex plugin: helpers take a required defaultRoot (agent workspace fact,
  never a requested thread cwd); delete the four root throws; sandbox context
  for conversation bindings now derives from the agent workspace
- ui: drop the rootless-rejection surface from the permission picker
- docs: permission-modes boundary contract updated

* fix(agents): split workspace path identity out of the kysely state store

Heals main: #116650 made memory-host-sdk/dreaming.ts import
resolveWorkspaceStateIdentity from workspace-state-store, statically pulling
kysely into the memory-core doctor-contract closure and failing the
doctor-contract-closure-guard lane on origin/main. The identity helpers are
pure path/crypto code; move them to workspace-state-identity.ts and repoint
all importers (dreaming, event-store, onboarding recommendations, workspace
migrations, legacy state).

* fix(ui): drop the unused permission picker sessionRoot prop and dead i18n keys

check-prod-types caught the New Session dialog still passing the removed
sessionRoot picker prop; the prop and the permissionControls.rootLabel /
sessionRoot strings have had no consumers since #124301.

* fix(codex): resolve rootless permission boundaries from agent config, not bind cwd

ClawSweeper P1: /codex bind --cwd stores the requested path as the binding
workspaceDir, which the previous commit then trusted as defaultRoot — letting
a bound thread's requested cwd become (and widen) the rootless permission
boundary. resolveConversationAppServerRuntime now owns the fact: it resolves
the selected agent's canonical workspace from config (falling back to the
plugin's configured default workspace), and the caller-supplied
agentWorkspaceDir parameter chain is deleted so no call site can pass a
tainted value. Recovery of recorded roots is unchanged (pinned roots stay
pinned); the moved-history test now proves the bind-cwd clamp lands on the
agent workspace.
2026-08-26 02:25:57 -07:00

2.9 KiB

summary, read_when, title
summary read_when title
Session permission modes, workspace boundaries, and escalation reviewers
Choosing a permission mode for an agent session
Understanding who reviews an exec escalation
Comparing session permissions with sandbox and tool policy
Session permission modes

Session permission modes set one session's filesystem boundary and exec escalation reviewer. The boundary is the session's recorded canonical sessionRoot, or the selected agent's canonical workspace when no root is recorded. The mode determines what may happen inside or outside that boundary.

Mode Filesystem access Exec escalation reviewer
read-only Reads under sessionRoot; mutation tools omitted None; exec is denied
guarded Reads and writes under sessionRoot A human after the allowlist fast path
workspace Reads and writes under sessionRoot LLM review, with human fallback
full Unrestricted filesystem access None

full requires operator.admin. The other modes require operator.write.

Session root and defaults

A permission mode can be set on any session. When a session has a recorded sessionRoot, that canonical path is its filesystem boundary. An explicit working directory and a managed worktree each pin their session's root. When no root is recorded, the boundary defaults to the selected agent's canonical workspace when the run is prepared.

Managed worktree sessions use the worktree checkout as sessionRoot. A nested working directory remains the runtime cwd, so relative paths start there while filesystem containment covers the whole checkout.

A new managed worktree session defaults to workspace when no mode is specified. Other sessions with no recorded mode keep the existing config-driven behavior.

Policy precedence and clamping

An explicit session mode takes precedence over the session's legacy execSecurity and execAsk overrides. When the mode is unset, those fields and the normal global or per-agent configuration continue to work as before.

An explicit full mode is the admin-authorized exception to host approval-file floors: its OpenClaw exec policy remains full with approvals off. Approval-file floors continue to tighten config-driven exec policy, legacy session overrides, unset modes, and every non-full session mode. Sandbox restrictions and tool allow/deny policy remain independent, and a harness may clamp an unsupported mode to a compatible safer policy tuple. Codex also continues to honor externally enforced requirements.toml constraints.

For the independent sandbox, tool-policy, and elevated-exec controls, see Sandbox vs tool policy vs elevated.