2026年9月6日·2 分钟阅读

AI 工具执行的审批与防篡改执行链

SRE-Buddy 执行安全体系:审批、身份绑定与执行前校验

approvalzero-trust-agenttamper-proofSRE-Buddy

Note

SRE-Buddy 允许模型在目标主机上执行诊断命令。执行链的输入(模型参数)不可信,且审批环节天然存在"审批内容"与"执行内容"分离的时序替换风险。本文描述该执行链的安全设计:以单一规范执行请求贯穿审批与执行,身份字段由服务端从受信会话派生,审批内容固化为确定性摘要并在执行前强一致复验,审查异常一律转人工审批。

一、信任边界与设计原则

执行链要求模型产出工具参数(目标主机、登录账号、命令、超时等),并经人工批准后在目标主机执行。该模型的信任边界定义如下:

  1. 工具参数不可信。参数来源于模型输出,可能受提示词注入诱导、产生幻觉或误判,不作为可信输入直接使用。
  2. 审批存在两层不一致风险。审批人审阅的展示内容与执行器使用的参数若为两份数据,二者之间可发生时序替换(TOCTOU)。
  3. 执行身份仅能来自身份系统。操作用户与登录账号若可由模型参数决定,提示词注入即可直接提升权限。

对应的设计原则:

  • 单一规范对象:审批前构造统一的规范执行请求,审批完整保存该请求,通过后仅恢复原请求执行,不重新生成;
  • 身份服务端派生:操作人邮箱仅来自受信 SSO 会话,目标登录账号受白名单约束;
  • 内容字节级固化:审批时对请求计算确定性摘要,执行前重算并与审批摘要强一致比对;
  • 审查失败默认收口:自动放行条件不满足或审查组件异常时,一律转人工审批。
威胁形态未防护后果对策
提示词注入伪造高权限账号模型参数中的账号字段生效账号由邮箱派生,参数中的相关字段被忽略
批准后替换执行载荷(TOCTOU)审批展示与执行载荷不一致摘要固化 + 执行前复验
目标指向本机回环地址横向探测服务端自身目标主机回环校验拒绝
审查组件不可用请求被静默放行或静默拦截明确转人工审批

二、规范执行请求:ExecuteRequest

全链路仅围绕 backend/tool/executor.go 中的 ExecuteRequest 运行。其类型注释直接约束了使用方式:

Server 在审批前构造它,审批完整保存它,审批通过后只能恢复原请求,不得重新生成。

关键字段如下:

字段含义来源
Call规范化工具调用(含命令、目标主机参数)模型参数经规范化处理
ActorEmail操作人邮箱服务端从受信会话注入
ToolSource工具来源:native / mcp服务端判定
Provider传输方式:ssh / qssh服务端指定
RemoteUser跳板机侧登录用户由邮箱派生,参数值被忽略
TargetUser目标机登录账号白名单 qboxserver / root(默认前者)
TargetHost / TargetPort目标地址参数读取并校验
TimeoutSeconds命令超时(1–3600s)参数透传,默认 30

请求构造阶段即施加以下约束(NormalizeExecuteRequest / ValidateBashRequest):

  • 身份派生校验remote_user 仅允许由 actor_email 派生(邮箱 @ 前缀),两者不一致直接拒绝构造;模型参数中携带的 remote_user 在规范化阶段被移除;
  • 账号与传输白名单target_user ∈ {qboxserver, root}provider ∈ {ssh, qssh},native 来源仅允许 bash 工具;
  • 回环地址拦截:目标主机命中 localhost*.localhost 或解析为回环 IP 时,返回 tool: loopback target is not allowed

三、确定性摘要与规范化

审批必须作用于"将要执行的内容",而非"经过渲染的内容"。每个执行请求可计算确定性摘要(ExecuteRequest.Digest):

  1. 规范化工具调用;
  2. 将模型自述元数据(执行原因 reason、只读自评 is_read_only)从参数中拆分,纳入摘要计算;
  3. 对结构化输入执行 RFC 8785 (JCS) 规范化序列化backend/security/seal),消除字段顺序、空白与转义差异导致的哈希漂移;
  4. 计算 SHA-256,输出十六进制摘要。

摘要覆盖:调用 ID、会话 ID、工具名、参数、原因、只读自评、操作人、工具来源、MCP Server/工具、传输方式、跳板机用户、目标主机、目标端口、目标用户、命令全文、超时秒数。任一字段变更即导致摘要变化;等价写法必须产生相同摘要,该项由确定性测试保障。

四、审批单模型与批次一致性

审批单 approval.Request 持久化于 approval_requests 表,主键为 (session_id, tool_call_id),核心列包括 tool_callexecution_requestrequest_digeststatuspermission_modephase。状态机仅含 pending / approved / rejected 三种状态。

批次模型:同一模型响应中产生的多个工具调用共享 batch_id(取该响应首个调用 ID)。

  • 若批次内任一调用需要人工审批,整个批次进入待审状态,全部决策完成后按原始顺序执行。该约束保证同轮调用间的顺序语义与副作用一致,并避免"单独放行低风险调用"造成的越权缝隙。
  • 若批次内全部调用自动放行,则不等待审批,按序就地执行,避免只读诊断被流程阻塞。

批次顺序此前存在执行倒置缺陷,已修复(#630)。

创建校验:审批单创建时叠加多层校验——执行请求合法性、工具调用与审批单身份一致(会话与调用 ID)、请求类型自洽(native 不得携带 MCP 字段,反之亦然)、以及传入的 request_digest 与执行请求现算摘要一致。任一校验失败,审批单无法创建。

五、自动放行策略与失败收口

每个候选工具调用在进入审批前先经 Reviewer 执行一次独立审查(reviewToolCall),输出 {is_read_only, risk_level, expect_result}。审查结果以 tool_review 事件进入会话事件流,供前端展示只读标记与风险等级。

自动放行需同时满足:

  1. 会话权限模式非 require_approval
  2. 模型只读自评合法;
  3. Reviewer 判定只读;
  4. 风险等级为 low

任一条件不满足即转入人工审批。下列异常路径同样一律转人工,不产生任何静默放行:Reviewer 不可用、审查超时(默认 30 秒)、审查输出非法、模型自评字段非法。服务初始化失败时,系统记录"所有工具调用均需审批"告警。

会话层权限模式支持 defaultrequire_approval 两档:后者强制该会话全部工具调用人工审批,可在建会话时指定,亦可在会话运行中切换(PATCH /api/sessions/:id/permission-mode)。

六、审批决策的并发与一致性

决策入口约束:决策请求仅允许会话所有者发起;目标会话必须处于审批暂停态且该调用位于待审集合内,否则返回 409。

存储层原子性:决策过程以行级锁(SELECT ... FOR UPDATE)锁定审批单,并校验当前状态必须为 pending,否则返回 already decided

审计与状态一致性:状态更新与审计写入无法构成单一原子操作。为此引入显式阶段状态机 creating → committed → deciding → committed

  1. 锁定并校验状态为 pending
  2. phase 置为 deciding 并提交——此时 status 保持 pending,外部等待方不会提前读到终态;
  3. 写入审批审计事件;
  4. 审计成功后执行条件更新(WHERE phase = 'deciding')将 status 落为终态;
  5. 审计写入失败时,phase 回退为 committedstatus 保持 pending,允许审批人重新决策。

跨实例语义:审批服务基于共享 PostgreSQL,行锁与阶段检查在不同实例间天然互斥,后到决策返回 already decided

等待机制:编排层(waitForBatch)以审批服务的 Watcher 事件唤醒为主路径,并保留轮询兜底(100ms 起步、指数退避、上限 1 秒),避免 watcher 通道异常导致永久等待。

七、执行前校验与超时控制

决策就绪后,executeDecidedBatch 对每张 approved 审批单执行执行前绑定校验ValidateExecutionBinding):

  • 重新校验执行请求合法性;
  • 确认执行请求与审批单身份一致(会话与调用 ID);
  • 重算摘要并与审批时固化的 request_digest 比对。

校验失败即终止整轮,命令不下发。该步骤将批准后任何中间环节对载荷的修改——缓存错乱、跨实例同步异常或恶意替换——在执行前拦截。

被拒绝的调用以明确结果回传模型(tool call rejected by user,退出码 -1),拒绝事实进入会话与审计,不静默丢弃。

执行阶段配置硬超时保护:以请求超时加 5 秒作为 guard 时限,执行置于独立 goroutine,由主协程定时器裁决。底层执行器死锁、不响应取消(目标机进程 D 状态、通道半开)时,到点强制返回,会话不会无限挂起。

八、审批界面约束:决策倒计时

为抑制"批准动作过廉",前端对批准操作施加分级倒计时冷却(#645/#650):

风险等级批准等待
low0 秒
medium3 秒
high / critical / 未知5 秒

默认值由后端经 /api/me 下发,可通过 SRE_APPROVAL_COUNTDOWN_SECONDSSRE_APPROVAL_MEDIUM_COUNTDOWN_SECONDS 覆盖,置 0 即整体关闭。倒计时期间批准按钮置灰并显示剩余秒数;拒绝操作不设冷却,任何时刻立即可执行。

命令超时参数(默认 30 秒)透传至审批单并在卡片展示(#607/#608),审批人可确认该命令的执行时限。

九、方案确认的结构化表达

执行方案的人机确认,早期依赖模型输出特定文本标记与前端状态机握手。该方案受流式输出截断、标记改写与错误时机复用影响,状态机脆弱(#631)。

当前实现改为结构化工具调用 propose_remediation_plan

  • 方案必须独占一轮,不允许与产生执行副作用的工具调用同批出现,违规时整轮报错并提示等待用户确认;
  • 引擎仅暴露工具 Schema,不执行该工具,方案本身不产生副作用;
  • 模型产出方案后,轮次以"等待用户确认执行"结束,前端渲染确认操作;用户确认后以新消息驱动执行批次,该批次仍走完整的规范化、审批与摘要校验链。

一般性原则:需要与人工握手的协议状态,应以带 Schema、可校验、不可与副作用调用混淆的结构化事件表达,而非依赖模型恰好输出特定文本。

十、防重放与幂等性

场景机制效果
审批创建(session_id, tool_call_id) 唯一键 + 创建时摘要强校验重复提交与创建前载荷变更被拒
审批决策行锁 + pending 状态检查 + 阶段机一张单据仅可决策一次
批次执行整批等待、按原始顺序执行防止乱序与部分放行越权
执行前校验摘要重算并与 request_digest 比对阻断批准后的时序替换
超时执行guard 定时器硬超时执行器挂起不阻塞会话

小结

上述机制将批准内容与执行内容的一致性作为核心不变量:审批时固化规范请求与摘要,执行前复验摘要,身份仅取自受信会话,审查异常一律转人工。各环节的审计记录与幂等约束为该不变量提供可追溯支撑。

返回文章列表

评论

评论组件加载中…

0%