Skip to main content
这是技术序列的最后一页。它不增加新行为,而是说明架构分析引擎所定义行为的依据和取舍。如需了解发生什么,请先阅读这两页。如需了解原因,请阅读本页。 CC Safety Net 源于一次真实事故:一个 AI 编码智能体删除了整个主目录。每项设计选择都服务于一个目标:在智能体执行破坏性命令之前阻止命令,并且绝不制造虚假的安全感。

使用语义分析,而不是通配符模式

编码智能体支持使用通配符匹配的 deny rule,例如匹配 git reset --hard 的通配符规则。通配符模式把原始命令字符串与模式比较。空格、标志顺序或命令包装的任何变化都可能让阻止静默失效。重新排列标志(rm -r -f /)、放入 shell 包装器(sh -c "rm -rf /")或隐藏在解释器后都能绕过字符串匹配。 CC Safety Net 会解析每条命令,并把命令交给理解 gitrmRemove-Itemfindxargsparallel 实际选项语法的分析器。因此,判定基于命令的作用,而不是命令的外观 代价是复杂性:解析器必须正确处理 shell 语法,每个受支持命令都需要自己的分析器。收益是对最重要命令的抗绕过能力。管线见架构,每个分析器的具体行为见分析引擎

固定顺序,并先执行始终启用的保护

在每个集成中,每次工具调用都经过相同的有序阶段。其中两个阶段,即规范策略文件保护和 Git 元数据保护,会刻意在加载策略快照之前运行。 这种顺序就是设计重点。在配置之后评估的保护只能和配置一样可靠,而受损智能体首先会尝试修改配置。因为这两个防护在读取策略文件前拒绝,所以它们没有配置状态,preset 或 override 无法放宽它们,它们保护的文件也不能关闭它们。代价是这些拒绝不能报告安全级别或 fallback 原因,因为两者此时均未知。这是用诊断细节换取无条件保证的有意取舍。 敏感路径保护位于边界另一侧,在快照之后执行。策略可以控制它,因为哪些路径属于敏感路径确实是本地决定,并且 deny path 只有在你能添加自己的路径时才有用。 具体阶段表见架构

无法完成分析时阻止

CC Safety Net 无法完成分析时会阻止,而不是允许:
  • 防护中任何位置抛出的错误都会在每个入口点变为拒绝,并归因于抛出错误的阶段。
  • 超过工具输入边界或解析器预算会在每个安全级别下拒绝。
  • Strict 模式把 fail-closed 扩展到解析器无法完全理解的命令和无法验证的破坏性目标。
原因很直接:fail-open 的安全网比没有安全网更差,因为它会制造虚假的安全感。意外错误造成的阻止很烦人,但可以恢复。破坏性命令被放行则无法恢复。 无效配置不属于这种情况。 被拒绝的配置源会被丢弃,而不会转换为拒绝。rulebook 中的拼写错误如果让机器阻止所有工作,就会对用户造成拒绝服务,并促使用户卸载工具而不是修复文件。配置恢复定义此约定和修复方法。 这些属性在每个信任边界的执行方式见安全模型

让智能体继续任务的拒绝方式

拒绝不是错误状态。它在活动会话中作为普通工具结果返回给智能体。此行为决定 CC Safety Net 如何编写每条阻止消息。 只有 permission denied 的消息可能让智能体重试类似命令或停止整个任务。重复变体可能找到未受保护的形式,还会消耗智能体轮次。停止整个任务则把一次安全操作变成工作中断。 因此,每条消息都会给智能体一个有效的后续动作。原因用清楚的语言说明命令的作用,并在有安全替代方案时给出该方案。每条规则还有一个 intent,用于选择结尾指令:报告阻止并继续任务其余部分、改用指定替代方案、用更窄的明确目标重试、把操作交给用户,或重构命令而不是穷举变体。即使内部错误产生 fail-closed 拒绝,也有 intent:重构,不要重试。因此,工具自身发生意外失败时仍会把智能体引向有效响应。 该指令只提供建议。没有机制强制智能体遵守。执行由防护完成,它也会阻止不遵守的重试。消息的作用是让合规路径最容易执行,使会话通常可以吸收一次阻止并继续。消息结构和完整 intent 表见工作原理

最小依赖面

CC Safety Net 把运行时依赖面限制为一个延迟加载的软件包。所有结构信息,包括段拆分、引号、重定向、命令替换和动态 word 来源,都来自它自有的有界 POSIX 和 PowerShell 解析器,而不是第三方语法。这是有意的自建决策:
  • 更小的依赖树意味着更小的供应链攻击面,而解析器是攻击者最想混淆的组件。
  • 分析需要通用 tokenizer 不保留的事实,例如哪些 word 来自展开、哪个目标锚定在工作目录、使用了哪种引用形式。因此,自有解析器是让这些事实成为一等数据的唯一方法。
  • 解析器预算可以是固定常量而不是配置,因此资源耗尽成为有界、可测试的失败模式,而不是开放式失败。
  • 对于把 CC Safety Net 作为 hook 子进程运行的智能体,它会在每次 shell 工具调用时重新启动。因此启动时间很重要,依赖项更少可缩短冷启动时间。
解析器预算和各依赖项的用途见架构

Rulebook 系统

早期版本把自定义规则存为单个项目文件中的内联 JSON。CC Safety Net 因四个原因改用 rulebook 系统:
  • 共享:可以从 GitHub 仓库获取 rulebook,并在 lockfile 中用 SHA-256 digest 固定,使团队无需复制 JSON 即可共享阻止策略。
  • 完整性:使用前会根据 lockfile digest 验证远程 rulebook 内容。内联配置没有完整性机制。
  • 作用域:rulebook 支持独立的用户(全局)和项目作用域,并使用不同配置目录。
  • 验证:rulebook 内容必须通过 schema 验证,才能影响阻止判定。
自定义规则只能增加限制。它们不能放宽内置保护。这样可保持简单的信任边界。编写流程见自定义规则

使用分级级别,而不是一个设置

保护以 standard、strict 和 paranoid 三个 preset 提供,而不是单个开关,因为“是否应阻止无法验证的命令”的正确答案取决于命令来源。 Standard 针对有人监督的会话优化:它阻止可识别的破坏性命令和敏感内容访问,同时容许无法解析但无害的文本,因此不会中断日常工作。它对对抗性或动态输入明确只提供尽力保护。当命令可能来自提示注入或其他不可信上下文时,不应使用此设置。 Strict 和 paranoid 用摩擦换取确定性。Strict 阻止无法验证的内容;paranoid 还阻止通常没有问题但偶尔会造成灾难的类别。设计不会通过增加更多 standard 模式解析启发式来填补 standard 的缺口。静态无法解析的目标不能通过更多猜测变得安全。对新缺口的规定响应是增加 strict 或 paranoid fail-closed fixture。因此,standard 模式的残余风险类别会被记录,而不会隐藏。 各能力仍可单独设置,任何 per-rule override 都可以在 standard 下强制启用 strict tier 规则。但任何 override 都不能削弱灾难性规则或始终启用的保护。级别见模式,准确边界见分析引擎

纵深防御,而不是替代方案

CC Safety Net 不声称自己是完整的安全方案。它是纵深防御堆栈中的一层:
  • 权限 deny rule提供快速且用户可配置的阻止。CC Safety Net 在权限系统之前运行,因此无论 deny rule 如何配置,它都会检查每条命令。
  • 操作系统级沙箱限制文件系统和网络访问,但不理解边界的操作是否具有破坏性。沙箱目录中的 git reset --hard 从沙箱角度看在技术上安全,但仍会造成严重误操作。
请组合使用这些层:用 deny rule 快速迭代,用沙箱处理未知威胁和隔离,用 CC Safety Net 针对已知破坏性模式提供抗绕过保护。见CC Safety Net 与沙箱的对比

Worktree 放宽

Linked Git worktree 会产生可用性问题:在 worktree 中工作的开发者通常需要运行 git checkout -- .git reset --hard 来丢弃该 worktree 中的本地更改,但默认规则会把它们作为 local-discard 操作阻止。 Worktree 模式不会全面放宽规则。它只对 local discard 放宽,只在被正向验证为 linked worktree 的目录中放宽,并且只在没有重定向 Git 上下文时放宽。验证是此设计的关键:看起来像 worktree 的目录不符合条件,如果检查无法完成,命令仍被阻止。 放宽范围有意保持狭窄。所有影响远程的操作(force push、删除分支、丢弃 stash)仍被阻止,可能影响可丢弃 worktree 外部内容的 local discard 也仍被阻止。具体条件和不可放宽的情况见分析引擎,启用方法见模式

后续阅读

技术指南从面向用户的生命周期逐步深入设计依据。本页是最后的第 5 步。
  • 上一页:分析引擎说明这些取舍产生的具体分类行为,架构说明这些取舍支持的防护顺序。
  • 从头开始:工作原理以用户层次说明同一系统。
相关页面:安全模型说明这些决定保护的信任边界,已知限制说明它们不能解决的问题,配置恢复说明上文引用的 readydegraded 约定。
最后修改于 2026年8月12日