← Back to PRs

#14127: fix(exec): return command output when gateway approval is Always Allow

by Siziff open 2026-02-11 14:48 View on GitHub →
agents stale
#### Summary With Exec Approval set to "Always Allow" (or when the UI auto-approves with allow-always), the exec tool was returning immediately with "Approval required..." and running the command in the background. The command output was only sent as system events, so the model never received stdout/stderr as the tool result. This fix awaits the approval decision, runs the command, and returns the actual output in the tool result. lobster-biscuit #### Root Cause Gateway exec path with `requiresAsk === true` used `void (async () => { ... })(); return approval-pending`, so the tool returned before the approved run completed; output was only emitted as system events. #### Behavior Changes - When gateway exec requires approval and user (or UI) responds allow-once/allow-always, the tool now waits for the decision, runs the command, and resolves with the command output (or denied/failed message). - Denied or failed cases now return a proper tool result with `status: "failed"` and message instead of leaving the flow in approval-pending. #### Tests - Updated `requires approval for elevated ask when allowlist misses`: expects `status: "failed"` and "Exec denied (user-denied)" when decision is deny. - Added `returns exec output when gateway approval is allow-always (Always Allow)`: mocks `decision: "allow-always"`, asserts `status: "completed"` and output text "test" for `echo test`. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR changes the gateway exec approval flow so that when `requiresAsk` is true and the gateway/UI auto-approves (including `allow-always` / “Always Allow”), the exec tool waits for the approval decision, runs the command, and returns stdout/stderr in the tool result instead of returning early and only emitting system events. Tests were updated to assert a failed tool result on deny, and a new test covers returning output for `allow-always`. Main concern: the new gateway `requiresAsk` execution path starts a `ProcessSession` but never backgrounds it (and it disables notify-on-exit and doesn’t stream updates), which can break follow-up semantics for long-running approved commands. There’s also an abort-signal listener that isn’t cleaned up after completion. <h3>Confidence Score: 3/5</h3> - This PR is close to safe to merge but has a couple of behavior/robustness issues in the updated gateway approval execution path. - Core change (returning output for allow-always) is sound and test-covered, but the gateway approval path now spawns a ProcessSession without backgrounding or streaming/notify semantics, which can regress long-running command follow-up behavior. There is also an abort listener that is never removed, which can accumulate over many calls. - src/agents/bash-tools.exec.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs