破坏性命令规则
zn-gate 可用来拒绝会清空机器或未经查看就运行下载内容的 shell 命令的六条规则:每条拦截什么、如何开启或关闭,以及这项检查看不到什么。
zn-gate 可以拒绝一小类会清空机器、或未经查看就运行下载内容的 shell 命令。其中两条规则在智能体钩子中默认开启:rm_root_home(递归删除主目录、文件系统根目录或系统文件夹)和 disk_overwrite(写入磁盘设备)。另外四条规则(pipe_to_shell、rc_download、perm_root、fork_bomb)默认关闭,你可以开启它们。你也可以关闭这两条默认规则。
它是防止模型出错或收到不当建议的护栏,不是沙箱。它读取单条命令的文本,只有命令具有下面某种形态时才会拦截。
命令被拦截后不会运行,智能体会被告知原因,并被要求在运行前先请你确认。如果你确实想运行它,请自己在终端中运行。不熟悉的词请查看术语表。
修改设置
对于智能体钩子(zn hooks install 为你的智能体设置的那些),在 ~/.zn/config.json 中设置 hooks.blockDestructiveCommands:
| 设置 | 生效的规则 |
|---|---|
| 未设置 | rm_root_home 和 disk_overwrite(默认) |
true |
全部六条规则 |
false |
无:检查关闭 |
规则名列表,例如 ["rm_root_home", "pipe_to_shell"] |
恰好这些规则(不是规则的名称会被忽略) |
{"hooks": {"blockDestructiveCommands": false}}
环境变量 ZN_BLOCK_DESTRUCTIVE=1 会开启全部六条规则。环境只能增加保护,不能取消保护:ZN_BLOCK_DESTRUCTIVE=0、任何其他值或不设置都会被忽略,仍由配置文件(或默认值)决定。智能体所在的项目可以设置环境变量,因此关闭规则只能通过配置文件进行,而智能体的文件工具无法写入该文件。
检查生效时,钩子会对你的智能体的 shell 工具(例如 Bash 和 PowerShell)运行它。
在你自己的代码中,可以直接调用该函数。调用它就是选择启用:它始终应用全部六条规则。
- Node.js:来自
zn-gate/lib/client的checkCommand(command) - Python:来自
zn_gate的check_command(command)
两者返回与 evaluate 同类的结果,规则形如 destructive:rm_root_home。参见 SDK 页面。上面的设置只适用于智能体钩子。
它拦截什么
| 规则 | 默认 | 拦截内容 | 示例 |
|---|---|---|---|
rm_root_home |
开启 | 递归删除主目录、文件系统根目录、顶层系统文件夹或驱动器根目录。也包括对这些路径使用 -delete 或 -exec rm 且没有 -name 之类条件的 find。 |
rm -rf ~、rm -rf /、rm -rf /usr、Remove-Item -Recurse -Force $env:USERPROFILE、rd /s /q C:\ |
pipe_to_shell |
关闭 | 未经查看就把下载内容当作脚本运行。 | curl https://example.com/install.sh | sh、sh -c "$(curl ...)"、bash <(curl ...)、iwr ... | iex |
disk_overwrite |
开启 | dd 以块设备为 of=,对块设备使用 mkfs、mkswap、wipefs、shred 或 blkdiscard,重定向写入块设备,以及 PowerShell 的 Format-Volume 和 Clear-Disk。 |
dd if=/dev/zero of=/dev/sda、mkfs.ext4 /dev/nvme0n1p2 |
perm_root |
关闭 | 对文件系统根目录或顶层系统文件夹使用 chmod -R、chown -R 或 chgrp -R;对主目录使用带全局可写权限的 chmod -R。 |
chmod -R 777 /、chmod -R 777 ~ |
fork_bomb |
关闭 | 经典的 shell fork 炸弹,无论函数叫什么名字。 | 一个在后台调用自身两次的函数 |
rc_download |
关闭 | 把下载内容写入 shell 启动文件(.bashrc、.zshrc、.profile、/etc/profile、fish 的 config.fish)。 |
curl -o ~/.bashrc https://example.com/rc |
“顶层系统文件夹”指 /bin、/boot、/dev、/etc、/home、/lib、/lib32、/lib64、/opt、/proc、/root、/sbin、/srv、/sys、/usr、/var,在 macOS 上还包括 /Users、/System、/Library、/Applications、/private、/Volumes。更深的路径,例如 /var/lib/apt/lists 或 /usr/local/lib/node_modules/x,不会被拦截。
命令的拆分方式与 zn-gate 钩子的其他检查相同,因此引号、&&、;、管道、sudo、env、nohup 以及类似的包装命令都能被理解。sh -c、bash -lc、eval、pwsh -Command 和 cmd /c 中的代码也会被检查,最多三层。引号中仅仅提到某条命令的文本(echo "rm -rf ~"、提交信息)不会被拦截。
它做不到什么
这项检查只读取命令文本。以下情况不在覆盖范围内,检查会放行:
- 命令在运行时才拼出的路径:
DIR为空的rm -rf "$DIR"、在未知文件夹中运行的rm -rf *,或来自管道的目标。 - 先保存、之后再运行的脚本(
curl -o x.sh ... && sh x.sh),或把下载内容交给不是 shell 的程序(curl ... | python3)。 - 其他工具和语言(
rsync --delete、git clean、删除文件夹的 Python 单行命令),以及顶层以下的路径(rm -rf /usr/local)。 - 在容器内或另一台机器上运行的命令。
- 智能体先写入文件、再运行该文件所做的任何事。
对于这些情况,请使用沙箱、容器或你的智能体自带的权限提示。这项检查只是为最常见的灾难性错误多加一道廉价的最后屏障。
效果如何
测试集包含约 1,000 条普通的开发命令(构建、git、包管理器、容器、删除 node_modules 或 dist、curl -o、编辑 .bashrc,以及许多与被拦截形态很接近的命令),以及约 550 条具有被拦截形态的命令,它们由模板生成,参数、目标和虚构主机各不相同。在这个测试集上没有误报,也没有漏报。测试集和规则出自同一批人之手,所以请把它当作回归测试,而不是所有真实命令上的错误率。
如果它拦截了你想运行的命令
请自己在终端中运行该命令。这项检查只适用于智能体。如果某条规则经常妨碍你,可以用上面的设置关闭这条规则(或整个检查)。