Python: bind policy-enforcement approvals to a single tool invocation - #6966
Merged
Roger Barreto (rogerbarreto) merged 5 commits intoJul 9, 2026
Conversation
PolicyEnforcementFunctionMiddleware retained approved call_ids in a set that was never cleared, so a reused call_id could re-authorize a later or different tool call without a fresh approval. It also accepted an approved response as long as the invocation metadata carried a pending call_id, without checking the response id or embedded function_call. Bind each approval to the exact invocation shown for review: call_id, function name, arguments, the security label (integrity/confidentiality), and the session. Validate that the approval response itself names the pending request (its id and embedded function_call), and consume the approval on first use. A reused call_id, a different function, changed arguments, an escalated label, a different session, or a mismatched approved response now all require a fresh approval. Adds regression tests covering each of those cases plus legitimate re-approval.
Contributor
There was a problem hiding this comment.
Pull request overview
Hardens the Python FIDES policy-enforcement approval flow so a granted approval is bound to a single, exact tool invocation and cannot be replayed to authorize a different call.
Changes:
- Replace call-id-only tracking with a per-
call_idpending-approval record that binds function name+args, context label, and session, and consume the approval on first successful use. - Validate the approval response body (embedded
function_call) against the pending request before allowing execution. - Add regression tests covering replay attempts across repeated calls, different functions, changed arguments, escalated labels, and different sessions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| python/packages/core/agent_framework/security.py | Implements bound pending-approval records, response validation, and consume-once behavior for policy-violation approvals. |
| python/packages/core/tests/test_security.py | Adds regression tests exercising approval binding, replay prevention, and session/label/argument constraints. |
Contributor
Make the policy-enforcement approval-response check reject a response that omits its id or embedded function_call.call_id: both must now be present and equal to the pending call_id, closing a None-identifier bypass. Adds a regression test.
Tao Chen (TaoChenOSU)
approved these changes
Jul 8, 2026
PolicyEnforcementFunctionMiddleware computed the approval decision once and reused it across the integrity and confidentiality checks, so a call that violated both policies produced an approval request describing only the untrusted-context violation and then silently waved the undisclosed confidentiality violation on replay. Detect every applicable violation up front and surface them together in a single approval request, so a granted approval waves only what it disclosed. The binding (call_id, function, arguments, security label, session) and consume-once behavior are unchanged. Adds a regression test covering a combined untrusted-context and confidentiality violation.
A pending policy approval was bound to the call body, security label, and session but not to the violations it disclosed. Because the violation set depends on the tool's policy metadata (max_allowed_confidentiality, accepts_untrusted), a replay could compute a different or larger set after that metadata changed and execute it under the old approval even though the user never reviewed that risk. Record the canonical disclosed violation fingerprint (type plus reason) in the pending record and require the replay to trip the same set, otherwise re-request approval disclosing the new set. Also require the approval response's approved flag to be a strict boolean True so a truthy non-boolean value is not treated as approval. Adds regression tests for a new violation appearing on replay, a same-type violation whose disclosed risk worsened, and a non-boolean approved flag.
Evan Mattson (moonbox3)
approved these changes
Jul 9, 2026
5 tasks
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Motivation & Context
Hardens the FIDES
PolicyEnforcementFunctionMiddlewareapproval flow (approval_on_violation=True). A granted approval was tracked only bycall_idin a set that was never cleared, so a reusedcall_idcould satisfy a later or different policy-violating call, and an approved response was accepted without checking its ownid/ embeddedfunction_call.Description & Review Guide
call_id+ function name + arguments + security label + session — the responseidand embeddedfunction_callare validated, and the approval is consumed on first use. Any reusedcall_id, different function, changed arguments, escalated label, different session, or mismatched response requires a fresh approval.agent-framework-coreonly; behaviour-preserving for legitimate approve→execute flows. No .NET change (the concept is Python-only; the hosted .NET approval path reconstructs calls from server-recorded state and is not affected).PolicyEnforcementFunctionMiddlewarebinding/consume-once logic and the added regression tests.Related Issue
N/A
Contribution Checklist