每个级别增加的阻止
部分灾难性保护不依赖所选安全级别:根目录和主目录的递归删除保护、Git 元数据保护和规范
policy.json 保护会忽略主破坏性命令开关和单条规则的 off 覆盖。Git 命令
同时带强制标志和创建/重置标志的 Git 分支变更命令(例如
git checkout -Bf、git switch -Cf --discard-changes)会被视为强制分支重置并阻止。
Git SSH 环境覆盖
Git 接受GIT_SSH_COMMAND、GIT_SSH 和 GIT_SSH_VARIANT,以在网络操作期间运行任意程序。CC Safety Net 会阻止这些覆盖与网络子命令的组合,因为它们可以执行任意命令:
文件系统命令
rm -rf 目标使用以下首个匹配分类顺序:不受支持的 Windows UNC 或设备目标、根目录或主目录、受保护的 Git 元数据、临时路径、动态目标、配置的允许路径、主目录作为工作目录、工作目录本身、工作目录内部、工作目录外部。临时路径在所有级别都允许。当前工作目录内的其他路径在 paranoid rm 未启用时允许。安全变体见被允许的命令。
把破坏性命令藏在 shell 函数中不会绕过这些规则。函数正文会在调用处按调用者的 cwd 分析;调用也可通过引号('cleanup')、time/! 前缀和 eval 解析。bash 关键字写法 function cleanup { ... } 和 function cleanup() { ... } 同样会解读为定义,因此行为与 cleanup() { ... } 相同。只定义但从未调用的函数,其正文不会运行。调用解析和作用域见 POSIX shell 函数。
未加引号的 glob 会先相对工作目录解析,然后才进入上面这套分类。cwd 位于主目录时,rm -rf * 和 rm -rf ./* 都归类为主目录目标,在所有级别都以 rm.recursive-force-root-or-home 阻止。加引号的 rm -rf '*' 不是 glob,它指的是文件名就叫 * 的那一个文件;在主目录下它同样会被阻止,规则是 rm.recursive-force-home-cwd,在其他位置则是普通的字面目标。
Git 元数据和动态目标都会在配置的允许路径之前分类,因此 destructive_command_protection.allow_paths 中的项绝不会放宽 Git 元数据保护,也绝不会应用于无法验证的目标。
设备和磁盘破坏
CC Safety Net 在每个安全级别分析dd、mkfs 和 shred。这些规则不是灾难性规则,因此主破坏性命令开关和单条规则的 off 覆盖仍然适用。
只有对设备的写入会触发
dd 规则。从设备读取到文件(dd if=/dev/sda of=./backup.img)是允许的,对文件镜像运行 mkfs.ext4 disk.img 同样允许。三条规则也适用于包装器和载体:bash -c "dd if=/dev/zero of=/dev/sda"、sudo mkfs.ext4 /dev/sda、env dd of=/dev/sda if=/dev/zero 和 eval "shred secret" 都会被阻止。
Git 元数据
CC Safety Net 会解析两个目录最近的祖先.git 条目:一个是执行目录,一个是决定项目规则配置的配置目录。这些条目、解析出的 Git 目录及其 hooks 子树都受保护。这两个目录通常是同一个;智能体在项目之外执行命令时才会不同,例如 Amp 的 shell_command.dir 或 OpenCode 的 workdir。这时两个 Git 控制面都受保护。即使你位于工作目录内,此保护也会生效。它在加载任何配置之前判定,因此不带安全级别,策略也无法将其关闭。
符号链接的
.git 和 hooks 会同时按字面路径和规范路径保护,指向缺失 Git 目录的 .git 标记仍会阻止。POSIX shell 中末尾的 * 不匹配以点开头的条目,因此仓库根目录中的 rm -rf ./* 不涵盖 .git,但 rm -rf .git/worktrees/* 和 PowerShell 通配符会涵盖。
边界:此防护覆盖执行目录和配置目录各自最近的祖先 Git 控制面,不包括这两个目录下的其他嵌套仓库,也不包括解析集合之外的 Git 内部路径。
受保护的 policy.json
修改或删除受保护的策略文件始终被阻止。受保护的文件有两个:用户策略文件,默认路径是 ~/.cc-safety-net/policy.json,设置 CC_SAFETY_NET_HOME 后为 $CC_SAFETY_NET_HOME/policy.json;以及项目策略文件 .cc-safety-net/policy.json,它分别从执行目录和配置目录解析。此检查在加载配置之前运行,因此它所保护的策略无法禁用这项检查,其拒绝也不带安全级别和配置状态。原因字符串固定为:
.cc-safety-net 目录,不再向上,因此项目根目录下的 rm -rf . 返回的仍是破坏性命令规则本来的原因,而不是这一条。涵盖以下形式:
- 直接的写入、编辑和 patch 目标。
- 精确的 shell 操作数和写入重定向。
- 受支持的环境变量、相对路径和现有符号链接别名。
- 对受保护目录的递归
rm。 - 以受保护的文件或目录为源的
mv。
[、cat、file、grep、head、jq、less、ls、more、rg、sed、stat、tail、test、wc。
智能体运行 cc-safety-net policy apply
policy apply 会重写这道防护所保护的文件,因此同一阶段会在加载配置之前拒绝它,intent 为 hard_stop。只有你本人可以应用提案,没有任何选项能解除这一点。原因字符串固定为:
cc-safety-net 或 ccsn,以及 npx、bunx、pnpx、pnpm dlx、yarn dlx、npm exec、pnpm exec、yarn exec、cc-safety-net@latest 这类带版本的写法,还有用 bun 或 node 运行 src/cli/cc-safety-net.ts 或 dist/bin/cc-safety-net.js。把运行器选项放在目标之前也无法绕开,-g 和 --global 出现在任何位置都会被跳过。policy check 和其他所有子命令仍然允许。
PowerShell Remove-Item
PowerShell 支持是一个保守子集:Remove-Item 及其别名、文件 cmdlet Get-Content、Set-Content、Add-Content、Copy-Item、Move-Item 及别名 gc、cat、type、cp、mv,以及现有的跨 shell 规则,而不是通用 PowerShell 解析器。下面的删除规则在 powershell 和 auto shell 模式中生效;posix 模式有意不应用这些规则,但仍保留 git.reset-hard 和 rm.recursive-force-root-or-home 等跨 shell 规则。敏感路径保护会解析 $HOME、$env:USERPROFILE、$env:HOME 或 ~ 前缀,加上用任一路径分隔符连接的字面量后缀,因此 Get-Content $HOME\.ssh\id_rsa 会被阻止;以其他方式拼装的路径,例如字符串拼接、子表达式或 Join-Path,不会被求值。
别名和缩写参数会被解析,因此
ri . -r -fo 同样阻止。调用运算符形式(& Remove-Item ...、& { ... }、. { ... })、带字面量字符串的 iex / Invoke-Expression 和 $(...) 子表达式都会被分析。行注释(#)和块注释(<# ... #>,包括嵌套)会被忽略,但其后的真实命令仍会阻止;格式错误或超过深度限制的块注释和子表达式则按 fail closed 处理。
-WhatIf 会解除阻止,因为 PowerShell 并不会真正删除任何内容:-WhatIf、-WhatIf:$true 和 -wi 缩写都会允许原本被阻止的 Remove-Item . -Recurse -Force;显式 -WhatIf:$false 则重新阻止。上面仅 strict 的那些行有一个例外:Remove-Item $HOME -Recurse -Force 在 standard 中也会阻止,因为它分类为根目录/主目录目标,而不是动态目标。敏感路径
敏感路径保护是独立的防护阶段,在命令分析前运行。它涵盖受支持的 command、path、search(grep/glob)和 patch 形式,也会检查未知工具,但绝不会将未知工具的任意文本视为 shell 命令。 内置敏感集合不只阻止写入,也阻止读取:cat .env、env cat .env、sudo command cat .env、strings id_rsa、xxd .env、base64 .env、dd if=.env、cat ~/.ssh/id_rsa、bash -c "cat .env" 和 node -e 'require("child_process").execSync("cat .env")' 都会被阻止。
command 形式的提取是有界且结构化的:触及结构性 shell 语法限制时按 fail closed 处理,解析无效时抛出错误。配置的拒绝路径在内置规则之前匹配,且不受 standard 模式下任何放宽的影响。
完整目录(每个规则 ID 和系列、受保护路径、两个 Coding CLI 层级、匹配顺序和豁免)见机密保护参考。可用 secret_protection.enabled: false 禁用整个功能,也可通过 secret_protection.overrides 逐条开启或关闭规则,详情见策略。
Shell 包装器和解释器单行命令
包在bash -c 或 sh -c 等 shell 解释器中的命令同样会被阻止。CC Safety Net 最多递归分析 10 层嵌套包装器;超过该深度时会拒绝,而不会放行。
默认情况下,会检测并阻止解释器单行命令中嵌入的破坏性代码。CC Safety Net 提取传给解释器
-c 或 -e 标志的代码,并扫描嵌入的破坏性操作,因此智能体无法把 os.system("rm -rf /") 包在 Python 或 Node 调用里来绕过 hook。
分析的解释器是
python、python2、python3、node、ruby 和 perl。触发阻止的是嵌入的破坏性命令,默认情况下不会只因单行命令形式而阻止。
生成命令的 eval 与 source
eval "$(CMD)"、source <(CMD) 和 . <(CMD) 会把 CMD 运行时打印的内容直接交给 shell。strict 和 paranoid 会拒绝所有这类动态 shell 执行来源。standard 只允许一种很窄的形态:仅标准允许中描述的完全字面的本地生成命令;其余一律阻止。
生成命令的主体和其他命令一样要经过分析,因此
eval "$(rm -rf /)" 会因其中的 rm 被阻止,source <(git reset --hard) 会因 reset 被阻止。
阻止所有解释器单行命令
如果想不论内容一律阻止解释器单行命令,可设置CC_SAFETY_NET_PARANOID_INTERPRETERS=1。此后每个 python -c、node -e、ruby -e 和 perl -e 单行命令都会被阻止,即使其中不含危险代码。python -c "print(1)" 在 standard 和 strict 中允许,在这里则被阻止。详情见模式。
strict 和 paranoid 中的 heredoc
启用 fail_closed 能力时,heredoc 命令仅在以下条件全部满足时才允许:
- 命令只有一个 heredoc。
- heredoc 用于标准输入。
- heredoc 不展开:分隔符带引号,或者分隔符不带引号且正文中不含
$、反引号或反斜杠。 - 命令没有其他输入重定向。
- 消费者是字面量
cat、tee、git apply、git commit、gh pr create或gh issue create。
fail_closed 在 strict 和 paranoid 中启用。
分隔符不带引号且正文含有 $、反引号或反斜杠时,会使用以下拒绝消息:
standard 模式处理 heredoc 内容的方式)见分析引擎。
无法解析的命令文本
shell 解析器无法对命令分词时(例如引号未闭合),行为取决于安全级别。
启发式扫描会查找
rm -rf、git reset --hard、git reset --merge、git clean -f、git checkout --force、git checkout --、git push --force、git push --delete、git branch -D、git tag -d、git stash drop、git stash clear、不带 --staged 的 git restore、find -delete、dd of=/dev/、mkfs /dev/ 和 shred <arg>。匹配会以规则 raw-text.dangerous-command 拒绝。文本以 echo 或 rg 开头时会跳过 find、dd、mkfs 和 shred 模式,因此把这些字符串引用进 echo 或 ripgrep 调用不会触发扫描。
扫描还会查找把下载内容经管道交给 shell 的写法,也就是远程安装的一行命令。远程抓取命令(curl、wget、fetch、aria2c、http、https、xh、xhs、nc、ncat、netcat)经管道接到 sh、bash、zsh、dash 或 ksh 时,会以 raw-text.dangerous-command 拒绝。shell 名带路径前缀(| /bin/sh),或中间夹着 sudo、env、command、builtin 包装器(| sudo sh、| env VAR=1 sh),结果都一样。在命令内部或管道前后加反斜杠续行同样藏不住。文本以 echo 或 rg 开头时也会跳过这条模式,因此用 echo 打印的安装行仍是数据。同一条管道能被解析为真正的命令时,改为按结构拒绝,理由是 “shell execution source cannot be verified safely”。文本扫描负责在 heredoc 正文等解析器不会深入之处拦下它。