Claude 与 Skill
把工具白名单放在 MCP 服务器端而不是 CLI 参数里:osFoundry 的安全设计拆解
osFoundry 在以 bypassPermissions 模式运行 Claude Code 时,不在命令行传 --allowedTools,而是把工具白名单做进 MCP 服务器。作者解释了为什么客户端参数在无人值守的 agent 模式下形同虚设,并用约 230 行 Python 复刻了这套 bridge,附上实测性能数据。
今天就能做
- 如果你的 agent 以 bypassPermissions 无人值守运行,别依赖 --allowedTools,把工具过滤做进 MCP 服务器端
- 在 tools/call 层对工具名做二次校验,防止模型调用从未在 tools/list 里出现过的工具
- workspace_id、channel_id 等上下文在启动时绑定,永远不要从请求参数里读取
为什么白名单不能放在 CLI 参数里
- agent 模式下 Claude Code 用 --permission-mode bypassPermissions 运行,此时 --allowedTools 会被直接忽略,flag 纯属装饰
- flag 是给客户端的指令,而客户端正是执行模型所指挥代码的一方,不能把唯一一道防线放在这里
- 服务器能看到每一次 tools/call,且不受模型控制,所以过滤工作必须由服务器承担
服务器端的两道过滤
- tools/list 只返回本次运行白名单内的工具,模型根本不知道其他工具存在
- tools/call 在执行前再校验一次工具名:模型可能从训练数据或被注入的文件里说出从未列出的工具名,第一道过滤挡不住这种情况
- 核心原则是 Never trust the client; the server decides
用 Python 复刻 bridge 并验证
- 注册表含 memory_search、execute_command、delete_file 三个工具,本次运行只允许 memory_search
- 模型尝试调用未列出的 execute_command(rm -rf),被服务器以 -32601 拒绝,审计日志中该调用从未到达执行层
- 模型试图通过参数把 workspace_id 指向别的 workspace,bridge 使用启动时绑定的 workspace_id,跨空间搜索返回空结果
- 错误 token 的请求返回 401,运行结束后端口立即关闭,不留存活 listener
性能开销实测
- 在 Apple M1 上,bridge 启动加握手约 3 ms,相比 Claude Code 进程本身的启动时间可以忽略
- 被拒绝的调用与被允许的调用耗时几乎相同(p50 均 0.41 ms),校验只是一次列表查找
- 唯一的坑是 Python serve_forever 默认 poll_interval 0.5 s,导致关停多等半秒;Rust 版用 tokio::select! 可即时唤醒,Python 侧调小 poll_interval 即可
协议兼容性细节
- 服务器对无 id 的 JSON-RPC 消息和 notifications/ 方法返回 202 空响应体
- 原因是 Codex 的 rmcp 客户端收到 200 加 {} 的通知会直接断开传输,导致整个运行在握手阶段就挂掉,Claude Code 则能容忍
- 每次请求新建连接(Connection: close),工具以 mcp__<server>__<tool> 命名暴露给 Claude Code
原文:Por qué osFoundry aplica la lista de herramientas permitidas de Claude Code en el servidor MCP y no en los flags de la CLI
来源:DEV Community · 2026-11-08
查看原文本文由 AI 阅读原文后整理,未经人工逐字核对,内容以原文为准。
登录后可以点赞、查看和发表评论