openclaw - ✅(Solved) Fix [Bug]: allow-always behaves like allow-once in exec approval (allow-always 点击后实际生效为 allow-once) [3 pull requests, 8 comments, 7 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58662Fetched 2026-04-08 01:59:33
View on GitHub
Comments
8
Participants
7
Timeline
24
Reactions
1
Author
Timeline (top)
commented ×7referenced ×7cross-referenced ×4closed ×2

Version: 2026.3.31

Description: When the agent executes shell commands through remote channels (WeChat/WebChat), the exec approval prompt appears. Clicking allow-always results in the same command requiring approval again on the next execution, behaving identically to allow-once.

agent 通过远程渠道(微信/WebChat)执行 shell 命令时弹出审批,点击 allow-always 后,同一命令下次执行时仍需审批,表现和 allow-once 一致。

Expected behavior: Clicking allow-always should permanently approve the command (at least until Gateway restart), without repeatedly showing the approval prompt.

点击 allow-always 后,相同命令应被永久放行(至少在 Gateway 重启前),不再重复弹出审批请求。

Steps to reproduce:

Ask the agent to execute any shell command via WeChat/WebChat Click allow-always in the approval prompt Ask the agent to execute the same command again Approval prompt still appears (behaves same as allow-once)

Root Cause

Version: 2026.3.31

Description: When the agent executes shell commands through remote channels (WeChat/WebChat), the exec approval prompt appears. Clicking allow-always results in the same command requiring approval again on the next execution, behaving identically to allow-once.

agent 通过远程渠道(微信/WebChat)执行 shell 命令时弹出审批,点击 allow-always 后,同一命令下次执行时仍需审批,表现和 allow-once 一致。

Expected behavior: Clicking allow-always should permanently approve the command (at least until Gateway restart), without repeatedly showing the approval prompt.

点击 allow-always 后,相同命令应被永久放行(至少在 Gateway 重启前),不再重复弹出审批请求。

Steps to reproduce:

Ask the agent to execute any shell command via WeChat/WebChat Click allow-always in the approval prompt Ask the agent to execute the same command again Approval prompt still appears (behaves same as allow-once)

PR fix notes

PR #58729: delete

Description (problem / solution / changelog)

Closed - replaced by #58745

Changed files

  • .openclaw/workspace-state.json (added, +4/-0)
  • FIX_58662_PR_DESCRIPTION.md (added, +62/-0)
  • HEARTBEAT.md (added, +7/-0)
  • SOUL.md (added, +36/-0)
  • TOOLS.md (added, +40/-0)
  • rules.md (added, +122/-0)
  • src/infra/exec-approvals-persist.test.ts (added, +142/-0)
  • src/infra/exec-approvals.ts (modified, +29/-3)

PR #58745: fix(exec-approvals): preserve allow-always allowlist entries (#58662)

Description (problem / solution / changelog)

Summary

Fixes #58662 - allow-always exec approval decisions were not being persisted, causing the same command to require approval repeatedly (behaving like allow-once).

Root Cause

The normalizeExecApprovals() function drops undefined fields when serializing the defaults object. When a file is saved with defaults: { security: "allowlist", ... }, JSON.stringify correctly preserves it. However, on subsequent loads:

  1. loadExecApprovals() calls normalizeExecApprovals(parsed), which creates a new defaults object with all fields set to undefined
  2. The original defaults from the file were lost
  3. ensureExecApprovals() would then save the file again with empty defaults
  4. This caused allowlist entries to effectively be lost on every exec call

Changes

src/infra/exec-approvals.ts

  1. loadExecApprovals(): Preserve parsed.defaults when loading the file, before normalizeExecApprovals() drops undefined fields.

  2. ensureExecApprovals(): Check if loaded file has a defaults field (even if empty) and preserve it, rather than always using the normalized defaults.

  3. resolveExecApprovalsFromFile(): Preserve original defaults in the returned file object to prevent loss during subsequent saves.

  4. resolveExecApprovalsPath(): Add environment variable override support for testing (OPENCLAW_EXEC_APPROVALS_FILE).

src/infra/exec-approvals-persist.test.ts (new)

Added regression tests to verify:

  • Allowlist entries persist across ensureExecApprovals() calls
  • Defaults field is preserved across restarts
  • Allowlist entries are not duplicated on repeated calls
  • resolveExecApprovals() preserves file defaults for subsequent saves

Testing

# Run new regression tests
npx vitest run --config vitest.unit.config.ts src/infra/exec-approvals-persist.test.ts

# Run existing allow-always tests
npx vitest run --config vitest.unit.config.ts src/infra/exec-approvals-allow-always.test.ts

All tests pass.

Impact

  • Users affected: All users using remote channels (WeChat, Telegram, WebChat) with exec approvals
  • Severity: High - core functionality regression in v2026.3.31
  • Backward compatibility: Fully backward compatible - only fixes broken persistence

Verification

After this fix:

  1. User clicks allow-always on an exec approval prompt
  2. The allowlist entry is persisted to ~/.openclaw/exec-approvals.json
  3. Subsequent executions of the same command do NOT trigger a new approval prompt
  4. Gateway restarts preserve the allowlist entries

Changed files

  • src/infra/exec-approvals-persist.test.ts (added, +142/-0)
  • src/infra/exec-approvals.ts (modified, +30/-3)
  • src/infra/provider-usage.fetch.shared.test.ts (modified, +1/-1)

PR #58792: fix(exec): resolve remote approval regressions

Description (problem / solution / changelog)

Fixes #58710 Fixes #58722 Fixes #58739 Fixes #58752 Fixes #58662 Fixes #46573 Fixes #58769 Addresses #58715 Addresses #58616 Addresses #58691 Addresses #49266 Addresses #43279 Addresses #46846 Addresses #46848 Addresses #42574

Summary

This PR fixes the 2026.3.31 exec-approval regression cluster at the shared policy/runtime seams instead of stacking more per-channel workarounds on top.

Root causes addressed:

  • src/agents/bash-tools.exec.ts inherited ask from exec-approvals.json but not security, so security:"full" + ask:"off" in exec-approvals.json could still collapse back to allowlist and fail remote exec.
  • shared approval availability could report a chat surface as approval-capable even when native delivery was not actually enabled.
  • Slack and Discord runtime handlers drifted from the shared approver-resolution logic and could disagree with inferred approver config from allowFrom / defaultTo.
  • isolated cron runs inherited stricter approval policy with no interactive approval surface, then fell into a dead-end denial path.
  • allow-always persisted only as an allowlist-mode implementation detail, so ask:"always" kept re-prompting and remote channels effectively treated allow-always like allow-once.
  • shell-wrapper paths that intentionally fail static allowlist analysis had no durable trust representation, so repeated node allow-always approvals could still degrade back into repeated prompts.

What changed

  • make gateway exec inherit both security and ask defaults from exec-approvals.json when tool policy is unset
  • make shared native approval availability require both approvers and native delivery enablement
  • make Slack handler use the canonical request matcher instead of a local partial check
  • make Discord handler use resolved approvers everywhere, including inferred approvers
  • resolve isolated cron no-route approval dead-ends from the effective host fallback policy when trusted automation is allowed
  • make openclaw doctor warn when tools.exec is broader than ~/.openclaw/exec-approvals.json, so stricter host-policy conflicts become explicit instead of silently clamping
  • persist allow-always as durable user-approved trust and honor it on future gateway and node-host exec calls
  • keep static allowlist entries from silently bypassing ask:"always", so the durable-trust fix does not weaken explicit policy
  • persist exact-command durable trust for shell-wrapper paths that cannot safely materialize an executable allowlist entry, so repeated node allow-always approvals actually stick without requiring a restart
  • when Windows cannot build an allowlist execution plan, require explicit approval instead of hard-dead-ending the exec path
  • add regression coverage for the policy-inheritance, inferred-approver, cron/headless, durable-trust, and shell-wrapper reuse paths
  • add changelog entries

Verification

  • pnpm test -- src/agents/bash-tools.exec.approval-id.test.ts src/plugin-sdk/approval-delivery-helpers.test.ts extensions/slack/src/monitor/exec-approvals.test.ts extensions/discord/src/monitor/exec-approvals.test.ts extensions/slack/src/exec-approvals.test.ts extensions/discord/src/exec-approvals.test.ts
  • pnpm test -- src/node-host/invoke-system-run.test.ts src/infra/exec-approvals-allow-always.test.ts src/agents/bash-tools.exec.approval-id.test.ts src/infra/exec-approvals-policy.test.ts src/node-host/exec-policy.test.ts
  • pnpm check
  • pnpm build

Notes

  • This still does not add Windows allowlist-plan reconstruction. The Windows path becomes usable again because preapproved full/off policy from exec-approvals.json now actually takes effect on remote exec, unsupported allowlist-plan cases fall back to explicit approval instead of a hard dead end, and durable exact-command trust covers repeated shell-wrapper reruns that cannot safely persist an executable allowlist entry.

Changed files

  • CHANGELOG.md (modified, +3/-0)
  • extensions/discord/src/exec-approvals.test.ts (modified, +24/-12)
  • extensions/discord/src/exec-approvals.ts (modified, +15/-13)
  • extensions/discord/src/monitor/exec-approvals.test.ts (modified, +46/-3)
  • extensions/discord/src/monitor/exec-approvals.ts (modified, +8/-4)
  • extensions/slack/src/config-ui-hints.ts (modified, +1/-1)
  • extensions/slack/src/exec-approvals.test.ts (modified, +20/-13)
  • extensions/slack/src/exec-approvals.ts (modified, +14/-6)
  • extensions/slack/src/monitor/exec-approvals.test.ts (modified, +41/-2)
  • extensions/slack/src/monitor/exec-approvals.ts (modified, +10/-15)
  • src/agents/bash-tools.exec-host-gateway.test.ts (added, +124/-0)
  • src/agents/bash-tools.exec-host-gateway.ts (modified, +78/-5)
  • src/agents/bash-tools.exec-host-node.ts (modified, +143/-100)
  • src/agents/bash-tools.exec-host-shared.ts (modified, +36/-0)
  • src/agents/bash-tools.exec-types.ts (modified, +1/-0)
  • src/agents/bash-tools.exec.approval-id.test.ts (modified, +288/-1)
  • src/agents/bash-tools.exec.ts (modified, +12/-3)
  • src/agents/pi-tools.ts (modified, +1/-0)
  • src/commands/doctor-security.test.ts (modified, +166/-0)
  • src/commands/doctor-security.ts (modified, +148/-0)
  • src/config/bundled-channel-config-metadata.generated.ts (modified, +1/-1)
  • src/config/types.discord.ts (modified, +1/-1)
  • src/config/types.slack.ts (modified, +1/-1)
  • src/infra/exec-approvals-allowlist.ts (modified, +37/-4)
  • src/infra/exec-approvals-policy.test.ts (modified, +81/-0)
  • src/infra/exec-approvals-store.test.ts (modified, +61/-0)
  • src/infra/exec-approvals.ts (modified, +103/-8)
  • src/node-host/exec-policy.test.ts (modified, +14/-0)
  • src/node-host/exec-policy.ts (modified, +14/-0)
  • src/node-host/invoke-system-run-allowlist.ts (modified, +3/-0)
  • src/node-host/invoke-system-run.test.ts (modified, +57/-0)
  • src/node-host/invoke-system-run.ts (modified, +47/-31)
  • src/plugin-sdk/approval-delivery-helpers.test.ts (modified, +7/-0)
  • src/plugin-sdk/approval-delivery-helpers.ts (modified, +2/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Version: 2026.3.31

Description: When the agent executes shell commands through remote channels (WeChat/WebChat), the exec approval prompt appears. Clicking allow-always results in the same command requiring approval again on the next execution, behaving identically to allow-once.

agent 通过远程渠道(微信/WebChat)执行 shell 命令时弹出审批,点击 allow-always 后,同一命令下次执行时仍需审批,表现和 allow-once 一致。

Expected behavior: Clicking allow-always should permanently approve the command (at least until Gateway restart), without repeatedly showing the approval prompt.

点击 allow-always 后,相同命令应被永久放行(至少在 Gateway 重启前),不再重复弹出审批请求。

Steps to reproduce:

Ask the agent to execute any shell command via WeChat/WebChat Click allow-always in the approval prompt Ask the agent to execute the same command again Approval prompt still appears (behaves same as allow-once)

Steps to reproduce

  1. From a remote channel (WeChat/WebChat), ask the agent to execute a shell command (e.g., openclaw --version)
  2. The exec approval prompt appears with options: allow-once / allow-always / deny
  3. Click allow-always
  4. Ask the agent to execute the same command again
  5. Approval prompt still appears — behaves same as allow-once

Expected behavior

After clicking allow-always, the same command should be permanently approved (at least until Gateway restart) and no longer trigger the approval prompt.

Actual behavior

Clicking allow-always only approves the current execution, same as allow-once. The next execution of the same command still shows the approval prompt.

OpenClaw version

2026.3.31

Operating system

Ubuntu 24.04

Install method

npm global

Model

openrouter/xiaomi/mimo-v2-pro

Provider / routing chain

Channel: openclaw-weixin (WeChat) > Agent: main > Model: openrouter/xiaomi/mimo-v2-pro

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The issue can be mitigated by modifying the approval storage mechanism to persistently store "allow-always" approvals until the Gateway restarts.

Guidance

  • Investigate the approval storage mechanism to determine why "allow-always" approvals are not being persisted.
  • Verify that the approval prompt's behavior is consistent across different shell commands and remote channels.
  • Check the Gateway's configuration and logs to ensure that there are no settings or errors that could be causing the approval prompt to reappear.
  • Consider implementing a temporary workaround, such as automatically approving specific commands or disabling the approval prompt altogether, until a permanent fix can be implemented.

Example

No code snippet is provided due to lack of information about the underlying implementation.

Notes

The root cause of the issue is unclear, and more information about the approval storage mechanism and Gateway configuration is needed to provide a definitive solution.

Recommendation

Apply workaround: Implement a temporary fix, such as automatically approving specific commands, until the underlying issue with the approval storage mechanism can be resolved.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

After clicking allow-always, the same command should be permanently approved (at least until Gateway restart) and no longer trigger the approval prompt.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING