s14: MCP handler defaults can be overridden by tool input, bypassing host policy
维护者通常 8 天内回复
评估
调研方向
从 s14_mcp_plugin/code.py 第 357 行左右开始,那里构建了 MCP 处理函数,然后阅读 permission_hook,了解 mcp_tool_policies 如何通过带前缀的名称作为键。运行 issue 中最小化的 FakeClient 复现,确认输入中的 'tool' 键会覆盖默认值。完成的标准是:调用时的 kwargs 无法再改变被路由的工具,并且带有额外 'tool' 键的 status 调用会被拒绝或不会被路由到 trigger。
由索引模型根据 Issue 内容生成。
描述
Summary
In s14_mcp_plugin/code.py, MCP handlers are built like this (around line 357):
handlers[prefixed] = (
lambda *, client=server, tool=raw_name, **kwargs:
client.call_tool(tool, kwargs)
)
The default arguments fix the late-binding problem described in README §5. However, tool and client are still ordinary keyword parameters. If the model's tool input contains a "tool" key, it replaces the default. The call is then routed to a different server tool than the one that permission_hook checked.
Why it matters for this lesson
permission_hook looks up mcp_tool_policies by the prefixed name only. With the default MCP_HOST_POLICY, ("deploy", "status") is allow, and ("deploy", "trigger") is confirm. So this tool call:
{"name": "mcp__deploy__status", "input": {"service": "web", "tool": "trigger"}}
passes as status without asking the user. The deploy server then runs call_tool("trigger", {"service": "web"}) and returns [deploy] Triggered: web.
The model might send this input by mistake, or because content it read told it to. Lesson 6 says the host policy decides what runs, and this input gets around that policy. The input schema is not validated before dispatch, so the extra key is not rejected.
Minimal repro (no API key needed)
class FakeClient:
def call_tool(self, tool, args):
return f"server ran {tool!r} with {args}"
server = FakeClient()
handlers = {}
for raw_name in ["status", "trigger"]:
prefixed = f"mcp__deploy__{raw_name}"
handlers[prefixed] = (
lambda *, client=server, tool=raw_name, **kwargs:
client.call_tool(tool, kwargs)
)
print(handlers["mcp__deploy__status"](**{"service": "web", "tool": "trigger"}))
# server ran 'trigger' with {'service': 'web'}
I also reproduced this with the unmodified s14_mcp_plugin/code.py. I used a scripted fake Anthropic client that returns the tool call above. The status call ran trigger without a permission prompt.
Suggested fix
Bind the values in a closure so that call-time arguments cannot reach them:
def make_handler(client, tool):
return lambda **kwargs: client.call_tool(tool, kwargs)
handlers[prefixed] = make_handler(server, raw_name)
With this change, the same input calls status with an extra tool argument. The demo server's status function rejects that argument with MCP error: TypeError: ... unexpected keyword argument 'tool', and nothing is deployed. functools.partial would not fix this, because keyword arguments given at call time also override the keywords stored in a partial.
If you want a short line in the README, §5 could say that default arguments solve late binding but remain overridable by caller kwargs.
Thanks for the great course! I found this while building a Traditional Chinese walkthrough of it.
- 主要语言
- Python
- 星标
- 79.9k
- 派生
- 12.8k
- 平均合并
- 7 天 17 小时
- 30 天内合并 PR
- 4
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
shareAI-lab/learn-claude-code 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 75/100
shareAI-lab/learn-claude-code#583 ·
维护者通常 8 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
shareAI-lab/learn-claude-code#528 ·
维护者通常 8 天内回复
-
s17: IDLE teammates cannot resume their own in-progress tasks可能已有人在做 @hichipli 于 70 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 84/100
shareAI-lab/learn-claude-code#519 ·
维护者通常 8 天内回复
-
s09: select_relevant_memories 的 "recent" 拼接顺序与切片不合理,不是真正的最近 2k 上下文可能已有人在做 @siri666942 于 87 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
shareAI-lab/learn-claude-code#517 ·
维护者通常 8 天内回复
-
plan_approval_response 不会唤醒 idle teammate可能重新可做 关联的 PR 已关闭且未合并。 未关闭
难度 2/5 1-3 小时 新手友好度 72/100
shareAI-lab/learn-claude-code#455 ·
维护者通常 8 天内回复
查看 shareAI-lab/learn-claude-code 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
cunla/fakeredis-py#636 ·
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
opensafely-core/job-server#6180 · 1 条评论 ·
维护者通常 1 天内回复
-
area:models enhancement
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
bug needs-triage
难度 2/5 1-3 小时 新手友好度 86/100
newrelic/newrelic-python-agent#1913 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 77/100
维护者通常 1 天内回复