Summary
When the AI agent decides to call an MCP tool, AIChatService passes functionCallItem.FunctionName directly to mcpClient.CallToolAsync() without first validating that the function name is in an allowed set. A prompt-injected payload that persuades the model to fabricate a tool call with an arbitrary name could cause unexpected behavior.
Affected Code
EssentialCSharp.Chat.Shared/Services/AIChatService.cs — both GetChatCompletionCore and ExecuteFunctionCallAsync:
// No allowlist check before calling
var toolResult = await mcpClient.CallToolAsync(
functionCallItem.FunctionName, // ← comes directly from model output
arguments: arguments,
cancellationToken: cancellationToken);
The list of tools is loaded from the MCP client at request time:
var mcpTools = await mcpClient.ListToolsAsync(cancellationToken: cancellationToken);
But this list is only used to advertise tools to the model — it is not re-checked when a tool call is received back from the model.
Risk
OWASP AI Agent Security — Risk: Tool Abuse & Privilege Escalation
If an indirect prompt injection convinces the model to emit a FunctionCallResponseItem with a crafted FunctionName, the application will attempt to call that tool name. While the MCP server would likely reject unknown tool names, the defense-in-depth principle dictates that the client should also enforce the allowlist. Future tool additions or MCP client changes could inadvertently expose new capabilities.
Recommended Mitigation
Cache the list of allowed tool names retrieved in CreateResponseOptionsAsync and validate each incoming FunctionName against it before calling:
// In CreateResponseOptionsAsync, return the allowed names alongside options
var mcpTools = await mcpClient.ListToolsAsync(cancellationToken: cancellationToken);
var allowedToolNames = mcpTools.Select(t => t.Name).ToHashSet(StringComparer.Ordinal);
// In ExecuteFunctionCallAsync / GetChatCompletionCore, before CallToolAsync:
if (!allowedToolNames.Contains(functionCallItem.FunctionName))
{
// Log and reject — do not call the tool
logger.LogWarning("Model requested disallowed tool: {ToolName}", functionCallItem.FunctionName);
return ("Tool not permitted.", responseId);
}
References
Summary
When the AI agent decides to call an MCP tool,
AIChatServicepassesfunctionCallItem.FunctionNamedirectly tomcpClient.CallToolAsync()without first validating that the function name is in an allowed set. A prompt-injected payload that persuades the model to fabricate a tool call with an arbitrary name could cause unexpected behavior.Affected Code
EssentialCSharp.Chat.Shared/Services/AIChatService.cs— bothGetChatCompletionCoreandExecuteFunctionCallAsync:The list of tools is loaded from the MCP client at request time:
But this list is only used to advertise tools to the model — it is not re-checked when a tool call is received back from the model.
Risk
OWASP AI Agent Security — Risk: Tool Abuse & Privilege Escalation
If an indirect prompt injection convinces the model to emit a
FunctionCallResponseItemwith a craftedFunctionName, the application will attempt to call that tool name. While the MCP server would likely reject unknown tool names, the defense-in-depth principle dictates that the client should also enforce the allowlist. Future tool additions or MCP client changes could inadvertently expose new capabilities.Recommended Mitigation
Cache the list of allowed tool names retrieved in
CreateResponseOptionsAsyncand validate each incomingFunctionNameagainst it before calling:References