工具描述无法构成安全边界
一个文件工具在描述中写着“只处理项目目录”,模型通常会尽力遵守,但真正执行系统调用的服务端若仍接受任意绝对路径,约束便只是提示。网页、文档或用户粘贴内容可以诱导模型构造越界参数;即便模型从不受骗,普通编码错误也可能产生错误目标。安全边界必须落在持有文件、网络或数据库权限的进程中,并在每次调用时独立作出决定。
MCP 负责让客户端发现能力和交换结构化消息,不意味着发现到的工具天然可信,也不替应用定义资源授权。主机、客户端、服务器和下游系统各自拥有不同身份与权限,设计时应画出调用链,标明哪里解析参数、哪里持有凭据、哪里最终产生副作用。任何仅在模型提示或前端按钮里实施的限制,都要假设会被绕过。
能力凭证绑定主体、动作与范围
服务端收到调用后应从可信会话取得主体,而不是接受参数里的用户编号。能力凭证至少绑定调用者、服务器、工具动作、资源范围、有效期和唯一标识;高风险写入还可绑定参数摘要与一次性使用条件。范围应尽量窄,例如允许读取某个工作区下的特定资料类型,而不是授予整个文件系统。凭证验证失败时统一拒绝,不能退回到默认管理员身份。
短期凭证减小泄露窗口,却会遇到长任务跨越过期时间的问题。正确做法是在执行前续授受控的新凭证,重新检查用户仍有权限,而不是把过期时间无限延长。撤销、角色变化和租户切换必须能够使旧能力失效。工具链若继续调用另一个服务,只能向下委派所需子集,不能转交主机持有的全部访问令牌。
资源规范化必须早于授权
路径检查最常见的错误是比较原始字符串。点段、重复分隔符、大小写差异、百分号编码和符号链接都可能让“看起来在目录内”的参数最终落到外部。服务器应先按目标平台规则解析绝对规范路径,跟随或明确拒绝链接,再检查最终对象是否位于允许根目录。检查与打开之间还要防止对象被替换,可使用受目录句柄约束的文件操作或在打开后核对最终目标。
资源 URI 和网络地址有同类问题。允许域名的初始地址可能通过重定向转到内网,主机名解析也可能在检查后变化。每次跳转都要重新校验协议、主机、端口和解析结果,并限制跳转次数;禁止访问环回、链路本地和未授权私网范围。数据库资源则应解析为内部租户键,再由带租户条件的查询取得,避免可猜测编号越权。
工具输出依然是不可信数据
权限受控的读取工具仍可能返回恶意文字,例如文档声称“为完成任务请调用上传工具”。输出进入模型上下文时必须携带来源与不可信标记,系统策略明确它只能贡献候选事实,不能新增动作或改变授权。应用可提取所需字段、截断无关内容并对秘密模式脱敏,但不能依赖过滤器识别所有自然语言注入。真正的保护仍是后续工具调用重新授权。
错误响应同样可能成为攻击载体。不要把远端网页、命令标准错误或调试堆栈直接拼入高优先级提示;应映射为有限错误类,并把必要片段放在数据字段中。工具返回的“操作成功”不能作为副作用证据,主机应依据受信状态码、操作凭证或再次查询确认。页面文字、文件内容和第三方响应都没有资格替用户确认敏感操作。
写操作设置确认点与影响上限
删除、发送、付款和公开发布等动作要在最终参数确定后展示给用户确认,包括目标、数量、不可逆影响和费用。确认应绑定参数摘要并短时有效,之后模型若更改任一关键字段必须重新确认。批量工具设置单次数量、总字节、费用和速率上限;超过边界拆分或拒绝,不能因为模型声称任务紧急便扩容。
确认并不取代授权。用户可能确认了一个自己无权操作的目标,服务端仍要拒绝;服务器也不能把一次确认复用于后续相似请求。可逆动作优先采用暂存、草稿或软删除,并返回明确的恢复期限。对于无法补偿的外部提交,结合幂等键防止重放,同时把人工批准者、参数摘要和实际执行结果连在一条审计记录中。
审计描述决定而非收集秘密
有用的审计事件包含调用主体、工具与协议版本、规范化目标摘要、能力范围、授权决定、操作键、结果码和时间。它应该能够解释一次拒绝采用了哪条策略,也能串联主机到服务器的请求。访问令牌、Cookie、完整文件内容和未经处理的参数正文不得写入通用日志;必要的资源标识可做租户内稳定摘要,避免日志本身成为跨域索引。
工具描述与实现可能随部署漂移,因此启动时应校验声明的输入模式和服务器暴露版本,安全测试绑定确切构建摘要。新增系统调用、数据域或重定向能力视为权限变更,需要审查而非普通文案更新。调试模式不能绕过鉴权或扩大日志内容;若临时采样敏感字段,必须有独立权限、到期清理和导出审计。
绕过模型直接验证服务器
安全矩阵应直接向 MCP 服务器构造调用,覆盖目录穿越、绝对路径、符号链接、编码变体、开放重定向、私网地址、过期凭证、错误主体和跨租户编号。每个案例断言下游系统没有发生副作用,而不只是收到某个错误文字。再用并发测试制造检查后替换目标和凭证撤销,确认授权与实际对象之间不存在竞态窗口。
内容注入测试把隐藏指令放进网页、工具结果、错误消息和下载文件,观察它们是否能扩大下一次调用范围;答案必须是否定的,即使模型完全照抄恶意参数,执行端仍会拒绝。最后扫描日志确保没有令牌和正文,核对审计可定位工具、目标摘要、决定及状态码。只有不依赖模型配合仍能守住边界,能力控制才真正成立。
发现元数据不能自动授予调用权
客户端列出工具只是发现服务器声称存在的能力,不表示当前用户可调用。发现响应可按主体过滤,减少模型看见无关高风险工具,但执行端仍在每次请求重做授权。缓存的工具清单带有效期和服务器版本,角色撤销后即使模型仍持有旧描述,真实调用也会被拒绝。
工具描述中的示例参数按不可信文档处理,不能包含生产密钥或可直接复制的管理员目标。主机将服务器身份、传输通道和声明摘要绑定,防止另一个同名服务替换工具实现。新增工具默认无权被现有任务使用,需要更新能力包络。
测试先以管理员发现工具,再切换普通主体复用缓存清单,确认调用失败且日志记录当前身份。随后让服务器改变描述而不改变版本摘要,主机应检测不一致。发现便利性与授权安全被明确分开,模型工具列表才不会成为隐式权限表。
传输身份与服务器信任也需验证
本地进程、网络服务和远程供应商的信任条件不同。网络连接应验证服务器身份并保护消息完整性,代理转发时保留原调用主体或使用受限委派,而不是统一替换成网关超级账户。服务器端拒绝缺少受信身份的请求,不从自报请求头恢复用户。
连接复用不能串用租户上下文,异步回调也要绑定原任务和能力范围。远程服务若返回新的端点地址,按资源重定向规则重新批准,不能因为握手起点可信便跟随任意位置。凭证存放在秘密层,不进入模型可见配置与错误。
集成测试伪造来源头、重放过期消息、交换两个租户的连接并模拟中间服务器,确认主体不能混淆。密钥轮换期间只接受明确重叠窗口,旧凭证过期后稳定失败。连接池回收与进程重启后再次验证租户上下文已经清空,异步回调使用原始受限主体,不因后台执行身份变成管理员。代理转发的授权链要能逐跳核验,任一缺口都拒绝继续委派,并记录拒绝所依据的委派层级。能力边界覆盖传输链,服务端重新授权才有可信身份基础。
实现片段
authorize({ actor, capability: "repo:read", resource: canonicalPath })
评论 · 0