Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help


id: ADR-018 title: 运行时安全与溯源采用运行时自有的决策边界 date: 2026-08-17 status: 提议中 relates-to:

  • https://github.com/zeroclaw-labs/zeroclaw/issues/7142
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6971
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6954
  • https://github.com/zeroclaw-labs/zeroclaw/issues/7432
  • https://github.com/zeroclaw-labs/zeroclaw/issues/7141
  • https://github.com/zeroclaw-labs/zeroclaw/issues/7155
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6996
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6909
  • https://github.com/zeroclaw-labs/zeroclaw/issues/3767
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6105
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8583
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8289
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8290
  • https://github.com/zeroclaw-labs/zeroclaw/pull/10425
  • docs/book/src/architecture/request-lifecycle.md
  • docs/book/src/architecture/background-work-lifecycle.md
  • docs/book/src/architecture/tool-execution-lifecycle.md
  • docs/book/src/security/model.md
  • crates/zeroclaw-api/src/ingress.rs
  • crates/zeroclaw-runtime/src/agent/turn/mod.rs
  • crates/zeroclaw-runtime/src/security/ingress.rs
  • crates/zeroclaw-runtime/src/security/audit.rs
  • crates/zeroclaw-runtime/src/approval/mod.rs
  • crates/zeroclaw-runtime/src/cron/scheduler.rs
  • crates/zeroclaw-runtime/src/tools/send_message_to_peer.rs
  • crates/zeroclaw-runtime/src/tools/spawn_subagent.rs

ADR-018: 运行时安全与溯源 采用运行时持有的决策边界

上下文

ZeroClaw 的多个安全敏感路径都需要对三个问题给出统一的答案:是谁或什么引发了这项工作,哪项策略允许了它,以及什么证据能证明在效果发生之前已经应用了边界。工具调用、Shell 命令、网关和 RPC 变更、定时任务、SOP 步骤、转向消息以及对等代理分发,过去都在不同的位置回答这些问题。

这种拆分会带来两种失效模式。新的动作路径可能遗漏某个步骤,例如审批、来源标记、最终目标校验或审计证据。新的扩展点也可能权限过大:如果它能够决定策略、屏蔽权威证据,并把事件响应整体交由一个可替换的提供方处理,就会变得过于强大。

三个已接受的 RFC 描述了在运行时边界解决此问题的架构:

  • #7142 接受了一条由运行时掌控的安全决策流水线,用于受保护的操作。该流水线综合了内置策略、规范化的主体授权、审批要求、沙箱约束、限制性叠加层、操作指纹、一次性运行时许可、规范化审计事件以及结果记录。
  • #6971 接受凭据面权限、安全状态报告,以及一条由运行时负责的模型准入路径。凭据形态的配置字段需要明确的处理分类,受保护的值不得进入保存和属性回读路径,运行时凭据边界图需要标明明文凭据可能流经的位置。每个面向模型的轮次和转向注入在模型看到之前都会收到可信入口信封,而传输边缘的身份验证和滥用控制则保留在该共享模型准入层之外。
  • #6954 接受由运行时持有的、用于内部发起轮次的溯源信息。Cron、daemon、SOP、子代理和对等代理的工作必须携带内部主体、会话绑定、回复溯源、明确的上下文缺失处理方式,并区分执行、投递和持久化的结果。

这些决定与#7141中的规范主体(canonical principal)决定、#7155中的命令/工具确认决定、#6996中的文件系统沙箱决定,以及#6909等特定消费者目标验证相关,但并不能取代它们。

当前代码库已包含重要的基础工作,但尚未达到完整的目标。IngressContext、TurnOrigin 和 IngressDecision 已经存在;turn 引擎会在循环入口和 steering 排空时调用入口策略;默认策略返回 Loop;AuditLogger 是可复用的哈希链脚手架;规范主体(canonical-principal)的基础工作也已开始。内部主体与分离结果(separated-outcome)这一部分仍在 #10425 中审查。本 ADR 记录目标架构,在满足下列门禁之前仍处于提议(proposed)状态。

决策

保持运行时作为强制性的安全权威

受保护的操作在执行或修改之前,都会经过一个由运行时统一掌控的安全决策流水线。该流水线基于可信的运行时上下文构造类型化请求,解析内置策略与规范主体授权,施加禁止权限提升和沙箱约束,叠加限制性覆盖层,在需要时收集可信审批,并在产生效果前立即重新校验时效性,生成规范化的审计证据,签发一次性运行时许可,并在受控的执行边界处消费该许可。

许可是决策与执行之间的交接凭证。它与规范化后的操作、主体、策略版本、运行时纪元、目标身份、审批有效期以及指纹模式绑定。它不能被序列化,不能根据参数重新构造,不能为同级操作复制,也不能被消费超过一次。

安全敏感的操作在运行时无法对其分类时会被拒绝。新的受保护边界必须登记到操作清单(action inventory)中,或登记到机械等效的结构中,且该结构需明确列出负责人(owner)、请求构造器(request constructor)、执行边界(execution boundary)、必需的策略层(mandatory policy layers)以及审计分类(audit classification)。

扩展只能收紧策略,而不能替代底线

限制性覆盖层可以拒绝某项操作、收窄其资源范围,或要求更强或更新的审批。它们不得将拒绝转为允许,不得扩大主体授权,不得削弱沙箱或风险配置限制,不得从不可信的请求数据中自行选择,不得抑制规范审计事件,也不得将基线事件响应标记为已完成。

可选的审计接收端(sink)和响应器(responder)是相互独立的扩展点。它们可以接收经过脱敏的投影数据,或添加遏制与通知行为,但不能删除、改写、延迟或替换运行时创建的规范事件(canonical event)以及基线运行时钩子(baseline runtime hooks)。

未来公开的插件、WIT、远程策略、动态库或事件响应器 API 需要各自独立的实现与信任审查。本 ADR 仅确立权限边界,并不构想一个推测性的第三方安全提供方 ABI。

保持凭证相关界面的分类与保护

凭据形态的配置字段必须有明确的处理分类,例如加密机密、仅路径引用、公开值、外部认证存储、兼容性环境路径或需要后续跟进。新的凭据形态字段在没有分类测试、审计或机械等效的棘轮(ratchet)机制之前,不得进入 schema。

受保护的凭据值必须排除在保存路径和属性回读路径之外。分类层说明的是值如何存储或暴露;它本身并不能决定每个运行时组件是否可能接收明文。

一份独立的运行时凭证边界图谱列出了明文可能流经的位置,涵盖提供方和渠道客户端、工具、MCP 服务器、委派任务、CLI 包装器、网关处理程序、日志、回执、事件和错误路径。本 ADR 将该图谱记录为必须满足的实现门槛,并允许基于它进行有针对性的加固,但不接受完整的凭证代理(credential broker),也不接受新的默认隔离配置文件。

使用统一的模型准入路径处理入站内容

每个面向模型的回合在模型执行之前都会经过共享的入口策略。每次转向注入都会获得并基于其自身的可信入口信封进行评估,而不是沿用原始回合中过时的发送者、消息、传输或信任信息。

入口策略会产生 Loop、Annotate、Gate 或 Drop。默认值 Loop 保留当前行为,且不分配托管的 SOP 工作。Annotate 在继续处理之前,将内容标记为不可信数据。Gate 将该轮对话移交给托管的人工或 SOP 决策路径。Drop 拒绝该轮对话,并记录拒绝原因。

传输层边缘控制仍然是强制性的,且彼此独立。信道配对、发送方白名单、签名校验、载荷校验、速率限制、协议特定过滤以及资源滥用控制,都会在共享的模型准入层之前运行。共享层决定规范化后的内容是否可以进入模型;它不负责对传输进行身份验证。

在可配置的非 Loop 策略可达之前,尚未实现的非 Loop 处置必须采用失败即关闭(fail closed)的方式处理。一旦配置可以选择 Gate,将 Gate 分支回落为 Loop 的做法就与本决定不兼容。

基于运行时事实标记溯源信息

来源信息由受信任的运行时入口代码标记,绝不由消息内容或工具参数标记。来源(origin)与信任(trust)是两个独立的事实。内部、定时、委派或转发的工作可能源自外部内容,不会仅因直接调用方是内部的而变得可信。

来自 #7141 的规范主体(canonical principals)在存在外部或已认证的执行者时,提供已认证的执行者身份和授权(grants)。来自 #6954 的内部主体(internal principals)用于标识由运行时拥有的发起者,例如 cron 任务、守护进程任务、SOP 步骤、对等代理(peer-agent)分发以及嵌套子轮次(nested sub-turns)。这些内部主体是来源(provenance)事实,而不是外部对等方,它们从不会像传输层用户一样出现在对等组或授权表中。

子回合需保留父级来源信息,或记录父级链路,以确保委派的工作不会丢失引发它的身份与信任信息。SOP 和守护进程发起的回合必须使用能够区分其具体任务来源的名称,以便在追踪记录和运行记录中加以辨别。

将内部工作绑定到对话,同时不转移权限

内部发起的轮次可以携带一个运行时内部会话绑定。该绑定指明历史记录从何处加载,以及已完成的轮次应追加到何处,并受常规的修剪和持久化规则约束。Cron 的 session_target = "main" 会绑定到智能体的主交互式会话;isolated 则有意不携带任何绑定。

绑定不等于投递,也不等于记忆召回。绑定决定由哪个会话持有上下文并负责追加内容;投递决定用户在何处看到通知或回复;记忆召回仍由记忆注入策略控制。

对等代理的回复使用不透明的回复溯源信息,而非共享会话。发送方的轮次在派发前会捕获关联 ID、发送方身份以及发送方会话绑定。接收方作为其自身代理执行,无法读取或解引用发送方的会话句柄。完成后,运行时沿该溯源信息追加或投递接收方的最终文本。

V1 中对等回复的来源信息(provenance)仅限于进程内。已完成的存活进程接收方轮次必须沿来源信息完成投递,或记录投递失败的结果;而尚在途中、未绑定的 degrade 分发可能会在崩溃时丢失。持久化的分发记录或持久化队列属于单独的后续工作,不在本次 V1 决策范围内。

缺失的上下文必须显式声明。isolated 表示不期望任何绑定,require 在无法推导所需回复溯源信息时拒绝分发,degrade 在没有绑定的情况下运行,并记录降级情况。接收方或消息内容不能将 require 削弱为 degrade。

保持结果与状态证据分离

执行、交付、持久化和审计持久性是彼此独立的结果。兼容性状态可以对它们进行汇总,但它必须由各个独立维度推导得出,而不能作为一个相互竞争的事实来源直接写入。

安全态势报告区分三类内容:已配置的意图、已解析或已探测的能力,以及经运行时验证的强制执行。active 和 enforced 这两个词仅保留给与实际应用该边界的运行时实例相关的证据。可选的投影、日志、观察者事件和回执可以展示有用的证据,但它们不会成为另一个安全权威。

当启用规范的持久化审计接收端时,执行前事件会在受保护的变更操作之前提交。如果该提交失败,则拒绝此变更操作,并且安全状态会报告降级或不可用状态。在操作产生效果后写入结果失败时,会记录明确的未知或降级审计状态,因为已经执行的操作不能因审计持久化而撤销。

Keep rollout sliced and reversible → 保持发布分批进行且可回滚

实现遵循 #7432 中的路由跟踪器,以及源 RFC 中链接的各个实现问题和 PR。运行时安全管道、规范审计接收器、凭证表面分类、运行时凭证边界映射、入口标记、非 Loop 策略、内部主体信封、会话绑定、对等回复溯源以及持久化分发后续工作,必须以可独立评审的切片形式落地。

没有任何单个 PR 应试图一次性将所有操作、所有传输方式、所有审计接收端以及所有内部轮次消费者都路由到完整目标中。每个切片都必须保持现有的默认行为,除非该切片明确负责某项兼容性变更。

验收关卡

此 ADR 在满足以下所有条件之前仍处于提议状态:

  • 运行时动作流水线具有类型化的请求与决策词汇表、用于受保护边界的动作清单(或等效的棘轮机制)、一次性使用且不可伪造的许可凭证(permit)、代际与运行时纪元的新鲜度检查,以及在所属执行或变更边界处的最终目标重新验证;
  • direct、nested、scheduled、delegated、SOP、gateway、RPC 及安全敏感的工具路径不得绕过已注册的流水线边界,且未知或未分类的受保护操作一律采取失败关闭(fail closed)策略。
  • 内置策略、#7141 主体授权、禁止提权、#7155 审批溯源、#6996 沙箱约束,以及 #6909 等特定使用方的重新验证,仍是不受限制性覆盖层控制的强制层。
  • 凭据形态的配置字段均有明确的处理分类,并配有模式审计、测试或同等的约束机制,用于拦截任何新增的未分类字段。
  • 受保护的凭据值在保存和属性回读路径中始终不会出现,并在适用的情况下提供未泄露的测试覆盖。
  • 运行时凭证边界图涵盖提供方与渠道客户端、工具、MCP 服务器、委派工作、CLI 封装器、网关处理程序、日志、回执、事件以及错误路径,由此产生的加固缺口将分流至专项后续任务,而非被视为已接受的凭证代理。
  • 规范化的最小化安全事件由运行时创建,包含策略决策和结果证据,但不包含机密负载;启用的持久化接收端会在执行变更之前提交执行前事件,若持久化失败则拒绝该变更。
  • 可选的审计接收器和事件响应人员可以添加投影或响应,但不能抑制、替换、延迟或改写规范证据或基线运行时钩子;
  • every 模型绑定轮次和引导注入都会收到各自的可信入口信封,其中包含传输方式、发送者或主体、可用时的消息标识、来源以及由入口代码而非消息内容标记的信任信息;
  • 可配置的 Annotate、Gate 和 Drop 行为,只有在未实现的非 Loop 处置方式改为以审计证据失败关闭并通过测试之后,才能启用。
  • 传输边缘的身份验证、配对、允许列表、签名校验、载荷验证、速率限制、自身/机器人过滤以及滥用控制,均在标准化模型准入之前强制执行;
  • internal principals 已为 cron、daemon/SOP、peer-agent 和 subturn 入口点实现,并通过测试证明它们是来源(provenance)事实,而不是 peer 成员资格授予;
  • conversation binding 通过串行化的每会话所有者加载并追加历史记录,cron 中的 session_target = "main" 会在下一次交互式轮次中可见,而 isolated 则刻意保持未绑定。
  • peer reply provenance 会投递或记录已完成的、运行中进程的接收方输出,同时不向接收方暴露发送方的会话句柄;并且 require 不能被接收方或消息内容削弱;
  • 执行、投递和持久化的结果各自独立存储或输出,任何兼容性汇总均由这些维度推导得出;
  • 安全态势、发布和常设文档应准确使用“已配置”“已解析/已探测”和“运行时已验证”等证据用语,包括更正先前仅属于第一阶段脚手架的主动执行声明;以及
  • #7432 和专门的实现跟踪项明确了剩余的切分任务、负责人、测试,以及发布或回滚说明,然后才能将本 ADR 标记为已接受。

后果

积极后果:

  • Reviewers 针对受保护的效果,只需由运行时负责回答一个问题:该操作是否获得了当前决策,并在其边界处消费了一个有效的许可(permit)?

  • Security extensions become less dangerous because they can narrow or project, but not replace the mandatory floor.

    Wait, I need to correct myself: the system instructions say to translate to zh-CN and return only the translated string. Here is the translation:

    安全扩展之所以危害性降低,是因为它们只能收窄或投射策略,而无法替换强制性的底线。

  • Inbound 内容决策、转向消息、定时任务和对等代理回复共享同一套来源溯源术语,而不是各自编造本地信任逻辑。

  • 运营人员能够区分已配置的策略、已解析的能力与运行时已验证的强制执行,而不是将所有状态输出都视为同等可靠。

  • 内部工作可以参与对话历史与回复路由,但不会将定时任务、SOP 步骤或对等智能体伪装成外部渠道的对等方。

负面后果:

  • The运行时必须在动作和回合边界之间传递更多结构化上下文。

    Wait, let me correct the spacing to be clean:

    运行时必须在动作和回合边界之间传递更多结构化上下文。

  • 当前仍有用的代码路径只是部分得到验证,需等到其实现切片补充上述的棘轮机制和测试之后,才能完全证明其正确性。

  • 默认保留的分阶段推出,比一次性大范围的安全重写要慢。

  • 非 Loop 入口行为和持久化的对等节点分发不能随意发布;在发布前,必须先提供故障、溯源和兼容性方面的证据。

  • 审计持久化在启用后会引入文件 I/O 和失败即关闭(fail-closed)行为,因此必须明确兼容性与回滚方案。

参考文献