Summary
MCP /mcp/{toolset} uses toolset scoping for tools/list, but tools/call resolves tools globally via resourceMgr.GetTool(toolName) without verifying membership in the toolset. A client connected to a low‑priv toolset can invoke any tool by name (IDOR/privilege escalation). The same issue exists for prompts/get.
Affected code
internal/server/mcp/v20241105/method.go: toolsCallHandler → resourceMgr.GetTool(toolName) (no toolset membership check)
internal/server/mcp/v20250326/method.go: same pattern
internal/server/mcp/v20250618/method.go: same pattern
internal/server/mcp/v20251125/method.go: same pattern
promptsGetHandler in the same files uses resourceMgr.GetPrompt(promptName) without promptset membership checks
Impact
If toolsets/promptsets are used as access boundaries, this allows unauthorized execution of tools/prompts outside the intended scope. Severity: High in deployments with privileged tools separated into different toolsets.
Repro (minimal)
- Configure toolset
public with only tool echo.
- Start server.
- Send:
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"admin_delete","arguments":{}}}
Observed: admin_delete runs.
Expected: request rejected because admin_delete is not in public.
Same for prompts/get with a prompt outside the promptset.
Suggested fix
Resolve tools/prompts from the current toolset/promptset (not the global registry), or explicitly check toolName ∈ toolset.ToolNames and promptName ∈ promptset.PromptNames before invoking.
Summary
MCP
/mcp/{toolset}uses toolset scoping fortools/list, buttools/callresolves tools globally viaresourceMgr.GetTool(toolName)without verifying membership in the toolset. A client connected to a low‑priv toolset can invoke any tool by name (IDOR/privilege escalation). The same issue exists forprompts/get.Affected code
internal/server/mcp/v20241105/method.go:toolsCallHandler→resourceMgr.GetTool(toolName)(no toolset membership check)internal/server/mcp/v20250326/method.go: same patterninternal/server/mcp/v20250618/method.go: same patterninternal/server/mcp/v20251125/method.go: same patternpromptsGetHandlerin the same files usesresourceMgr.GetPrompt(promptName)without promptset membership checksImpact
If toolsets/promptsets are used as access boundaries, this allows unauthorized execution of tools/prompts outside the intended scope. Severity: High in deployments with privileged tools separated into different toolsets.
Repro (minimal)
publicwith only toolecho.{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"admin_delete","arguments":{}}}Observed:
admin_deleteruns.Expected: request rejected because
admin_deleteis not inpublic.Same for
prompts/getwith a prompt outside the promptset.Suggested fix
Resolve tools/prompts from the current toolset/promptset (not the global registry), or explicitly check
toolName∈toolset.ToolNamesandpromptName∈promptset.PromptNamesbefore invoking.