Skip to content

Python: isolate FIDES security state per session - #8137

Closed
Eduard van Valkenburg (eavanvalkenburg) wants to merge 2 commits into
microsoft:mainfrom
eavanvalkenburg:python-fides-session-isolation
Closed

Eduard van Valkenburg (eavanvalkenburg) wants to merge 2 commits into
microsoft:mainfrom
eavanvalkenburg:python-fides-session-isolation

Conversation

@eavanvalkenburg

Copy link
Copy Markdown
Member

Motivation & Context

FIDES middleware currently stores cumulative labels, hidden variables, audit records, and pending policy approvals on reusable middleware instances. Hosts that share one agent across conversations can therefore leak security state between sessions. This layer moves FIDES state into the owning AgentSession boundary while preserving standalone middleware behavior.

Description & Review Guide

  • What are the major changes? Introduces session-scoped FIDES state and variable storage, binds label tracking and policy enforcement to each invocation's session, preserves configured middleware options when creating scoped instances, and updates the security samples to pass explicit sessions.
  • What is the impact of these changes? Concurrent and restored conversations no longer share confidentiality, integrity, hidden variables, audit logs, or approval state through a reused agent instance.
  • What do you want reviewers to focus on? Please focus on session restoration, omitted-session isolation, and preservation of caller-supplied middleware configuration.

Related Issue

Part of #7455. This is the bottom layer of a four-PR FIDES hardening stack.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and the title prefix in sync automatically.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 8, 2026 07:15
@agent-framework-automation agent-framework-automation Bot added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Sep 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new state-accessor behavior breaks an existing public call pattern despite the PR declaring no breaking change.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Moves FIDES security state into AgentSession to prevent cross-conversation leakage.

Changes:

  • Adds durable session-scoped labels, variables, audits, and approvals.
  • Uses task-local middleware and preserves middleware configuration.
  • Updates documentation, samples, and regression tests.
File summaries
File Description
security.py Implements session-scoped FIDES state.
test_security.py Tests isolation, restoration, concurrency, and serialization.
FIDES_DEVELOPER_GUIDE.md Documents session-aware accessors.
email_security_example.py Reads audit state from the active session.
repo_confidentiality_example.py Creates and passes an explicit session.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +2765 to +2766
if session is None and self._provider_state_used:
raise ValueError("session is required after SecureAgentConfig is used as a context provider")
@eavanvalkenburg

Copy link
Copy Markdown
Member Author

Superseded by #8138 using an in-repository head branch; native GitHub stacks do not support cross-fork heads.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAF Automated Review — Iteration 1

Result: Findings reported
Scope: full PR (2 commit(s)): e912fce745d4, 53e1ce19f123
Model: gpt-5.6-sol-fast

Overview

The PR moves cumulative labels, hidden variables, audit records, and pending approvals into session-owned state, with strong owner checks, strict durable serialization, task-local middleware binding, and restoration tests. Explicit sessions are isolated and resumable, but the new lifecycle makes security state from omitted-session runs unreachable and leaves several public middleware state APIs silently attached to a detached standalone scope.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
2 verified findings remained after source verification (2 medium) across 1 file. Details are attached to the affected lines below.

Affected areas: python/packages/core/agent_framework/security.py

Returns:
List of violation records, or empty list if policy enforcement disabled.
"""
if session is None and self._provider_state_used:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When Agent.run() is called without a session, the framework creates a private generated session, but this new gate then rejects config.get_audit_log() and the caller has no session object it can pass instead. Existing session-optional callers therefore lose access to that run's policy audit state. Please keep this workflow retrievable, for example by exposing a per-run session/state handle, while still preventing reads from an unrelated standalone scope.

def _middleware_for_scope(self, scope: _SecurityScope) -> list[FunctionMiddleware]:
"""Clone the current overridable middleware stack into one scope."""
return [
middleware._clone_for_scope(scope) # pyright: ignore[reportPrivateUsage]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These scoped clones leave the public config.label_tracker and config.policy_enforcer handles attached to standalone state. After a provider run, calls such as config.label_tracker.reset_context_label() succeed but do not reset the session, so the next run can remain tainted and keep blocking tools; there is no session-aware replacement for context-label reset, metadata access, or audit clearing. Please route these stateful public operations through an explicit session scope, or make the detached handles fail loudly instead of silently reading or mutating the wrong state.

This branch was previously deployed

1 inactive deployment
github-app-auth — 53e1ce19 Deployed Sep 8, 2026 by eavanvalkenburg via team_check #3607
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants