Skip to content

fix(agents): honor effective exec policy for Claude live Bash#86330

Merged
sallyom merged 3 commits into
openclaw:mainfrom
sallyom:sallyom/pr-81971-effective-exec-policy
May 25, 2026
Merged

fix(agents): honor effective exec policy for Claude live Bash#86330
sallyom merged 3 commits into
openclaw:mainfrom
sallyom:sallyom/pr-81971-effective-exec-policy

Conversation

@sallyom

@sallyom sallyom commented May 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #81971. The original live Claude control_request handling fixed the stdio response path, but the Bash allow/deny decision still needed to match OpenClaw's effective exec policy.

This patch:

  • resolves Claude live Bash policy through the effective exec defaults and approval-file tightening path
  • treats OpenClaw's effective exec policy as authoritative over Claude's native permission mode, matching the Codex path
  • updates the public Claude CLI permission-mode docs so raw Claude args are no longer documented as an OpenClaw policy override for managed live sessions
  • normalizes Claude live launches in both directions:
    • effective OpenClaw security=full, ask=off launches Claude with --permission-mode bypassPermissions, even if raw Claude args requested a non-bypass mode
    • restrictive effective OpenClaw policy launches Claude with --permission-mode default, even if raw Claude args requested bypassPermissions or omitted --permission-mode
  • honors session exec overrides, approval defaults, per-agent approvals from explicit agentId or sessionKey, and sandbox-derived defaults
  • forwards sessionEntry through user and cron CLI paths
  • adds regression coverage for restrictive approval defaults, session overrides, explicit-agent approvals, session-key-derived approvals, launch-mode downgrading, omitted Claude permission mode under restrictive OpenClaw policy, and OpenClaw YOLO overriding raw Claude non-bypass mode

Fixes #80819.

Related review context: #81971 and ClawSweeper comment #81971 (comment).

Real Behavior Proof

Ran a local real Claude CLI/API-backed proof against this branch with OpenClaw state isolated in a temporary OPENCLAW_HOME, OPENCLAW_STATE_DIR, and config path. The proof exercised OpenClaw's Claude live stdio bridge through executePreparedCliRun, not a mocked Claude process.

Observed behavior:

  • permissive openclaw effective policy (security=full, ask=off) launched Claude with --permission-mode bypassPermissions
    • permissive case successfully executed a harmless Bash side effect
  • restrictive openclaw effective policy (security=allowlist, ask=on-miss) launched Claude with --permission-mode default
    • restrictive case produced a real Claude native Bash control_request
    • OpenClaw replied with a deny control_response
    • the denied Bash side effect did not happen

Redacted proof summary:

{
  "realClaudeCli": true,
  "tempOpenClawHome": true,
  "allow": {
    "permissionMode": "bypassPermissions",
    "sideEffectObserved": true
  },
  "deny": {
    "permissionMode": "default",
    "bashControlRequests": 1,
    "denyResponses": 1,
    "sideEffectBlocked": true
  }
}

Testing

  • node scripts/run-vitest.mjs src/agents/cli-runner.spawn.test.ts
  • node scripts/run-vitest.mjs src/agents/cli-backends.test.ts src/agents/cli-runner.spawn.test.ts src/cron/isolated-agent/run.session-key-isolation.test.ts src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts
  • pnpm check
  • pnpm check:changelog-attributions
  • .agents/skills/autoreview/scripts/autoreview --mode local --prompt 'Review PR #86330 after fixing the restrictive no-permission-mode path. OpenClaw effective exec policy is authoritative over Claude native permission mode, matching Codex: effective OpenClaw full/off must normalize Claude live to --permission-mode bypassPermissions and allow native Bash even if raw Claude args requested default/acceptEdits; any restrictive effective OpenClaw policy must normalize Claude live to --permission-mode default, including when Claude args omitted --permission-mode, and deny/route native Bash control_request through OpenClaw policy. Check for regressions, compatibility issues, missing tests, and stale PR/comment wording.' --parallel-tests 'node scripts/run-vitest.mjs src/agents/cli-runner.spawn.test.ts src/cron/isolated-agent/run.session-key-isolation.test.ts src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts'

Final autoreview result: autoreview clean: no accepted/actionable findings reported.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: L maintainer Maintainer-authored PR labels May 25, 2026
@clawsweeper

clawsweeper Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed May 25, 2026, 11:15 AM ET / 15:15 UTC.

Summary
The branch routes Claude live native Bash permission requests through OpenClaw effective exec policy, normalizes managed live --permission-mode, forwards sessionEntry into CLI runs, and updates docs, changelog, and regression tests.

PR surface: Source +213, Tests +771, Docs +5. Total +989 across 10 files.

Reproducibility: yes. The linked issue gives a live Claude CLI reproduction path, and source inspection of current main confirms the live JSONL bridge has no control_request response branch; I did not run a live repro in this read-only review.

Review metrics: 1 noteworthy metric.

  • Permission-policy contract: 1 changed. Managed Claude live sessions now normalize raw --permission-mode to OpenClaw effective exec policy, which is compatibility-sensitive before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none

Risk before merge

  • Merging intentionally changes the previously documented raw Claude --permission-mode override behavior for OpenClaw-managed live sessions, so existing users who relied on raw args to steer Claude live permission mode may see different launch behavior.
  • The patch is in the native command-execution security boundary: under effective security=full, ask=off, OpenClaw will normalize Claude live to bypass mode and allow native Bash control requests.
  • The patch changes session-sensitive live-run plumbing by adding policy to the live-session fingerprint and forwarding sessionEntry through user and cron CLI paths.

Maintainer options:

  1. Accept OpenClaw-policy authority (recommended)
    If maintainers agree that managed live sessions must follow OpenClaw effective exec policy over raw Claude args, keep this shape and land after required checks and owner review.
  2. Preserve the old raw-arg contract
    If raw --permission-mode overrides must remain authoritative for live sessions, change the normalization and docs/tests to keep explicit raw args as the user-facing source of truth.
  3. Pause for security-boundary review
    If the native Bash allow path under full/off policy needs broader security review, pause this PR until the permanent boundary is confirmed.

Next step before merge
Manual review is the right lane because the patch is security-sensitive and intentionally changes a documented Claude raw-args override contract; this review found no narrow mechanical repair.

Security
Cleared: No concrete supply-chain issue was found; the diff is security-sensitive because it changes native Bash permission decisions, but restrictive OpenClaw policies are kept out of bypass mode.

Review details

Best possible solution:

Land this as the canonical fix for #80819 after maintainer approval of the OpenClaw-authoritative permission-mode contract and green required checks; otherwise revise code, docs, and tests to preserve the older raw-arg override contract.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked issue gives a live Claude CLI reproduction path, and source inspection of current main confirms the live JSONL bridge has no control_request response branch; I did not run a live repro in this read-only review.

Is this the best way to solve the issue?

Yes, with maintainer sign-off. The PR fixes the implicated bridge and launch-policy path with focused tests and docs, but the raw-args compatibility decision is the part that should remain a human approval gate.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 8da8bc4aadfc.

Label changes

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body contains after-fix live Claude CLI/API proof with isolated OpenClaw state showing permissive native Bash allowed and restrictive control_request denied with the side effect blocked.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P1: The linked bug stalls Claude live sessions on native tool permission requests, breaking a real agent runtime workflow.
  • merge-risk: 🚨 compatibility: The PR intentionally changes raw Claude permission-mode args from an override into launch mechanics for managed live sessions.
  • merge-risk: 🚨 session-state: The PR changes live-session fingerprint/reuse behavior and forwards session policy state into user and cron CLI runs.
  • merge-risk: 🚨 security-boundary: The PR decides when native Claude Bash is allowed or denied based on OpenClaw exec policy.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body contains after-fix live Claude CLI/API proof with isolated OpenClaw state showing permissive native Bash allowed and restrictive control_request denied with the side effect blocked.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body contains after-fix live Claude CLI/API proof with isolated OpenClaw state showing permissive native Bash allowed and restrictive control_request denied with the side effect blocked.
Evidence reviewed

PR surface:

Source +213, Tests +771, Docs +5. Total +989 across 10 files.

View PR surface stats
Area Files Added Removed Net
Source 5 223 10 +213
Tests 2 772 1 +771
Docs 3 19 14 +5
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 10 1014 25 +989

What I checked:

  • Current main still drops control requests: On current main, handleClaudeLiveLine parses JSONL and then only handles drain state, turn state, output limits, and result; there is no control_request branch before non-result frames return, so the PR is still necessary. (src/agents/cli-runner/claude-live-session.ts:523, 8da8bc4aadfc)
  • PR adds policy resolution and control responses: The PR head resolves Claude live policy from exec defaults plus approval-file tightening, builds allow/deny permission results, and writes control_response frames for can_use_tool. (src/agents/cli-runner/claude-live-session.ts:499, 9580109565f6)
  • PR normalizes Claude live launch args: runClaudeLiveSessionTurn now rewrites live Claude args to --permission-mode default under restrictive OpenClaw policy and bypassPermissions under full/off policy before fingerprinting and spawning. (src/agents/cli-runner/claude-live-session.ts:1053, 9580109565f6)
  • Regression coverage added: The PR head adds focused tests for allow, deny, missing approval-file creation, restrictive approval defaults, session ask overrides, agent/session-key approvals, and raw permission-mode normalization. (src/agents/cli-runner.spawn.test.ts:1605, 9580109565f6)
  • Docs and changelog align with the changed contract: The docs now say OpenClaw-managed Claude live sessions normalize raw Claude --permission-mode to the effective OpenClaw exec policy, and the changelog records the user-visible fix. Public docs: docs/gateway/cli-backends.md. (docs/gateway/cli-backends.md:172, 9580109565f6)
  • Dependency contract checked: The pinned @anthropic-ai/[email protected] types define control_response success/error shapes, PermissionResult allow/deny behavior, and bypassPermissions/default permission modes matching the PR's payload shape.

Likely related people:

  • steipete: Peter authored the current main import of the Claude live-session and CLI backend surfaces in a374c3a and the earlier merged Claude permission-mode alignment in f523bbf, which this PR intentionally revises for managed live sessions. (role: feature-history owner; confidence: high; commits: a374c3a5bfd5, f523bbfcd10d; files: src/agents/cli-runner/claude-live-session.ts, extensions/anthropic/cli-shared.ts, docs/gateway/cli-backends.md)
  • guthirry: Guillaume opened the linked bug report and authored the first two commits carried in this PR, including the original control_request handler and policy-default alignment. (role: original reporter and prior fix author; confidence: medium; commits: 4685b0b021ea, de0187005bc4; files: src/agents/cli-runner/claude-live-session.ts, src/agents/cli-runner.spawn.test.ts)
  • sallyom: Sally authored the current head commit and PR comments that clarify the intended compatibility/security policy change beyond the earlier linked PR. (role: current PR follow-up owner; confidence: medium; commits: 9580109565f6; files: src/agents/cli-runner/claude-live-session.ts, docs/tools/exec-approvals.md, docs/gateway/cli-backends.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@sallyom

sallyom commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

Opened this as a separate maintainer PR rather than pushing over #81971 because the follow-up changes go beyond the original contributor’s patch: they adjust the Claude live Bash security boundary, add session/approval policy plumbing, and add regression coverage.

This branch intentionally preserves the original #81971 commits and layers one maintainer fix commit on top so CI can validate the complete stack cleanly. Once this is reviewed, we'll land this PR directly rather than use as the reference patch for #81971. This PR required much back & forth iteration and testing, so needed to own it here.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 25, 2026
@clawsweeper

clawsweeper Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: 💎 rare Pearl Clawlet

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 💎 rare.
Trait: sniffs out flaky tests.
Image traits: location status garden; accessory tiny test log scroll; palette charcoal, cyan, and signal green; mood proud; pose holding its accessory up for inspection; shell glossy opal shell; lighting subtle sparkle highlights; background little resolved-comment flags.
Share on X: post this hatch
Copy: My PR egg hatched a 💎 rare Pearl Clawlet in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels May 25, 2026
@sallyom
sallyom force-pushed the sallyom/pr-81971-effective-exec-policy branch from f845db2 to 51f7160 Compare May 25, 2026 05:20
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 25, 2026
@sallyom

sallyom commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

Maintainer clarification on the compatibility point:

  • Original fix(agents): answer Claude live control_request can_use_tool via exec policy #81971 bug: Claude live could emit a native Bash control_request, but OpenClaw did not answer with a control_response, so an otherwise allowed OpenClaw exec path could stall when Claude was in a prompting/default permission mode.
  • This intentionally updates the fix: align claude cli permissions with exec policy #70800 raw-args override contract for OpenClaw-managed Claude live sessions. Maintainer discussions confirmed we should match Codex: OpenClaw's effective exec policy is authoritative, and the provider-native permission flag is launch mechanics, not the user-facing policy source.
  • If effective OpenClaw exec is YOLO (security=full, ask=off), Claude live is normalized to --permission-mode bypassPermissions, even if raw Claude args requested a non-bypass mode such as default or acceptEdits; native Bash is allowed.
  • If effective OpenClaw exec policy is restrictive, Claude live is normalized to --permission-mode default, even if raw Claude args requested bypassPermissions or omitted --permission-mode; native Bash is routed through OpenClaw's deny/allow policy.
  • Claude native non-Bash tools are still denied with MCP guidance; the bundled OpenClaw MCP tools remain the intended Read/Write/Edit path.

@sallyom
sallyom force-pushed the sallyom/pr-81971-effective-exec-policy branch 3 times, most recently from 4de972d to 40a9070 Compare May 25, 2026 14:14
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 25, 2026
@sallyom
sallyom force-pushed the sallyom/pr-81971-effective-exec-policy branch from 40a9070 to c6ffd0e Compare May 25, 2026 14:29
@clawsweeper clawsweeper Bot added status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels May 25, 2026
guthirry and others added 3 commits May 25, 2026 11:29
… policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819
…faults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.
@sallyom
sallyom force-pushed the sallyom/pr-81971-effective-exec-policy branch from 9580109 to 86c861e Compare May 25, 2026 15:30
@sallyom
sallyom merged commit f0b6f70 into openclaw:main May 25, 2026
98 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 26, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
@sallyom
sallyom deleted the sallyom/pr-81971-effective-exec-policy branch May 29, 2026 15:14
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…aw#86330)

* fix(agents): answer Claude live control_request can_use_tool via exec policy

Claude CLI emits stream-json control_request frames with subtype
can_use_tool when it wants to use a native tool. The Claude live-session
bridge previously dropped these frames, leaving Claude waiting for a
control_response until the 180/600s no-output timeout fired (see openclaw#80819).

Resolve the effective OpenClaw exec policy (per-agent tools.exec -> global
tools.exec -> allowlist/on-miss defaults) once at session-start time and
thread it through fingerprinting and the session record. When a
can_use_tool request arrives:

- Allow native Bash when the resolved policy is security=full, ask=off
  (matching the bypassPermissions semantics OpenClaw already documents).
- Otherwise deny with a message that names the resolved policy and
  points the agent at OpenClaw MCP tools.

Unsupported control_request subtypes get a structured error response
instead of a silent no-op, and stray control_response frames are
silently dropped. Adds spawn-test coverage for both allow and deny paths.

Fixes openclaw#80819

* fix(agents): align Claude live control_request policy with backend defaults

Resolve the effective exec policy through the same defaults that
extensions/anthropic/cli-shared.ts:isOpenClawRequestedYolo and
src/agents/exec-defaults.ts:resolveExecDefaults already use (security
?? "full", ask ?? "off") instead of falling back to a hand-rolled
allowlist/on-miss default that disagreed with the rest of the codebase.
Without this, a default-config OpenClaw deployment launches Claude with
--permission-mode bypassPermissions but the bridge would still deny
Bash control_requests, re-creating the openclaw#80819 stall for the very
default-config case the issue reports.

Also thread the effective Claude permission mode into the policy
decision. Prefer the operator's explicit --permission-mode in argv,
falling back to what normalizeClaudePermissionArgs would have inserted
for an un-overridden launch. Native Bash is auto-allowed only when the
effective mode is bypassPermissions AND tools.exec resolves to
full/no-ask, so explicit raw-arg overrides like --permission-mode
default or acceptEdits broaden Claude's native prompting and are
honored by routing through deny.

Adds a no-config regression test (default deployment allows Bash, no
stall) and a permission-mode-override test (tools.exec full/off plus
explicit --permission-mode default in raw args denies). Existing
allow/deny tests continue to pass via the synthesized-mode fallback.

* fix(agents): honor effective exec policy for Claude live Bash

---------

Co-authored-by: Guillaume Thirry <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude CLI live-session bridge ignores control_request (can_use_tool) — sessions stall until 180/600s timeout — reproduces on 2026.5.3-1

2 participants