FRELY / BLOG

当 AI 在你的电脑上运行命令时,沙箱运行时做了什么

让 AI 在你的电脑上运行 shell 命令很有用。它可以安装依赖、运行测试、读取日志、修复构建。但这也意味着,一个你并未编写的程序,在由你未曾审阅的文本驱使下,以你的用户账户运行。

默认情况下,这个账户可以读取你的 SSH 密钥、云服务凭据、包仓库令牌以及浏览器个人资料。一条命令要造成破坏,并不需要是恶意的。藏在网页或 issue 评论中的一段提示注入,就足以让一条看起来完全正常的命令读取某个机密并发送到别处。

在每条命令前问一句“你确定吗?”并不能解决这个问题。人们会批准自己无法完全读懂的东西。更好的答案是让危险的事情在默认情况下无法发生,并在真正需要时让人打开一扇窄门。沙箱正是为此而生。

srt 是什么

srt 是 Anthropic 的开源沙箱运行时(@anthropic-ai/sandbox-runtime)。它为 Claude Code 而建,既可以作为命令行工具使用,也可以作为库使用。它会将任何进程以及该进程启动的一切,都包裹在由操作系统强制执行的文件与网络限制之中。没有容器镜像,也没有虚拟机。

它自己的 README 称其为一个 beta 研究预览版,因此请把它当作一块坚固的基石,而不是一份完备的保证。

它如何限制文件

文件规则说来简单:

  • 默认允许在任何地方读取。 你用 denyRead 列出要隐藏的位置,比如你的凭据文件夹。
  • 默认拒绝在任何地方写入。 你用 allowWrite 列出命令可以写入的位置,通常是项目文件夹和一个临时目录。denyWrite 的优先级高于 allowWrite,因此你可以在一个允许写入的文件夹中划出一块受保护的文件。

读取这一侧是拒绝列表,而不是允许列表。这很务实,因为工具需要读取许多系统文件,但这也意味着沙箱只会隐藏有人想到要列出的东西。

它如何限制网络

默认情况下,完全不允许任何网络访问。命令只能通过运行在沙箱之外的代理访问网络,由这些代理决定允许哪些域名。

  • macOS:命令在一个自动生成的 Seatbelt 配置文件(sandbox-exec)下运行,该配置只允许与本地代理端口通信。
  • Linux:命令在 bubblewrap 下运行,其网络命名空间已被移除,因此唯一的出路是通过挂载进沙箱的 Unix 套接字访问的代理。

HTTP 和 HTTPS 流量经由一个 HTTP 代理。其他 TCP 流量经由一个 SOCKS5 代理。两者都会执行域名的允许与拒绝列表。Unix 套接字默认被阻止。

为什么这是一个好方法

这些限制存在于操作系统之中,而不是依赖于 AI 的良好行为,也不是一份命令名称清单。一条命令可以被改写、包装进脚本或加以混淆。它依然无法读取沙箱隐藏的文件夹,也无法写入未授权给它的文件夹。同样的规则适用于每一个子进程。

srt 不做什么

沙箱不是魔法护盾。坦率面对它的局限很重要,因为这决定了你能在什么事情上信任它。

  • 它的严密程度取决于其配置。 如果网络允许列表是开放的,那么命令能读取的任何东西都可以被发送出去。如果某个机密不在拒绝列表上,沙箱就不会隐藏它。
  • Beta 软件。 项目自己就是这样说的,而且它的选项可能会变化。
  • 平台差异。 它支持 macOS 和 Linux。在 Linux 上它需要 bubblewrap、socat 和 ripgrep。srt 对 Windows 的支持处于 alpha 阶段,而且 Frely CLI 不会在 Windows 上运行沙箱化的命令。
  • 有些选项会故意削弱它。 允许 Unix 套接字、嵌套沙箱或 Apple Events,每一个都会打开一条绕过隔离的途径。README 对这些都有警告。
  • 它限制的是单条命令的进程树。 它无法防止你亲自把密码交给 AI,也无法防止你亲自把文件从沙箱中复制出去。

Frely CLI 如何使用 srt

Frely CLI 让你能够通过 AI 控制一台电脑:AI 发出请求,CLI 在你的设备上运行命令。Frely CLI 为远程 AI 客户端运行的每一条命令都会先经过 srt。以下内容基于 CLI 的源代码,说明这在实践中是什么样的。

默认行为

  • 写入:命令可以在工作区文件夹和系统临时目录内写入。仅此而已。
  • 凭据文件夹被隐藏。 CLI 拒绝读取 SSH 密钥,AWS、Google Cloud、Kubernetes 和 GitHub CLI 的配置,GnuPG 密钥,已保存的 git 凭据,以及包仓库令牌文件(.npmrc、.pypirc、Cargo 凭据)。Frely 自己的设备凭据永远不会因任何批准而被打开。
  • 敏感位置保持写保护。 诸如 .zshrc 和 .bashrc 之类的 shell 启动文件、macOS LaunchAgents 以及凭据文件夹都受到写入保护。像“写入我的主文件夹下的内容”这样的宽泛权限并不包括它们。要打开其中一个,必须指明那个确切的路径。
  • .git/hooks 保持封锁。 钩子会在沙箱之外运行程序,因此任何批准都无法打开它们。
  • 它失败即拒绝(fail closed)。 如果沙箱无法在某台设备上启动(平台不受支持或缺少依赖项),命令将被拒绝,并附带说明原因的消息。绝不会在悄无声息中脱离沙箱运行命令。

以最窄范围请求更多

当命令需要沙箱隐藏的某些东西时,AI 不能径直取用。它会发起请求,由设备所有者在 Frely 网站上批准,使用 passkey(通行密钥)或验证器代码,而不是在聊天里点一个按钮。请求会说明原因和确切的命令。批准的范围可以窄到只有一个凭据组(例如 SSH,但不包括 AWS)、一个缓存文件夹,或一个特定目录。

如果没有合适的窄范围选项,所有者可以批准在无沙箱的情况下运行一条命令。这是最后的选择,而不是默认选项,而且 CLI 的拒绝消息会促使 AI 先请求最窄的选项。

使用 Git 而不交出大门

srt 阻止对仓库 .git/config 的写入,因为 git 配置可以让 git 日后在沙箱之外运行程序。这同时也阻止了诸如 git push -u 和 git remote add 这样的日常命令。

Frely CLI 对普通命令允许这些写入,然后进行检查。它会在命令执行前为工作区中的每个 .git/config 留一份副本,在命令退出后进行比较,并移除任何新增的、会让 git 运行程序的设置,比如 fsmonitor、凭据助手(credential helper)、自定义分页器或 shell 别名。结果会告知 AI 移除了什么。命令遗留在后台运行的进程会被终止。

沙箱内部的网络访问

由于 srt 只转发 HTTP、HTTPS 和 SOCKS 流量,像 ssh 这样的工具需要额外帮助。CLI 会将 ssh、scp 和 sftp 经由沙箱的代理转发。对于数据库客户端和其他原始 TCP 工具,内置的 frely tunnel 会在沙箱内打开一个本地端口。如果你通过本地代理(例如 Clash)访问互联网,frely sandbox proxy 可以让沙箱使用它。Frely 只读取你的代理设置;它不会更改它们。

Frely CLI 对 srt 的使用未覆盖之处

我们更希望你了解它的边界:

  • 出站网络默认开放。 CLI 不限制命令可以访问哪些域名,以便 npm、pip、git 和 curl 继续正常工作。这意味着保护你数据的是文件规则:沙箱能读取的机密同样也能被发送出去。保护来自让凭据无法被触及,而不是来自封锁网络。
  • 你的主文件夹大部分是可读的。 拒绝列表覆盖的是众所周知的凭据位置,而不是所有私密内容。你存放在别处的文件(另一个项目中的 .env 文件、笔记、文档)对于在沙箱中运行的命令来说是可读的。
  • 获批准的访问就是真实的访问。 如果你批准访问 SSH 密钥,命令就能读取这些密钥。只批准你理解的东西,并优先选择最窄的选项。
  • .git/config 防护是事后检查。 它在命令退出后撤销危险的设置。它检查的是 git 已知的会运行程序的设置,并且它自己也注明了一个局限:在两条命令之间逃过清理的进程,会在下一次检查时被发现,而不是立即被发现。
  • 它约束的是命令,而不是人。 沙箱限制的是命令能触及的范围。它无法阻止你批准某个不明智的东西,也无法代替锁屏或可靠的账户登录。
  • srt 是一个 beta 研究预览版,Frely CLI 也继承了这一状态。

简短总结

能够运行命令的 AI,其安全程度取决于围绕这些命令的墙有多坚固。srt 在操作系统层面筑起这些墙:除项目之外不得写入、隐藏凭据文件夹、让网络流量经过一个守门人。Frely CLI 默认让这些墙保持不倒,把打开它们变成一个经过深思的、范围极窄的、经人批准的步骤,并坦率地告诉你它没有覆盖什么。

All posts