Declarative MCP invocations may expose protected workflow values to external servers
Summary
Microsoft.Agents.AI.Workflows.Declarative did not enforce its protected-value boundary when evaluating inputs for an InvokeMcpTool action. A declarative workflow could therefore forward values marked SensitivityLevel.Sensitive, including environment-scoped secrets, to an external MCP server.
Details
Expressions used for the MCP server URL, server label, tool name, arguments, and transport headers are evaluated by the workflow expression engine. The resulting values include sensitivity metadata that identifies values derived from protected sources such as the workflow environment scope.
In vulnerable versions, InvokeMcpToolExecutor used only the evaluated raw values and discarded their sensitivity metadata. The values were then included in an approval request or passed to the configured MCP handler. The default MCP handler sends evaluated arguments and headers to the workflow-selected MCP server, creating an external data-exfiltration path.
Other declarative action executors already rejected protected values before exposing them outside workflow state. The missing checks in InvokeMcpToolExecutor.GetServerUrl, GetServerLabel, GetToolName, GetArguments, and GetHeaders created an inconsistent security boundary.
Proof of concept
A sanitized reproduction can be performed with a mocked MCP handler:
1. Add PROTECTED_SETTING to the...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| Microsoft.Agents.AI.Workflows.Declarative NuGet | < 1.24.0 | 1.24.0 |
Details and references
### Summary `Microsoft.Agents.AI.Workflows.Declarative` did not enforce its protected-value boundary when evaluating inputs for an `InvokeMcpTool` action. A declarative workflow could therefore forward values marked `SensitivityLevel.Sensitive`, including environment-scoped secrets, to an external MCP server. ### Details Expressions used for the MCP server URL, server label, tool name, arguments, and transport headers are evaluated by the workflow expression engine. The resulting values include sensitivity metadata that identifies values derived from protected sources such as the workflow environment scope. In vulnerable versions, `InvokeMcpToolExecutor` used only the evaluated raw values and discarded their sensitivity metadata. The values were then included in an approval request or passed to the configured MCP handler. The default MCP handler sends evaluated arguments and headers to the workflow-selected MCP server, creating an external data-exfiltration path. Other declarative action executors already rejected protected values before exposing them outside workflow state. The missing checks in `InvokeMcpToolExecutor.GetServerUrl`, `GetServerLabel`, `GetToolName`, `GetArguments`, and `GetHeaders` created an inconsistent security boundary. ### Proof of concept A sanitized reproduction can be performed with a mocked MCP handler: 1. Add `PROTECTED_SETTING` to the workflow environment scope with the value `protected-value` and mark it `SensitivityLevel.Sensitive`. 2. Create an `InvokeMcpTool` action targeting a test MCP server. 3. Set an MCP argument, such as `query`, to the expression `Env.PROTECTED_SETTING`. 4. Set a transport header, such as `X-Custom`, to the same expression. 5. Execute the action using a mocked `IMcpToolHandler`. 6. Observe that a vulnerable version invokes the handler with `protected-value` in both the argument and header. The expected secure behavior is to throw a `DeclarativeActionException` before creating an approval request or invoking the MCP handler. The regression tests added by the fix verify that protected server URLs, server labels, tool names, arguments, and headers are rejected in both direct and approval-based execution. ### Impact An application is affected when it executes declarative workflow definitions supplied by an untrusted or less-trusted actor, exposes secrets or other protected configuration values to the workflow environment scope, and permits the workflow to invoke MCP tools. Under those conditions, a malicious workflow can reference a protected environment value in an MCP invocation input and send it to an attacker-selected MCP server. This can disclose API keys or other secrets belonging to the affected application. This is not a cross-tenant issue, and no exploitation or customer impact is known.