standard 的行在启用 strict 或 paranoid 后会被移除。
本页是允许命令的参考。被阻止的形式见被阻止的命令,有序防护流程见架构,分类器行为见分析引擎。
Git 命令
文件系统命令
rm -rf 按目标分类,第一个匹配项生效。根目录或主目录目标(/、~、$HOME)、受保护的 Git 元数据、当前工作目录本身(rm -rf .),以及当前工作目录就是主目录的情况,在所有级别都被阻止。当前工作目录外的其他字面路径也会被阻止,除非它们是已识别的临时目标或配置的允许路径。临时路径和当前工作目录内的路径是允许的。请注意区别:rm -rf ./subdir 是允许的,但 rm -rf .(当前工作目录本身)被阻止。
在此基础上还有两项与级别相关的调整:
- 动态目标(
rm -rf "$target"、反引号、替换)在standard中允许,一旦启用 fail-closed 能力就会被阻止。standard对对抗性或动态生成的命令文本只提供尽力保护。 - 启用
CC_SAFETY_NET_PARANOID_RM=1后,即使在当前工作目录内,非临时的递归强制删除也会被阻止,因此rm -rf ./cache不再通过。临时目标和配置的允许路径仍然可以通过。
配置的允许路径
destructive_command_protection.allow_paths 下列出的绝对目录或以 ~/ 开头的目录会被当作受信任的临时根目录。它们在每个安全级别都生效,适用于 rm、PowerShell Remove-Item 和 find -delete。
允许路径不会放宽其他任何东西。它既不放宽敏感路径保护,也不放宽拒绝路径。它无法覆盖根目录、主目录或受保护的 Git 元数据。即使某个仓库位于允许路径内,rm -rf 该仓库的 .git 仍会被阻止。由于动态目标先于允许路径分类,允许路径永远不会作用于无法验证的目标。等于或包含 $HOME 的条目在校验时和规范化后都会被拒绝,而经符号链接逃逸出允许路径的情况也不在覆盖范围内。
Heredoc 数据消费者
标准输入上不展开的 heredoc,如果其消费者只是存储或发布正文,那么正文属于数据而不是程序,因此永远不会被当作命令文本扫描。消费者必须是字面量cat、tee、git apply、git commit、gh pr create 或 gh issue create;heredoc 必须是该命令唯一的输入重定向;cat/tee 也不能把内容送入输出进程替换(>(...))。此项允许在每个级别都成立,strict 和 paranoid 也不例外。
heredoc 必须是不展开的:分隔符带引号(
<<'EOF'),或者分隔符不带引号且正文中不含 $、反引号或反斜杠,这样 shell 就没有需要展开或转义处理的内容。不带引号且含有这三个字符之一的正文会经过 shell 展开或转义处理,因此在 standard 中仍会被扫描,启用 fail-closed 后则直接被拒绝。heredoc 之外的命令仍会分析。cat <<'EOF' && rm -rf ~ 会因 rm 被阻止。对于 cat、tee、git commit、gh pr create 和 gh issue create,分隔符带引号的正文在提取敏感路径前还会被遮蔽,因此正文里提到机密文件名不会阻止提交。不带引号的正文即使通过关卡也不会被遮蔽,其中形似文件名的 token 仍会被提取。git apply 的正文仍对路径提取可见,因为 patch 会列出它写入的文件。完整关卡以及 standard 如何处理未通过关卡的 heredoc,见 Heredoc 分析。
仅标准允许
这些形式在standard 中允许,启用 strict 或 paranoid 后则会被拒绝。这不是疏漏。standard 对对抗性或动态输入只能尽力保护。
带引号赋值的延后判定范围很窄。赋值本身不执行任何操作,带引号的展开始终是一个 argv word,无法拆成命令加标志。只要分析器无法证明某处引用属于这类数据用法,赋值时的阻止就会保留:未加引号的展开(
env $W)、位于命令位置的任何展开(即使带引号)、命令替换内的引用,以及未加引号的 heredoc 正文中的引用。把值交给 shell 则由下游拦截:eval "$W"、bash -c "$W" 和 echo "$W" | sh 都会被拒绝,因为无法验证 shell 的执行来源。
对生成命令的这项放行只看命令的形态,不看命令出自谁手,也没有一份可信生成命令的清单。只有 CMD 同时满足以下条件时,eval "$(CMD)" 和 source <(CMD) / . <(CMD) 才会放行:
- 只有一条简单命令,没有重定向,也没有嵌套命令;
- 所有词都是字面量,开头没有环境赋值;
- 头部 basename 既不是远程抓取命令(
curl、wget、fetch、aria2c、http、https、xh、xhs、nc、ncat、netcat),也不是 shell 或sudo、env这类标准命令包装器。
CMD 本身,因此 eval "$(rm -rf /)" 会被阻止。不检查的是 CMD 打印出来的那段 shell:standard 由此把信任扩展到了每一条字面本地命令的输出,包括 eval "$(cat somefile)" 这样的形态。仍被阻止的形态见生成命令的 eval 与 source。
资源耗尽限制不属于此项权衡。超出解析器递归或结构校验上限的命令在每个级别都会被拒绝,
standard 也不例外。设备命令
dd、mkfs 和 shred 在每个级别都会被分析,但只有真正具有破坏性的形式才会被阻止。
PowerShell 命令
把 shell 模式设为
posix 会完全禁用 PowerShell 删除规则,但仍保留 git.reset-hard、rm.recursive-force-root-or-home 等跨 shell 规则。在 auto 模式下,分析器会识别显式的 Remove-Item,包括出现在 ;、换行、&& 或 || 之后的命令。Get-Content、Set-Content、Add-Content、Copy-Item、Move-Item 同样会被识别,gc、cp 之类别名在参数写成 PowerShell 路径表达式时也会被识别。
敏感路径允许
敏感路径保护是覆盖受支持形式的一组有界模式,因此某些提到敏感文件名的形式仍然允许。
其中两项允许的边界很明确,值得了解:
- env 模板。
.env.example、.env.sample、.env.template和.env.defaults这几个精确基名,以及任何以.env.example.或.env.sample.开头的名称,例如.env.example.local,会在其他敏感路径规则运行前豁免。因此,即使位于受保护的主目录内也可读可写。这种前缀形式不适用于另外两个模板:.env.template.local和其他所有.env.*名称一样,会被secret.pattern.env-variant阻止。 - 供应商目录。 当任意路径段是
node_modules或__pycache__,或者出现相邻的vendor/bundle或vendor/cache组合(单独一个vendor段不算)时,恰好有两组规则被抑制:扩展名规则(.pem、.p12、.key等)和宽泛的无扩展名密钥基名规则secret.pattern.ssh-key-basename(*_rsa、*_dsa、*_ed25519、*_ecdsa)。其余规则在那里照常生效。node_modules/x/.env和node_modules/x/id_rsa仍会被阻止。.git不在跳过集合内,因此.git树内的密钥材料(例如.git/hooks/deploy_key_rsa)和在其他任何位置一样匹配规则。
Worktree 模式例外
使用CC_SAFETY_NET_WORKTREE=1 时,CC Safety Net 会在验证 linked Git worktree 后允许选定的本地丢弃命令。如果验证失败,命令仍然被阻止。
worktree 模式启用后,以下命令在 linked worktree 内是允许的:
git restore <file>和git restore --worktree <file>git checkout -- <file>、git checkout <ref> -- <file>、git checkout --force,以及有歧义的多位置参数 checkout 形式git switch --discard-changes和git switch -f/--forcegit reset --hard和git reset --mergegit clean -f(以及-fd这类组合标志)git rm --force/-f
git push --force会影响远程。git branch -D会影响共享引用。git stash drop/git stash clear会影响多个 worktree 共享的 stash。git worktree remove --force可能删除另一个 worktree。
rm .git、rm -rf <resolved gitDir>、rm -rf <commonDir> 以及重定向 > .git 仍会硬停止,因为标记文件解析出的 Git 目录同样受保护。