#13707: macOS: respect exec-approvals.json settings in gateway prompter
app: macos
stale
Cluster:
System Prompt Enhancements
## What
The macOS companion app was not respecting `exec-approvals.json` settings and always prompted for approval on every `system.run` request, regardless of the configured security/ask policy.
## Why
`ExecApprovalsGatewayPrompter` had three problems:
1. **No exec-approvals.json consultation:** `shouldPresent()` only checked connection mode, session matching, and recent input activity. It never read the `security`/`ask` settings from `exec-approvals.json`, so the app always prompted regardless of policy.
2. **Silent drop instead of resolving:** When `shouldPresent()` returned `false`, the handler returned without resolving the gateway request. The gateway was left waiting for a decision that never came, causing timeouts.
3. **No askFallback handling:** When a prompt was needed but couldn't be presented (e.g., remote + stale activity, session mismatch), there was no fallback behavior — the request was just dropped.
## How
- `shouldPresent` now returns a `PresentationDecision` struct with four fields: `shouldAsk`, `canPresent`, `security`, and `askFallback`.
- Added `shouldAsk(security:ask:)` to evaluate whether the ask policy requires prompting the user. This is distinct from whether the action is allowed — the `security` policy (full/deny/allowlist) decides the actual outcome.
- `shouldPresent` calls `ExecApprovalsStore.resolveReadOnly(agentId:)` using `request.request.agentId` (not `sessionKey`) and checks the per-agent resolved config, which respects the full resolution chain: agent-specific entry → wildcard `*` entry → global defaults.
- `resolveReadOnly` is a new read-only variant of `resolve` that uses `loadFile()` instead of `ensureFile()` to avoid disk writes on the MainActor.
- Three distinct paths in `handle(push:)`:
1. **Ask policy says no prompt** (`shouldAsk: false`) → resolve based on security policy: allow if `security == .full`, deny otherwise.
2. **Prompt needed but can't present** (`canPresent: false`) → consult `askFallback` (default: `.deny`); only allows if `askFallback == .full`.
3. **Can present** → show the native prompt as before.
- Added `_testShouldAsk` test helper and three new test cases covering all `ExecAsk × ExecSecurity` combinations.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
The macOS companion app now correctly respects `exec-approvals.json` settings when evaluating `system.run` requests. Previously, it always prompted regardless of policy; now it consults the resolved security/ask settings from `exec-approvals.json` (including agent-specific overrides and wildcard entries) and handles three distinct scenarios: auto-approve when policy doesn't require prompting, use `askFallback` when prompt is needed but can't be shown, and present native prompt when conditions allow.
The PR addresses two critical bugs identified in previous reviews:
- Now uses `request.request.agentId` instead of `sessionKey` when resolving policy, ensuring agent-specific overrides are respected
- When prompts can't be shown, consults `askFallback` instead of silently approving
The implementation introduces `resolveReadOnly()` in `ExecApprovalsStore` to avoid disk writes on the MainActor, `shouldAsk()` helper to evaluate ask policy against security settings, and a `PresentationDecision` struct to cleanly separate policy evaluation from presentation heuristics. Tests cover all `ExecAsk × ExecSecurity` combinations.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- Both critical bugs from previous review are properly fixed, logic is clear and correct, comprehensive tests validate all policy combinations, and the read-only resolve pattern avoids potential MainActor disk write issues
- No files require special attention
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20435: fix(exec): prioritize user 'always allow' config over tool defaults...
by ChisomUma · 2026-02-18
77.7%
#17221: fix(agents): prevent agents from using exec for gateway management
by CornBrother0x · 2026-02-15
76.8%
#8260: fix(macOS): gateway readiness detection + reversible Configure later
by xksteven · 2026-02-03
76.6%
#14127: fix(exec): return command output when gateway approval is Always Allow
by Siziff · 2026-02-11
75.8%
#21733: security(exec): platform-aware allowlist matching and restricted sa...
by Esubaalew · 2026-02-20
74.7%
#14222: core: add needsApproval to before_tool_call; move AgentShield to ex...
by Eventedge · 2026-02-11
74.4%
#11048: fix: address repository issues (env, author, CI comments, security ...
by cavula · 2026-02-07
73.3%
#7983: feat(security): add secure coding guidelines to system prompt
by TGambit65 · 2026-02-03
73.1%
#21742: fix(doctor): warn on conflicting exec approval config surfaces
by habakan · 2026-02-20
73.0%
#8086: feat(security): Add prompt injection guard rail
by bobbythelobster · 2026-02-03
72.8%