AI and data stack advisories

Severe, 6 weeks117Projects324

117 severe, 6 weeks · 324 projects

MicrosoftGHSA-8j78-92fm-c727

Cross-session state and chat-message disclosure in reused .NET workflow executors

Microsoft

Published Oct 23, 2026

Medium5.4
Fix: upgrade to 1.26.0 or later
GitHub advisory

Summary

Microsoft Agent Framework's .NET workflows can retain state from another AgentSession when an application hosts a workflow through AsAIAgent and reuses an instance-bound, application-defined StatefulExecutor<TState> or ChatProtocolExecutor subclass. In the affected configuration, one session can observe another session's state. A failed or cancelled chat turn can also leave messages that are included in a later session's model input.

Details

The affected StatefulExecutor<TState> implementation keeps a per-instance _stateCache. ReadStateAsync can return that cache before consulting the current workflow context, and InvokeWithStateAsync can use it as the state for a subsequent run. The cache can therefore outlive the session whose state it represents when a non-concurrent hosted workflow reuses the executor.

ChatProtocolExecutor derives from StatefulExecutor<List<ChatMessage>> and uses the same state mechanism to accumulate turn messages. Its normal turn path replaces the accumulated messages after processing succeeds. If processing fails or is cancelled before that replacement, the old cache can remain available to a different session.

The demonstrated setup uses an application-defined start executor, instance binding, the default declareCrossRunShareable = false, and multiple AgentSessions served by the same hosted workflow agent. The report's...

Affected versions

PackageAffectedFixed in
Microsoft.Agents.AI.Workflows
NuGet
< 1.26.01.26.0
Details and references

### Summary Microsoft Agent Framework's .NET workflows can retain state from another AgentSession when an application hosts a workflow through AsAIAgent and reuses an instance-bound, application-defined StatefulExecutor<TState> or ChatProtocolExecutor subclass. In the affected configuration, one session can observe another session's state. A failed or cancelled chat turn can also leave messages that are included in a later session's model input. ### Details The affected StatefulExecutor<TState> implementation keeps a per-instance _stateCache. ReadStateAsync can return that cache before consulting the current workflow context, and InvokeWithStateAsync can use it as the state for a subsequent run. The cache can therefore outlive the session whose state it represents when a non-concurrent hosted workflow reuses the executor. ChatProtocolExecutor derives from StatefulExecutor<List<ChatMessage>> and uses the same state mechanism to accumulate turn messages. Its normal turn path replaces the accumulated messages after processing succeeds. If processing fails or is cancelled before that replacement, the old cache can remain available to a different session. The demonstrated setup uses an application-defined start executor, instance binding, the default declareCrossRunShareable = false, and multiple AgentSessions served by the same hosted workflow agent. The report's factory-bound control was isolated. The report does not establish that all built-in orchestrations or other language implementations are affected. ### Proof of concept Use an in-process test with inert marker strings and a mocked chat implementation; no external model or service is required. 1. Define a StatefulExecutor<List<string>> subclass that appends incoming message text to workflow state and returns that state as its response. 2. Bind one instance as the workflow's start executor, host it with AsAIAgent, and create two distinct AgentSessions. 3. Send SESSION_A_MARKER through session A, then SESSION_B_MARKER through session B, then resume session A. 4. On the affected implementation, session B can receive state containing SESSION_A_MARKER, and the resumed session A can contain session B's text. Expected behavior is that each session observes only its own state. 5. For the chat variant, use an application-defined ChatProtocolExecutor with a mocked turn handler that fails or is cancelled on session A's first turn. Run session B using the same hosted agent and inspect the messages supplied to the handler. The affected implementation can include session A's marker; expected behavior is that session B receives only its own turn messages. The report reproduced the behavior with package version 1.24.0. These steps describe a sanitized local reproduction, not an instruction to test a live service. ### Impact Applications serving multiple users through the same affected hosted workflow agent can expose state or chat content across session boundaries. A user able to submit messages to that agent can contribute content that later appears in another session. For the chat variant, a failed or cancelled earlier turn is an additional prerequisite; carried-over messages can influence subsequent model input. The demonstrated boundary is between users or sessions within one application. It does not establish a Microsoft cloud cross-tenant compromise, arbitrary code execution, or effects in deployments that do not reuse the affected executor instances.

CVSS 3.1
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
Severity from
GitHub (reviewed advisory)
Weakness
CWE-488, CWE-524

More Microsoft advisories

All Microsoft