我应该使用哪个安全级别?
有人监督的会话使用默认的standard 级别,它对对抗性或动态输入只做尽力而为的防护。如果命令可能来自提示注入或其他不可信的上下文,请使用 strict。如果还想阻止项目内的 rm -rf 以及所有 python -c、node -e 单行命令,请使用 paranoid。
每个级别都是三项能力的预设组合:
使用
policy.json 中的 safety.level 或 CC_SAFETY_NET_LEVEL 环境变量设置级别,两者取较高者。本页介绍的各项开关会在该级别之上各开启一项能力,不匹配任何预设的组合会报告为 custom。
在 linked Git worktree 中,开启 worktree 模式即可允许 git reset --hard 等本地丢弃操作。如需隔离不可信代码或控制网络,请再加一层沙箱。
全部变量以及策略与环境之间的优先级见环境,safety.overrides 见策略。受影响的命令列在各安全级别增加的阻止中。
默认模式
默认模式即standard 安全级别。无需设置环境变量,即可阻止内置的破坏性 Git 和文件系统模式以及对机密文件的访问。
包括 standard 在内,每个级别都会阻止格式错误的 hook 输入、分析器错误,以及过大或嵌套过深而无法分析的命令。参见 Fail-closed 执行。
Standard 与 strict 的区别在于如何处理无法解析或验证的输入:
- 命令无法拆分成 token 时(例如存在未闭合的引号),CC Safety Net 改为扫描文本中的已知危险模式。
echo 'unterminated可以执行,git reset --hard 'unterminated会被阻止。参见 standard 无法验证命令时。 - 目标为动态值的递归删除(如
rm -rf "$target"),只要命令不在主目录中运行就允许;strict 在任何目录下都会阻止。
eval 或 source(如 eval "$(ssh-agent -s)")。
Standard 允许只检查机密文件是否存在而不读取它,例如 test -f .env 或 ls ~/.ssh;strict 和 paranoid 会阻止这类检查。全部此类形式见 standard 模式不算作读取的情形。读取机密文件内容、配置的拒绝路径和灾难性规则在任何级别都不会放宽。
standard 无法验证命令时
在 standard 级别,有两类拒绝表示“无法验证”而不是“危险”:- 命中破坏性模式的无法解析文本。
- CC Safety Net 无法确定其来源的 shell 命令,如
bash -c "$CMD"。
Strict 模式(CC_SAFETY_NET_STRICT=1)
Strict 开启 fail_closed 能力,少见语法偶尔会被误判。它会阻止:
- 无法解析的命令,即使文本扫描没有发现危险内容。原因为“Command could not be safely analyzed (strict mode)”。
echo 'unterminated在 standard 中允许,在此级别被阻止。 - 少数受支持形式以外的 heredoc。
git commit -F - <<'EOF'和普通的cat <<'EOF'可以通过,但 strict 会拒绝python3 - <<'PY'。参见 Heredoc。 - 无法验证的破坏性目标,例如
rm -rf "$target"。 - 向远程主机的上传。 发送请求体或文件的
curl、wget请求会被阻止,除非其中每个 URL 都是环回地址。见网络命令。 - 对机密文件的存在性检查,例如
test -f ~/.ssh/id_rsa或find ~/.ssh -type f。 - 解释器代码中被 standard 视为数据的机密路径,例如
python -c "x = '.env'"。
fail_closed 开启时生效:
通过级别开启 strict,或使用设置同一能力的旧开关:
可以在 policy.json 中用
destructive_command_protection.overrides 关闭上表中的任意一条规则,也可以用 "on" 在 standard 下开启其中一条。无法解析的命令、不受支持的 heredoc 和机密文件检查没有可关闭的规则,因此只要 strict 开启,它们就一直被阻止。Paranoid 模式(CC_SAFETY_NET_PARANOID=1)
paranoid 级别等于 strict 再加 paranoid_rm 和 paranoid_interpreters 两项能力。它们可能干扰正常工作流,因此需要主动开启。可以选择整个级别,也可以单独开启其中一项能力。只开启其中一项时,CC Safety Net 会报告级别为 custom。
rm 检查(CC_SAFETY_NET_PARANOID_RM=1)
默认情况下,CC Safety Net 允许在当前工作目录内执行 rm -rf 和 find -delete。Paranoid rm 检查在这里也会阻止非临时路径的递归删除:
临时目标和
destructive_command_protection.allow_paths 中列出的目录仍然允许。
解释器单行命令(CC_SAFETY_NET_PARANOID_INTERPRETERS=1)
在 paranoid 以下的级别,CC Safety Net 只阻止正文含有危险命令的单行命令,规则为 interpreter.dangerous-command。开启此检查后,interpreter.one-liner-paranoid 会阻止所有解释器单行命令,不论内容如何:
python -c '...'(也包括python3和python2)node -e '...'ruby -e '...'perl -e '...'
python -c "print(1)" 在 standard 和 strict 中允许,在这里被阻止。
开启 paranoid 检查
CC_SAFETY_NET_PARANOID=1 不会开启 fail_closed。如需完整预设,请使用 CC_SAFETY_NET_LEVEL=paranoid 或 safety.level: "paranoid"。
Worktree 模式(CC_SAFETY_NET_WORKTREE=1)
Linked Git worktree 是隔离的工作区,因此 worktree 模式会在其中放宽部分本地丢弃规则。只有在 CC Safety Net 确认当前工作目录位于 linked worktree 内时,它才会生效。
开启 worktree 模式
workflow.worktree_mode: true。任一设置都会开启 worktree 模式。
在 linked worktree 中允许的命令
在已确认的 linked worktree 中,worktree 模式允许以下命令:git restore <file>和git restore --worktree <file>git checkout -- <file>、git checkout <path>、git checkout <ref> -- <file>、git checkout --force,以及有歧义的多位置参数 checkout 形式git reset --hard和git reset --mergegit clean -f(以及-fd等组合短选项)git switch --discard-changes和git switch -f / --force
在 linked worktree 中仍阻止的命令
以下命令会影响共享 ref 或其他 worktree,因此 worktree 模式从不放宽它们:git push --force:影响远程仓库git branch -D:强制删除在各 worktree 之间共享的分支git stash drop/git stash clear:改动在各 worktree 之间共享的 stashgit worktree remove --force:可能删除另一个 worktree
/tmp 等临时目录下的 worktree 目录,git worktree remove --force 仍可能放行。参见临时仓库中的 Git 命令。
worktree 模式不生效的情况
如果 CC Safety Net 无法确认工作目录是 linked worktree,默认规则照常生效。主 worktree 和 submodule 从不放宽。其他使 worktree 模式不生效的情况
其他使 worktree 模式不生效的情况
- 命令传入了
--git-dir或--work-tree,或环境中设置了GIT_DIR、GIT_WORK_TREE、GIT_COMMON_DIR或GIT_INDEX_FILE。 - 命令通过
git -c或GIT_CONFIG_*设置了core.worktree,或者该 worktree 的config.worktree、共享的仓库配置中设置了worktree键。 - 该 worktree 的 Git 目录中有符号链接或 FIFO。
- CC Safety Net 无法解析
git -C <path>的目标。 - 参数是动态的,含有
$、*、?或[。 - 命令使用了
--recurse-submodules或递归 submodule 配置。 - 命令强制重置分支(带
-f或--discard-changes的git checkout -B或git switch -C),或执行带多个-f的git clean。