git push 或 npm install -g。规则写在 rulebook 文件中,每个范围的 rule.json 列出要加载的 rulebook。自定义规则只会新增阻止,绝不放宽内置规则。
规则配置文件位置
CC Safety Net 从两个范围加载 rulebook 并合并:- 用户范围:
~/.cc-safety-net/rules/rule.json(用rule init --global创建)。用于适用于所有项目的个人默认规则。 - 项目范围:项目根目录下的
.cc-safety-net/rules/rule.json。用于可提交到版本控制的团队或项目专属规则。
.cc-safety-net/ 的目录(通常是主目录)中,项目路径就是用户配置,因此写入项目范围的 rule 子命令在那里会拒绝运行。参见在用户配置目录中运行 rule。
范围合并行为
- CC Safety Net 先加载用户范围,再合并两个范围的 rulebook。
- 两个范围列出同名 rulebook 时,以用户范围的为准,项目范围的那个不贡献任何规则。CC Safety Net 会报告警告,运行时显示
degraded。重命名其中一个即可解决。 - 每个范围的
overrides只作用于本范围的规则,因此项目配置无法关闭或改写用户规则。指向用户规则的项目覆盖,以及不匹配任何规则的覆盖键,都会被忽略并报告警告。 - 两个范围的
transparent_wrappers和command_tools会合并。
管理 rulebook 来源
rule.json 的 rules 数组中的每个条目都是一个 rulebook 来源:
请用
rule 命令管理来源,不要手动编辑 rule.json:
--global(-g)即可修改用户范围而不是项目范围。--only 和 --ref 的说明见官方 rulebook,每个子命令及其输出和错误见 rule。
rulebook 是实时文件
运行时在每次工具调用时从磁盘读取每个rulebook.json,因此保存的修改从下一条命令起生效。缺失、不可读或无效的 rulebook 不贡献任何规则,运行时报告 degraded。对于从未获取过的 GitHub 来源,请运行 npx -y cc-safety-net rule update。参见配置恢复。
透明包装器
透明包装器是运行另一条命令的命令,例如timeout 5 git push。CC Safety Net 会穿过透明包装器,看到它实际运行的命令,因此内置规则和自定义规则对 timeout 5 docker system prune 的作用与对 docker system prune 相同。
有八个包装器是内置的,无需配置:caffeinate、exec、nice、nohup、setsid、stdbuf、time 和 timeout。
如果团队通过 rtk 等其他包装器运行命令,请添加它:
- 包装器名称必须匹配
^[a-zA-Z][a-zA-Z0-9_-]*$,且在文件内唯一。 - 保留命令不能作为包装器:
git、busybox、rm、find、xargs、parallel、所有 shell 包装器、所有解释器以及 awk 解释器。 - 只添加按原样运行子命令的包装器。
rule.json 中,因此 rule.json 不可读时它们会失效。参见 rule.json 中声明的覆盖范围。
社区 shell 工具
插件可以为智能体添加自带的 shell 工具,例如dsh-ops 插件会加入 ops_bash 和 ops_run_background。CC Safety Net 不认识这些名称,因此只检查它们的路径参数,从不把它们的 command 当作 shell 命令解析。在你声明之前,ops_bash 执行 git reset --hard 不会被阻止。
声明该工具后,CC Safety Net 就会分析它的命令:
command_tools 数组:
ops_bash 执行 git reset --hard 会被 git.reset-hard 阻止。
- 名称必须与智能体发送的工具名完全一致,包括大小写。
rule tool add会拒绝内置工具名。参见rule tool add名称错误。 cwd指出由哪个参数承载工作目录。未指定时,CC Safety Net 读取workdir、cwd或working_directory,都没有则使用会话工作区。工作目录为空白时,该调用以tool-call.malformed拒绝;目录不存在时,以cwd.requested-unusable拒绝。"cwd": false适用于在另一台机器(例如手机或远程主机)上执行命令的工具。CC Safety Net 不会为它读取工作目录参数,因此上述两种拒绝都不适用,每条命令都以会话工作区为基准检查。rm -rf build这类相对路径在该工作区内判定,而不是在远程目录中。
rule.json 中,因此 rule.json 不可读时,该范围声明的工具会失效。手动编辑该文件后,请运行 npx -y cc-safety-net rule verify。
创建你的第一条自定义规则
1
创建 rule.json
.cc-safety-net/rules/rule.json,其中没有任何 rulebook 来源:rule init --example 还会在 .cc-safety-net/rules/example-rules/rulebook.json 写入一个示例 rulebook。在运行 npx -y cc-safety-net rule add example-rules 之前,它不会生效。2
编写 rulebook
创建
.cc-safety-net/rules/project-rules/rulebook.json:3
注册 rulebook
rule.json 中列有 "rules": ["project-rules"]。从下一条命令起,CC Safety Net 会以你写的原因阻止 git add -A、git add --all 和 git add .。4
验证 rulebook
rule verify 会检查两个范围的 rule.json,按运行时的方式加载每个来源,并运行版本 2 的 fixture。它从不获取远程内容。rule.json schema
rule.json 选择生效的 rulebook、应用覆盖,并声明透明包装器和社区 shell 工具。安全级别、内置保护、允许路径和拒绝路径以及审计保留期在另一个文件中配置,参见策略。
integer
必填
Schema 版本,必须为
1。array
rulebook 来源字符串列表,默认为空数组。来源名称在文件内必须唯一,文件最多列出 64 个来源。
object
以
<rulebook-name>/<rule-name> 为键的规则覆盖。值可以是 "off"(关闭该规则),也可以是一个对象(替换该规则的阻止消息)。对象形式必须包含 reason,可以带上可选的 intent;省略 intent 时,规则自身的意图保持不变。array
插件提供的 shell 工具,CC Safety Net 会像分析内置 shell 工具一样分析它的
command。每个条目可以是工具名,也可以是 { "name": "ops_bash", "cwd": "dir" } 这样的对象,其中 cwd 为参数名或 false。默认为空数组。名称必须唯一,且不能是内置工具名。参见社区 shell 工具。rule.json 编辑器支持
CC Safety Net 为 rule.json 发布了一份 JSON Schema。把编辑器指向它,即可获得补全和校验:
rule.json,rule verify 会补上 $schema。policy.json 没有发布 schema。
Rulebook schema
每个 rulebook 都放在各自的rulebook.json 文件中。
string
必填
rulebook 名称,必须与本地目录名或 GitHub 来源名称一致。
string
必填
rulebook 版本字符串。
string
rulebook 的可读描述。
string
rulebook 作者。
array
必填
此 rulebook 可以为其定义规则的命令。
array
可选的 rulebook fixture。参见 Fixture schema。
规则 schema
以下字段定义rulebook_version 1 的规则。版本 2 用 match 对象取代了 subcommand 和 block_args,参见版本 2 规则。
string
必填
在 rulebook 内唯一的名称,最多 64 个字符。必须以字母开头,后跟字母、数字、连字符或下划线。
string
必填
要匹配的基础命令,必须列在
allowed_commands 中。string
要匹配的子命令,例如
add 或 install。省略时匹配任何子命令。string
必填
规则阻止命令时 CC Safety Net 显示的消息,最多 256 个字符。
string
给智能体的意图,追加在阻止消息的页脚。取
hard_stop、use_alternative、scope_down、manual_only 或 stop_and_explain 之一,默认为 manual_only。版本 2 规则
设置"rulebook_version": 2,即可按精确的命令路径匹配,而不是子命令加一组参数。在 gcloud compute 下阻止 delete 的版本 1 规则,会在命令中任意位置查找该 token,因此也会阻止 gcloud compute instances create delete;命令路径为 ["compute", "instances", "delete"] 的版本 2 规则则不会。
版本 2 规则沿用版本 1 的 name、command、reason 和 intent,并用 match 对象取代 subcommand 和 block_args。
array
必填
必须按顺序跟在命令后面的命令词,是由非空字符串组成的非空数组。由于路径不能为空,没有规则能匹配某个命令的所有调用,例如所有
aws 调用。array
参数中必须至少字面出现其中一个 token。由非空字符串组成、无重复的非空数组。省略时,命令路径匹配后不论参数如何都会命中。
array
参数中只要字面出现其中任意一个 token,规则就不匹配。由非空字符串组成、无重复的非空数组。
subcommand 或 block_args 的规则会以 rules[0].subcommand: not supported in rulebook_version 2 和 rules[0].block_args: not supported in rulebook_version 2 校验失败。
Fixture schema
Fixture 用于记录预期行为。CC Safety Net 解析其中的命令,交给该 rulebook 的规则求值,但从不执行它们。string
必填
Shell 命令 fixture。
string
必填
blocked 或 allowed。string
预期会阻止该命令的规则。
blocked fixture 必填。rule add、rule update 和 rule verify 会对版本 2 的 fixture 求值。blocked fixture 在它指定的规则第一个命中时通过,allowed fixture 在没有任何规则命中时通过。
rule add 和 rule update 会在写入之前拒绝 fixture 失败的来源。每条失败都以该 fixture 在 tests 中的下标标明:
rule verify 会在每条前面加上 rulebook 文件名,形如 example-rules/rulebook.json: tests[0]: ...。
匹配行为
两个版本都按字面匹配 token,区分大小写,不支持正则表达式、glob 或子串匹配。
--all-files 不匹配 --all。规则按顺序求值,第一条命中的规则产生阻止。
规则同样作用于嵌套命令。为 rm 写了规则后,bash -c 'rm -r ./tmpdir'、eval 'rm -r ./tmpdir' 和被调用的函数正文都会被阻止,内置分析器同样覆盖的命令也不例外。
版本 2 的全局选项
CC Safety Net 只认识aws、gcloud 和 az 的带值全局选项。对其他命令,取值分开书写的选项(如 git -C repo push)会导致规则匹配不上。Terraform 的 -chdir=DIR 是单个 token,会被跳过。
发布通道需要单独的规则。gcloud beta compute instances delete 不匹配 ["compute", "instances", "delete"],请另写一条 ["beta", "compute", "instances", "delete"] 的规则。
版本 1 会误读紧贴选项的取值
版本 1 会误读紧贴选项的取值
CC Safety Net 把
-Cfoo 视为 -C -f -o -o,而不是 -C foo。因此阻止 -f 的规则可能误匹配紧贴在选项后的取值。规则匹配的是命令,不是文件路径
自定义规则匹配的是 shell 命令及其参数。它看不到智能体用自带的读取和编辑工具打开的文件,因此规则无法保护~/.zshrc 这样的文件。要阻止对某个文件或目录的一切访问,请把它加入 policy.json 的 secret_protection.deny_paths。拒绝路径也会阻止读取。
示例
阻止所有 git push
command_path: ["push"] 且不带 any_args 的版本 2 规则,会阻止带任何参数的 git push。版本 1 规则做不到这一点,因为 block_args 至少需要一个参数。
timeout 是透明包装器,这条规则也会阻止 timeout 5 git push。它不会命中 git -C repo push。参见版本 2 的全局选项。
关闭单条规则
要关闭某条自定义规则,在列出该 rulebook 的那个范围的rule.json 中,把它的 <rulebook-name>/<rule-name> 键加入 overrides,值设为 "off"。阻止消息中会打印这个键。
rule update 不会撤销这条覆盖。要关闭 git.push-force 这样的内置规则,请改用 policy.json,参见允许被阻止的命令。
阻止全局 npm 安装
阻止消息格式
阻止消息的完整布局见阻止消息的形式。自定义规则会在原因前加上 rulebook 名称和规则名称,便于看出是哪个 rulebook 触发了阻止:<rulebook-name>/<rule-name> 也是你在 rule.json 的 overrides 中用来关闭该规则或替换其原因的键。
迁移旧配置
CC Safety Net 不再加载旧版内联配置文件(.safety-net.json 和 ~/.cc-safety-net/config.json)。其中的规则不起作用,运行时也不会给出警告。npx -y cc-safety-net doctor 和 rule verify 会把残留的文件报告为 Legacy inline rule configs are ignored。
rule migrate 没有 --global,会同时迁移两个范围。在主目录中运行时,它会跳过项目范围。参见在用户配置目录中运行 rule migrate。
它会把内联文件转换为以下布局:
无效的自定义规则配置
CC Safety Net 会丢弃加载失败的自定义规则配置,而不是拒绝命令。其他来源和内置规则继续生效,运行时报告degraded。阻止因此减少时不会有任何提醒,所以编辑规则或升级后,请运行 npx -y cc-safety-net status。参见配置恢复。