fix: align claude cli permissions with exec policy#70800
Conversation
🔒 Aisle Security AnalysisWe found 3 potential security issue(s) in this PR:
1. 🟠 Arbitrary local image file exfiltration via prompt path references when using Claude CLI imageArg '@'
DescriptionThe CLI runner auto-detects image file path references inside the prompt text (including absolute paths like This enables a prompt-injection style data exfiltration of any local image file readable by the OpenClaw process (e.g., screenshots, camera photos, exported diagrams containing secrets), because an untrusted prompt can include an image-looking absolute path and the host will read and attach it. Key points:
Vulnerable code: const resolvedImages = ... : await loadPromptRefImages({ prompt, workspaceDir: params.workspaceDir });
...
prompt = appendImagePathsToPrompt(prompt, imagePaths, params.backend.imageArg === "@" ? "@" : "");RecommendationEnforce a strict local-file policy for prompt-detected image references. Minimum safe fix (recommended): default to const resolvedImages =
params.images && params.images.length > 0
? params.images
: await loadPromptRefImages({
prompt,
workspaceDir: params.workspaceDir,
workspaceOnly: true, // prevent absolute paths / traversal outside workspace
});Additionally:
2. 🟠 Claude CLI backend enables all OpenClaw MCP tools via wildcard allowlist (can self-approve exec/plugin requests)
DescriptionOpenClaw’s Anthropic Claude CLI backend now passes This is risky because Claude Code’s In
Vulnerable change (enables the wildcard by default): "--allowedTools",
"mcp__openclaw__*",This is especially concerning because the wildcard is applied to both fresh and resumed sessions, so it persists across runs. RecommendationAvoid wildcard tool enablement; explicitly allow only the minimal set of MCP tools required. Option A (preferred): do not set Option B: explicitly deny sensitive approval/administrative tools from the MCP server namespace (or move them behind an owner-only gate enforced server-side). For example, restrict to read-only conversation tools and exclude args: [
// ...
"--allowedTools",
"mcp__openclaw__conversations_list,mcp__openclaw__conversation_get,mcp__openclaw__messages_read"
]Additionally, enforce authorization server-side for approval resolution regardless of client allowlists (e.g., require an authenticated owner/admin identity for 3. 🟡 Claude CLI permission bypass inferred from missing exec policy, ignoring sandbox default security
Description
Impact:
Vulnerable code: const security = exec?.security ?? "full";
const ask = exec?.ask ?? "off";
return security === "full" && ask === "off";RecommendationDerive the effective exec policy using the same logic as the runtime (including host-dependent defaults), or at minimum incorporate For example, compute defaults consistent with function isOpenClawRequestedYolo(ctx?: CliBackendNormalizeConfigContext): boolean {
const agentExec = ctx?.agentId
? ctx.config?.agents?.list?.find((a) => a.id === ctx.agentId)?.tools?.exec
: undefined;
const exec = agentExec ?? ctx?.config?.tools?.exec;
const host = exec?.host ?? "auto";
const defaultSecurity = host === "sandbox" ? "deny" : "full";
const security = exec?.security ?? defaultSecurity;
const ask = exec?.ask ?? "off";
return security === "full" && ask === "off";
}Even better: pass in (or resolve) the already-computed effective exec policy (security/ask/host) from the core exec-policy resolver rather than re-deriving it here, to avoid future drift. Analyzed PR: #70800 at commit Last updated on: 2026-04-23T22:05:35Z |
PR SummaryMedium Risk Overview Extends the CLI-backend plugin API by adding Reviewed by Cursor Bugbot for commit 8f58608. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR aligns Claude CLI's Confidence Score: 5/5Safe to merge; logic is correct, well-tested, and backward-compatible. All findings are P2 style suggestions (test logic duplication, dead-code field). The core permission-mode injection, per-agent fallback, and raw-arg override semantics are correct and covered by new unit tests. No data-integrity, security-boundary, or runtime-breakage concerns were found. No files require special attention.
|
| export function resolveClaudePermissionMode(context?: CliBackendNormalizeConfigContext): { | ||
| mode?: string; | ||
| overrideExisting: boolean; | ||
| } { | ||
| return isOpenClawRequestedYolo(context) | ||
| ? { mode: CLAUDE_BYPASS_PERMISSION_MODE, overrideExisting: false } | ||
| : { overrideExisting: false }; | ||
| } |
There was a problem hiding this comment.
overrideExisting: true path is currently dead code
resolveClaudePermissionMode always returns overrideExisting: false, so the branch in normalizeClaudePermissionArgs that checks options.overrideExisting for true (dropping the caller-supplied value and injecting the policy mode instead) is never exercised by any current caller. If overrideExisting: true is intentionally reserved for future callers, a comment explaining the intended use case would help; otherwise the field can be dropped to simplify the contract.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/anthropic/cli-shared.ts
Line: 80-87
Comment:
**`overrideExisting: true` path is currently dead code**
`resolveClaudePermissionMode` always returns `overrideExisting: false`, so the branch in `normalizeClaudePermissionArgs` that checks `options.overrideExisting` for true (dropping the caller-supplied value and injecting the policy mode instead) is never exercised by any current caller. If `overrideExisting: true` is intentionally reserved for future callers, a comment explaining the intended use case would help; otherwise the field can be dropped to simplify the contract.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8f58608. Configure here.
| ): string[] | undefined { | ||
| if (!args) { | ||
| return args; | ||
| return options?.mode ? [CLAUDE_PERMISSION_MODE_ARG, options.mode] : args; |
There was a problem hiding this comment.
Permission args created without setting-sources for undefined args
Low Severity
When args is undefined and YOLO mode is active, normalizeClaudePermissionArgs now returns ["--permission-mode", "bypassPermissions"] instead of undefined. However, in normalizeClaudeBackendConfig, it's composed after normalizeClaudeSettingSourcesArgs, which already returned undefined for undefined input. This means the resulting args contain --permission-mode bypassPermissions but are missing the security-hardening --setting-sources user flag. Before this PR, both functions preserved undefined consistently.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8f58608. Configure here.
|
Landed via squash onto main. |


Summary
--permission-mode bypassPermissionsonly whentools.exec.security=fullandtools.exec.ask=off, including per-agentagents.list[].tools.exec; explicit raw Claude args still override; malformed permission-mode args are stripped.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
Regression Test Plan (if applicable)
extensions/anthropic/cli-shared.test.ts,src/agents/cli-backends.test.ts,src/gateway/gateway-cli-backend.live.test.tsUser-visible / Behavior Changes
Claude CLI follows OpenClaw's existing YOLO exec policy by adding
--permission-mode bypassPermissionsonly forsecurity=full+ask=off. Safer exec policy omits bypass. Users can still force Claude behavior with explicit raw--permission-modeargs.Diagram (if applicable)
Security Impact (required)
Yes, explain risk + mitigation: Claude CLI bypass mode is now tied to OpenClaw's existing YOLO exec policy and remains opt-out via explicit raw Claude args. Safer exec policies do not receive bypass.Repro + Verification
Environment
claude-cli/claude-sonnet-4-6ANTHROPIC_API_KEYfrom~/.profile; token env unsetSteps
Expected
--permission-mode bypassPermissions.--permission-modeargs override.Actual
Evidence
Human Verification (required)
pnpm build; direct Claude non-bypass probe; live OpenClaw Claude CLI smoke with debug args showing--permission-mode bypassPermissions.Review Conversations
Compatibility / Migration
Risks and Mitigations