ARTICLE / 安全
凭据多走一步,权限早放一秒:智能体三道边界
智能体框架最危险的时刻,往往不是黑客发起攻击的时刻,而是它自己的组件在边界上交换信息的一瞬间。
2026 年 9 月到 10 月,OpenClaw 公开仓库出现三个 issue:一个发生在浏览器工具的输出处理,一个在 Codex 子进程的工具分发,一个在 Talk 实时会话的异步回调。功能上毫不相干,结构上却是同一类错误——授权信息在组件边界上,要么多走了一步,要么没有按实际使用时间持有[1][2][3]。
把这三个案例放在一起看的价值在于:它们给出了智能体基础设施权限设计的三道通用考题。任何在做 agent 平台的团队,都可以拿自己的系统对照作答。
第一道:凭据不该跟着连接地址进入模型视野
Issue #158966 记录了一个输出边界问题:当 loopback CDP 端点包含 HTTP Basic 凭据或 query token 时,标签页列表和打开结果会把派生出的带凭据 WebSocket URL 一并交给模型[1]。
拆开看:模型操作标签页实际用的是 targetId,完全不需要建立连接用的认证信息。凭据对运行时建立连接是必要的——问题出在输出处理链上:formatAgentTab 复制了 wsUrl,而本应裁剪内部信息的 stripBrowserOpenInternalMetadata 移除了所有权、resolvedProfile 等字段,却保留了 wsUrl[1]。凭据就这样从"运行时内部数据"变成了"模型可见文本"。
这个 case 的验证方法值得一提:调用生产环境的 URL 规范化、标签页动作和打开结果过滤函数,只在浏览器代理边界注入合成响应,不连接真实浏览器。它能证明这些函数在给定输入下会保留带凭据地址,但不能替代完整的 Chrome 端到端验证——报告对此的边界划分很诚实[1]。另外,相关实现 PR #137756 正按作者要求撤回,但关闭 PR 不等于缺陷已修复;该 issue 被标 stale 也只是因为长期无活动,不是维护者认定问题解决了[1]。
留下一个可直接落地的检查:连接凭据和操作标识不应依赖同一个输出字段。 运行时内部可以持有带凭据的连接地址,但交给模型的输出只应包含它真正需要的 targetId 和页面元数据。
第二道:工具出现在目录里,不代表它有执行通路
Issue #150822 关注另一种错位。环境为 OpenClaw 2026.9.4,父进程用 native Codex app-server,子进程通过 native collaboration.spawn_agent 创建。对照现象:父进程能成功执行 gateway_exec canary,子进程的同类调用失败——子进程能发现工具定义,调用时却返回 “OpenClaw did not register a handler for this app-server tool call."[2]。
独立复核确认了机制:子进程请求找不到精确注册的路由时,就会得到这个失败响应。也就是说,工具出现在模型可见的能力目录里,但系统没有为它注册对应的执行处理器——模型"看得见"它,却无法据此判断调用是否可用。报告同时包含"分离式失败通知”(detached failure delivery)的疑问,但多条复核记录明确:这部分未被独立复现,不能与缺少执行处理器合并成一条已完整验证的故障链[2]。
源码侧的解释是:native 子进程监控器负责任务、历史通知和子任务认领,不负责入站子工具执行分发;而父级的精确 thread/turn 守卫不能移除——否则子进程可能绕过父级权限与生命周期限制[2]。这直接排除了"让子进程继承父进程工具句柄"这种直觉修法:保留的 native model 和 source 权限并不自动产生子作用域的记忆工具权限,native pre-tool 恢复租约也不是通用的 detached 工具执行授权[2]。
缺少执行器本身不构成越权,但它制造了一种更隐蔽的风险状态:能力目录撒谎。 模型基于目录做规划,规划里包含一个实际不可达的调用——智能体系统的行为可预测性从这里开始崩坏。
第三道:连接还在,setup 阶段的权限却已经释放
Issue #167876 把问题推进到时间维度。Gateway 拥有的 Talk 实时会话能完成 setup、接收音频,但 provider 随后触发 agent 咨询时失败,报错 Gateway caller authority is no longer active.[3]。
复现路径三步:认证创建 Gateway 拥有的实时会话 → websocket 分发释放已完成 setup 请求所持有的 caller authority → 调用 provider 的 agent-consult 回调,后续权限捕获失败。native run admission 同样没有收到原始操作者来源。该 issue 被标记为高置信度源码级复现[3]。
这里的结构性错误是:权限生命周期与连接生命周期不一致——setup 结束就释放调用方权限,而稍后才到达的咨询仍需要它。注意边界:它不是权限绕过,也不代表所有版本的实时咨询都会失败;是否出现取决于版本、传输路径和后续执行位置[3]。
三道考题合成一张检查表
三个 issue 的共同点,不是"都属于智能体安全问题",而是授权信息没有沿着实际使用路径被准确保管。各自对应一条边界:
| 边界 | OpenClaw 的失误 | 通用检查 |
|---|---|---|
| 空间(输出) | 凭据随 wsUrl 越过输出边界 | 模型可见输出里,是否出现了操作并不需要的凭据、内部地址、认证字段 |
| 能力(执行) | 目录里的工具没有执行处理器 | 每个向模型公开的工具,是否都有可到达、权限明确的执行处理器 |
| 时间(租约) | 权限释放早于异步回调的实际使用 | 异步回调真正发生前,原始调用方权限是否仍在有效期 |
我把它提炼成设计时的"授权生命周期三问":谁需要看见?(最小可见)谁能执行?(能力对齐)什么时候过期?(生命周期对齐) 三问里任何一问答错,答案都不会立刻变成安全事故——这正是它们危险的地方:凭据进上下文、目录与执行器脱节、租约错配,在日常运行里都表现为"没事"。它们等着的是一个恰好需要这些错位的攻击者。
这三项检查还有一层方法论价值:它们不依赖攻击者先找到利用链,而是直接审查系统有没有把自己的连接、能力、授权交代清楚。对自托管智能体基础设施,这比盯着"某个工具是否对外可见"更接近真实的风险边界——因为攻击者的第一步从来不是绕过你设计的防线,而是找你没想到的那条缝。
本文面向授权安全研究与防御建设。未经授权对任何系统实施文中技术属违法行为。
参考
- OpenClaw 公开仓库 issue #158966——浏览器工具输出边界:
formatAgentTab复制wsUrl、stripBrowserOpenInternalMetadata保留带凭据地址;合成响应验证边界;PR #137756 撤回与stale说明。快照(2026-10-26 采集):sources/oc_158966.txt - OpenClaw 公开仓库 issue #150822——OpenClaw 2026.9.4 父/子进程
gateway_exec对照、缺少执行处理器机制复核、detached failure delivery 未独立复现、native 子进程监控器职责与父级 thread/turn 守卫。快照:sources/oc_150822.txt - OpenClaw 公开仓库 issue #167876——Talk 实时会话
Gateway caller authority is no longer active.三步复现、高置信度源码级复现标记、权限生命周期与连接生命周期不一致。快照:sources/oc_167876.txt
本文事实层以上述一手来源为限;「授权生命周期三问」「能力目录撒谎」为作者分析框架,非来源原文观点。
参考来源:OpenClaw 公开仓库 issue #158966、#150822、#167876 原始页面(2026-10-26 采集快照)。
