openclaw - ✅(Solved) Fix BUG: exec allowlist matching broken for compound commands - "allowlist miss" even when command is in safeBins [1 pull requests, 3 comments, 3 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#59600Fetched 2026-04-08 02:42:44
View on GitHub
Comments
3
Participants
3
Timeline
10
Reactions
2
Timeline (top)
commented ×3cross-referenced ×2mentioned ×2subscribed ×2

Root Cause

Location: src/infra/exec-approvals-allowlist.ts in isSafeBinUsage() function

The bug: The matching logic works as follows:

  1. Extracts executableName from resolved path (e.g., "gh" from /opt/homebrew/bin/gh)
  2. Checks if executableName exists in safeBins Set
  3. If found, requires a safeBinProfile to validate subcommand args
  4. Most CLIs (gh, git, curl with args, etc.) do not have profiles defined
  5. Command is denied because no profile exists to validate the subcommand arguments

Code path (lines 80-102):

const matchesSafeBin = params.safeBins.has(execName);  // "gh" matches
if (!matchesSafeBin) {
  return false;
}
// ...
const profile = safeBinProfiles[execName];  // profile["gh"] is undefined
if (!profile) {
  return false;  // FAILS here
}
return validateSafeBinArgv(argv, profile, { binName: execName });

Fix Action

Fix / Workaround

Option C: Document that compound commands require entries in exec-approvals.json instead of safeBins (workaround, not a fix).

PR fix notes

PR #60010: docs(exec-approvals): clarify defaults fallback and allowlist pattern matching

Description (problem / solution / changelog)

Summary

  • Problem: Users configuring exec approvals hit two undocumented pitfalls: (1) an empty defaults: {} silently falls back to restrictive policy (security: "allowlist", ask: "on-miss"), blocking unattended cron/headless sessions; (2) allowlist patterns that include arguments (e.g., /path/to/python3 scripts/*.py) never match because patterns match resolved binary paths only, not full command strings.
  • Why it matters: These two issues account for multiple open bug reports (#59224, #59600, #27843) and hours of operator debugging. The current docs mention binary-path matching in passing but do not call it out prominently or warn about the defaults fallback behavior.
  • What changed: Added an admonition block clarifying defaults fallback behavior, strengthened the allowlist pattern documentation with explicit correct/incorrect examples, and added a "Troubleshooting" section covering the three most common exec approval pitfalls.
  • What did NOT change (scope boundary): No code changes. No changes to CLI behavior, exec policy logic, or approval flow. Only docs/tools/exec-approvals.md was modified.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #59224
  • Related #59600
  • Related #27843
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

N/A — documentation gap, not a code regression.

Regression Test Plan (if applicable)

N/A

User-visible / Behavior Changes

None — docs only.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS 15 (arm64)
  • Runtime/container: N/A
  • Model/provider: N/A
  • Integration/channel: Telegram (cron-triggered exec)

Steps

  1. Set defaults: {} in exec-approvals.json
  2. Add allowlist entries with arguments (e.g., /opt/homebrew/opt/[email protected]/bin/python3.12 *)
  3. Trigger a cron job that invokes Python scripts
  4. Observe: commands are denied with "allowlist miss"

Expected

  • Docs should clearly state that empty defaults fall back to restrictive policy
  • Docs should clearly state that patterns match binary paths only, not command+args

Actual

  • Docs mention binary-path matching only in passing ("Patterns should resolve to binary paths")
  • Docs do not explain what happens when defaults is empty or missing

Evidence

  • Trace/log snippets

Firsthand reproduction: configured defaults: {} with argument-including patterns, spent multiple debugging cycles before discovering (1) defaults must be explicit and (2) patterns match binary path only.

Human Verification (required)

  • Verified scenarios: reproduced both pitfalls on a live OpenClaw 2026.4.1 deployment with Telegram cron jobs; confirmed the fix (explicit defaults + binary-only patterns) resolves both issues
  • Edge cases checked: verified that openclaw approvals set replaces the entire file (documented in troubleshooting)
  • What I did not verify: other exec policy combinations beyond allowlist+deny; node-host vs gateway-host differences

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Changed files

  • docs/tools/exec-approvals.md (modified, +71/-1)

Code Example

"safeBins": ["gh", "gh pr list", "gh api", "curl -s", "python3 -c"]

---

const matchesSafeBin = params.safeBins.has(execName);  // "gh" matches
if (!matchesSafeBin) {
  return false;
}
// ...
const profile = safeBinProfiles[execName];  // profile["gh"] is undefined
if (!profile) {
  return false;  // FAILS here
}
return validateSafeBinArgv(argv, profile, { binName: execName });

---

"safeBins": [
  "gh",
  "gh pr list",
  "gh api",
  "gh auth status",
  "curl -s",
  "python3 -c"
]
RAW_BUFFERClick to expand / collapse

Bug Description

exec allowlist matching is fundamentally broken for compound commands. Commands with subcommands or flags are denied even when their full command string is explicitly listed in safeBins.

Environment

  • OpenClaw version: 2026.4.1
  • Platform: macOS
  • Config: tools.exec.security: "allowlist"

Symptoms

What works:

  • Single-word commands: echo, whoami, gh alone
  • Scripts via safeBinProfiles paths (jq, grep, cut, etc.)

What doesn't work:

  • Commands with subcommands: gh pr list, gh api, gh auth status
  • Commands with flags: curl -s, python3 -c
  • Full paths: /opt/homebrew/bin/gh

Reproduction

  1. Set tools.exec.security: "allowlist" in openclaw.json
  2. Add compound commands to safeBins:
    "safeBins": ["gh", "gh pr list", "gh api", "curl -s", "python3 -c"]
  3. Run a compound command: gh pr list
  4. Result: exec denied: allowlist miss

Root Cause Analysis

Location: src/infra/exec-approvals-allowlist.ts in isSafeBinUsage() function

The bug: The matching logic works as follows:

  1. Extracts executableName from resolved path (e.g., "gh" from /opt/homebrew/bin/gh)
  2. Checks if executableName exists in safeBins Set
  3. If found, requires a safeBinProfile to validate subcommand args
  4. Most CLIs (gh, git, curl with args, etc.) do not have profiles defined
  5. Command is denied because no profile exists to validate the subcommand arguments

Code path (lines 80-102):

const matchesSafeBin = params.safeBins.has(execName);  // "gh" matches
if (!matchesSafeBin) {
  return false;
}
// ...
const profile = safeBinProfiles[execName];  // profile["gh"] is undefined
if (!profile) {
  return false;  // FAILS here
}
return validateSafeBinArgv(argv, profile, { binName: execName });

Impact

System-wide: This bug affects ALL agents/sessions, not just the main session:

  • Main webchat session
  • Link agent
  • ACP spawned subagents (backend-developer, github-expert, etc.)
  • Any agent using security: "allowlist" with safeBins

Severity: Critical — completely blocks exec for any compound command

Expected Behavior

safeBins should allow compound commands like "gh pr list" when explicitly listed. The current behavior treats safeBins entries as executable-only names, not full command strings.

Suggested Fix Approaches

Option A: Modify isSafeBinUsage() to check if the full command string (or argv slice) exists in safeBins before falling back to executable-only match with profile validation.

Option B: Add gh, git, curl, etc. profiles to safeBinProfiles defining their valid subcommands (high maintenance, incomplete).

Option C: Document that compound commands require entries in exec-approvals.json instead of safeBins (workaround, not a fix).

Config Evidence

Config is correct — entries literally exist but still fail:

"safeBins": [
  "gh",
  "gh pr list",
  "gh api",
  "gh auth status",
  "curl -s",
  "python3 -c"
]

Related Files

  • src/infra/exec-approvals-allowlist.ts - isSafeBinUsage() function
  • src/infra/exec-safe-bin-policy-profiles.ts - safeBinProfiles definitions
  • src/node-host/invoke-system-run-allowlist.ts - combined allowlist+safeBins evaluation

extent analysis

TL;DR

Modify the isSafeBinUsage() function to check if the full command string exists in safeBins before falling back to executable-only match with profile validation.

Guidance

  1. Review the isSafeBinUsage() function: Focus on lines 80-102 in src/infra/exec-approvals-allowlist.ts to understand the current matching logic.
  2. Implement full command string matching: Modify the function to check if the full command string (or argv slice) exists in safeBins before checking for an executable-only match with profile validation.
  3. Test with compound commands: Verify that the modified function allows compound commands like "gh pr list" when explicitly listed in safeBins.
  4. Consider maintaining profiles for common CLIs: Although not a primary fix, adding profiles for common CLIs like gh, git, and curl to safeBinProfiles can provide additional validation for subcommands.

Example

const fullCommand = argv.join(' ');
if (params.safeBins.has(fullCommand)) {
  // Allow the command if the full command string is in safeBins
  return true;
}
// ... existing executable-only match logic

Notes

This fix approach focuses on modifying the isSafeBinUsage() function to correctly handle compound commands. It does not require adding profiles for every possible CLI, making it more maintainable than Option B.

Recommendation

Apply the workaround by modifying the isSafeBinUsage() function to check for full command string matches in safeBins, as this directly addresses the issue with compound commands being denied despite being explicitly listed.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix BUG: exec allowlist matching broken for compound commands - "allowlist miss" even when command is in safeBins [1 pull requests, 3 comments, 3 participants]