-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
[Bug]: Exec approval checks use symlink path but execution uses real path #45595
Copy link
Copy link
Closed
Closed
Copy link
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.ClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.
Description
Metadata
Metadata
Assignees
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.ClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.
Type
Fields
Priority
None yet
Bug type
Behavior bug (incorrect output/state without crash)
Summary
The exec approval system checks
resolvedPath(may be a symlink) but execution pins toresolvedRealPath(the real file). The system computes both paths but uses different ones for trust vs execution - so it can approve or reject one path and then run a different one.Steps to reproduce
Have a binary available through a symlink on PATH (Homebrew, nix, asdf all do this):
Add an allowlist entry for the real file:
{"pattern": "/opt/homebrew/Cellar/ripgrep/14.1.1/bin/rg"}The agent runs
rg -n TODO.Expected behavior
The command is auto-approved. The binary at the end of the symlink chain is allowlisted.
Actual behavior
The command is blocked. Approval matching compares against
/opt/homebrew/bin/rg(symlink) while execution later pins to/opt/homebrew/Cellar/ripgrep/14.1.1/bin/rg(real file). They do not match.The reverse is also wrong: allowlist the symlink path, change the symlink target, and the old approval still holds while execution runs the new binary.
OpenClaw version
2026.3.12
Operating system
All platforms (scope varies - see additional information)
Install method
Any
Model
N/A (exec approval layer, not model-dependent)
Provider / routing chain
N/A (exec approval layer, not provider-dependent)
Config file / key location
tools.exec.allowlist,tools.exec.safeBins,tools.exec.safeBinTrustedDirs,autoAllowSkillsinexec-approvals.jsonAdditional provider/model setup details
No response
Logs, screenshots, and evidence
No response
Impact and severity
/opt/homebrew/bin/are symlinks.Additional information
Root cause:
resolveExecutablePath()returns the executable path as found. It does not resolve symlinks.buildCommandResolution()stores bothresolvedPathandresolvedRealPath.resolvedPath.resolvedRealPath ?? resolvedPath.The system already knows both values, but does not use one canonical executable identity across trust checks, persistence, and execution.
This is not only one matcher bug. The same path mismatch shows up in:
openclaw doctorsafe-bin hints (diagnostic only)Platform notes:
Workaround:
Use the symlink path in allowlist entries, not the real file:
{"pattern": "/opt/homebrew/bin/rg"}The "Always Allow" button also works because it saves the symlink path. The trade-off is approval drift if the symlink target changes.
Key files:
src/infra/executable-path.tssrc/infra/exec-command-resolution.tssrc/infra/exec-approvals-allowlist.tssrc/infra/exec-approvals-analysis.tssrc/node-host/runner.tssrc/node-host/invoke-system-run.tssrc/agents/bash-tools.exec-host-gateway.tsRelated: