Skip to content

Elevated permissions not resolved in agentCommand path (sessions_spawn, sessions_send, sub-agents) #18834

Description

@brandonshoreai

Bug Description

The agentCommand gateway RPC handler does not call resolveElevatedPermissions() and does not pass bashElevated to the embedded PI agent runner. This causes elevated exec to fail for all sessions dispatched via the gateway agent method, including sub-agents (sessions_spawn), sessions_send, and subagents steer.

Additionally, when a sub-agent fails elevated and announces back to the parent session, the parent's response to that announce also goes through the agentCommand path, causing the parent session's elevated to break until a new channel message (Telegram/BlueBubbles/Webchat) arrives and re-resolves permissions via Path A.

Environment

  • OpenClaw version: 2026.2.15
  • Platform: macOS (Darwin 24.6.0, Apple Silicon)
  • Sandbox mode: all (Docker)
  • Agent config: tools.elevated.enabled: true, agents.list[].tools.elevated.enabled: true, agents.defaults.elevatedDefault: "full", allowFrom: ["*"] at both levels

Steps to Reproduce

  1. Configure an agent with sandbox.mode: "all" and tools.elevated.enabled: true at both global and agent levels
  2. Send a message via a channel (Telegram/BlueBubbles) — elevated works correctly
  3. Have the agent spawn a sub-agent via sessions_spawn with a task that requires elevated exec
  4. Sub-agent attempts elevated: true on an exec call → fails with:
    elevated is not available right now (runtime=sandboxed).
    Failing gates: enabled (tools.elevated.enabled / agents.list[].tools.elevated.enabled)
    
  5. Sub-agent announces failure back to parent
  6. Parent session attempts elevated exec in the context of processing the announce → also fails
  7. A new channel message (Telegram/iMessage) to the parent session restores elevated

Expected Behavior

  • Sub-agents should have elevated resolved based on the parent agent's config (or explicitly disabled with a clear message)
  • The parent session's elevated should never be affected by sub-agent operations
  • agentCommand should call resolveElevatedPermissions() the same way dispatchInboundMessage does

Root Cause Analysis

The Two Dispatch Paths

Path A — Channel messages (works correctly):

dispatchInboundMessage()
  → dispatchReplyFromConfig()
    → resolveElevatedPermissions(cfg, agentId, ctx, provider)  ✅
    → bashElevated = { enabled: true, allowed: true, defaultLevel: "full" }
    → runReplyAgent()
      → runEmbeddedPiAgent({ bashElevated })  ✅

Path B — Gateway agent RPC (broken):

callGateway({ method: "agent" })
  → agentCommand(opts)  ❌ NEVER calls resolveElevatedPermissions()
    → runAgentAttempt(params)  ❌ NO bashElevated in params
      → runEmbeddedPiAgent({ bashElevated: undefined })
        → createExecTool({ elevated: undefined })
          → elevatedAllowed = false  → gate check fails

Affected Code Locations (v2026.2.15)

  1. agentCommand in dist/agent-ryGRIqHy.js (~line 443): Missing resolveElevatedPermissions() call
  2. runAgentAttempt in dist/agent-ryGRIqHy.js (~line 375-441): Does not receive or pass bashElevated to runEmbeddedPiAgent
  3. runEmbeddedPiAgent in dist/subagent-registry-kdTa9uwX.js (~line 58200): Passes params.bashElevated through correctly, but receives undefined
  4. createExecTool in dist/subagent-registry-kdTa9uwX.js (~line 11180): When defaults.elevated is undefined, elevatedAllowed = false, gate check always fails

All Affected Callers

Every caller of callGateway({ method: "agent" }) hits this bug:

  • sessions_spawn (line ~26696) — sub-agent task spawn
  • sessions_send (line ~26329, 26352) — cross-session messaging
  • subagents steer (line ~17111) — steering existing sub-agents
  • runAgentStep (line ~25962) — internal agent step execution
  • Sub-agent memory flush/compaction paths (lines ~27182, 59060, 59334)

Suggested Fix

Add resolveElevatedPermissions() to agentCommand:

// In agentCommand(), before calling runAgentAttempt:
const { enabled: elevatedEnabled, allowed: elevatedAllowed, failures } = 
    resolveElevatedPermissions({ cfg, agentId: sessionAgentId, ctx: runContext, provider: messageChannel });
const resolvedElevatedLevel = elevatedAllowed 
    ? agentCfg?.elevatedDefault ?? "on" 
    : "off";
const bashElevated = {
    enabled: elevatedEnabled,
    allowed: elevatedAllowed,
    defaultLevel: resolvedElevatedLevel ?? "off"
};
// Pass bashElevated to runAgentAttempt → runEmbeddedPiAgent

Alternatively, as defense-in-depth, createExecTool could fall back to resolving elevated from the live config when defaults.elevated is undefined.

Impact

This bug makes elevated access unreliable for any agent using sandbox.mode: "all" with sub-agents. The parent session's elevated breaks every time a sub-agent attempts and fails elevated, requiring a new channel message to restore it. This blocks automated/overnight workflows where no human is available to send a recovery message.

Workaround

Set sandbox.mode: "non-main" for the affected agent so the main session runs on the host and doesn't need elevated. Sub-agents remain sandboxed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions