-
Notifications
You must be signed in to change notification settings - Fork 12
fix(agent): enforce approval gate on allowFinalResponse path and validate predicate args (#54) #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
LukasParke
wants to merge
14
commits into
main
Choose a base branch
from
fix/54-approval-gate-validated-args
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
b6cd7ce
fix(agent): enforce approval gate on allowFinalResponse path and vali…
LukasParke 3ae034e
test(agent): cover hook deny on allowFinalResponse path
LukasParke 639e7bb
fix(agent): gate each response once and let schema-invalid calls reac…
LukasParke 0418b07
fix(agent): keep fail-closed on invalid args for manual tools
LukasParke 631edb2
test(agent): lock in the validate-before-execute invariant behind the…
LukasParke bc76be8
fix(agent): normalize call-level approval args
LukasParke 9a415f1
fix(agent): preserve call-level approval precedence
LukasParke 54a5aef
fix(agent): gate post-hook tool arguments
LukasParke f51b2dc
fix(agent): split tool approval into two phases
LukasParke 9bd6d01
refactor(agent): split approval gate phases
LukasParke 84feaca
fix(agent): harden mutated approval preparation
LukasParke 0719be2
fix(agent): prevent approval key collisions
LukasParke 292f9da
fix(agent): distinguish duplicate approval calls
LukasParke 25ec586
fix(agent): stabilize uncanonicalizable approval identities
LukasParke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| '@openrouter/agent': patch | ||
| --- | ||
|
|
||
| Fix two ways the tool-approval gate could be bypassed. | ||
|
|
||
| **`allowFinalResponse` executed pending tool calls with no approval check.** When a `stopWhen` condition halted the loop on a turn that still carried tool calls, the final-response path ran those calls directly — skipping the approval gate the normal loop applies on every round. A tool marked `requireApproval: true` (or gated by a predicate) would execute unguarded, and because the `PermissionRequest` hook's deny bookkeeping lives inside the approval check, hook-based `deny` never fired on this path either. That path now runs the same check as the in-loop call sites, so the run pauses with `status: 'awaiting_approval'` and the gated calls on `pendingToolCalls` instead of executing them. | ||
|
|
||
| **Function-based `requireApproval` received unvalidated arguments.** The predicate was called with the raw JSON-parsed tool arguments, while `execute` receives the arguments *after* the tool's Zod `inputSchema` runs. Any default, coercion, or transform in the schema made the two disagree — e.g. with `inputSchema: z.object({ dangerous: z.boolean().default(true) })`, a model emitting `{}` showed the predicate `dangerous: undefined` (no approval required) and then executed with `dangerous: true`. The predicate now sees the parsed value, so it decides on exactly what `execute` will receive. Arguments that don't satisfy the schema are not gated for engine-executed tools: such a call can never run (every execute path validates with the same schema first and turns the failure into a tool error output the model can recover from), so pausing for a human to approve it would only stall the run. Manual tools — which the host application executes without any engine-side validation — still fail closed on schema-invalid arguments. | ||
|
|
||
| **Duplicate approval prompts for the same tool call.** The approval gate could run more than once over the same response — e.g. the pre-loop check plus the post-loop `allowFinalResponse` gate when a stop condition fired on the first iteration — re-emitting the `PermissionRequest` hook and re-running `requireApproval` predicates for calls that were already resolved. Each response is now gated at most once per run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.