当前位置:首页>Linux>Linux 系统中的 AI 代理沙箱

Linux 系统中的 AI 代理沙箱

  • 2026-09-04 17:18:51
Linux 系统中的 AI 代理沙箱

Senko Rašić

和许多开发者一样,我发现自己越来越多地使用人工智能代理来辅助软件开发。

我目前使用命令行界面 Claude Code 以及 Opus 4.5(截至撰写本文时 Anthropic 的顶级型号)。我用它来将粗略的任务需求提炼成详细的开发计划,然后执行该计划。

默认情况下,Claude Code 每次都会询问是否可以读取和写入文件以及运行软件。这种默认配置虽然合理,但时间长了确实会让人觉得烦躁。更糟糕的是,它频繁地打断我,以至于我一边照看它一边无法同时做其他事情。

还有一种--dangerously-skip-permissions(又称“YOLO”)模式,它会在未经询问的情况下运行任何程序。这可能很危险(尽管我知道有些人就是这么运行的,而且他们的开发机器至今还没出问题)。

沙盒

标准解决方案是将代理程序置于沙箱中——要么在远程机器上(exe.dev、sprites.dev、daytona.io),要么通过 Docker 或其他虚拟化机制在本地运行。

Linux 上的一个轻量级替代方案是bubblewrap,它利用 Linux 内核特性(如 cgroups 和用户命名空间)来限制(囚禁)进程。

事实证明,Bubblewrap 是构建轻量级 AI 代理沙箱的好方案。以下是我个人对这种方案的需求:

  • 模仿我常用的Linux开发机配置(我不想管理多个开发环境)
  • 除当前项目所需信息外,几乎无法获取其他信息。
  • 仅对当前项目拥有写入权限
  • 可以直接操作项目的文件/文件夹,因此我可以轻松地从我的 IDE 中查看或修改相同的文件,或者自己运行代码。
  • 网络访问——既用于连接到人工智能提供商和搜索互联网,也用于启动一个我可以连接的服务器。

Bubblewrap 和 Docker 并非强化的安全隔离机制,但我并不在意。我并不太担心以下风险:

  • 利用零日 Linux 内核漏洞逃脱
  • 隐蔽侧信道通信
  • 从当前项目中窃取数据(包括项目特定的访问密钥)
  • 搞砸了代码库(代码通过gitGitHub 或其他地方进行管理和备份)。

最后一点比较棘手,即使是完全远程的沙箱也无法防范这种情况。理论上,我们可以使用透明的 API 代理,在 AI 代理毫不知情的情况下注入正确的访问密钥,但目前实现起来非常复杂。

另一种方法是通过创建项目特定的 API 密钥来控制潜在的损害,这样即使这些密钥泄露,至少影响范围也会降到最低。

实际应用

这是我的 BubbleWrap 沙盒脚本的样子:

#!/usr/bin/bashexec 3<$HOME/.claude.jsonexec /usr/bin/bwrap \    --tmpfs /tmp \    --dev /dev \    --proc /proc \    --hostname bubblewrap --unshare-uts \    --ro-bind /bin /bin \    --ro-bind /lib /lib \    --ro-bind /lib32 /lib32 \    --ro-bind /lib64 /lib64 \    --ro-bind /usr/bin /usr/bin \    --ro-bind /usr/lib /usr/lib \    --ro-bind /usr/local/bin /usr/local/bin \    --ro-bind /usr/local/lib /usr/local/lib \    --ro-bind /opt/node/node-v22.11.0-linux-x64/ /opt/node/node-v22.11.0-linux-x64/ \    --ro-bind /etc/alternatives /etc/alternatives \    --ro-bind /etc/resolv.conf /etc/resolv.conf \    --ro-bind /etc/profile.d /etc/profile.d \    --ro-bind /etc/bash_completion.d /etc/bash_completion.d \    --ro-bind /etc/ssl/certs /etc/ssl/certs \    --ro-bind /etc/ld.so.cache /etc/ld.so.cache \    --ro-bind /etc/ld.so.conf /etc/ld.so.conf \    --ro-bind /etc/ld.so.conf.d /etc/ld.so.conf.d \    --ro-bind /etc/localtime /etc/localtime \    --ro-bind /usr/share/terminfo /usr/share/terminfo \    --ro-bind /usr/share/ca-certificates /usr/share/ca-certificates \    --ro-bind /etc/nsswitch.conf /etc/nsswitch.conf \    --ro-bind /etc/hosts /etc/hosts \    --ro-bind /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf \    --ro-bind /usr/share/zoneinfo /usr/share/zoneinfo \    --ro-bind $HOME/.bashrc $HOME/.bashrc \    --ro-bind $HOME/.profile $HOME/.profile \    --ro-bind $HOME/.gitconfig $HOME/.gitconfig \    --ro-bind $HOME/.local $HOME/.local \    --bind $HOME/.claude $HOME/.claude \    --bind $HOME/.cache $HOME/.cache \    --file 3 $HOME/.claude.json \    --bind "$PWD" "$PWD" \    claude --dangerously-skip-permissions $@

如果这看起来有点特殊,那是因为它确实如此。我没有采用一些通用规则,而是反复试验,bwrap直到找到适合我系统的最小配置方案。

一些有趣的内容:

  • /tmp/proc并由……/dev自动处理bwrap
  • 我将文件和目录绑定挂载(即暴露)到与本地机器相同的路径下,因此文件位置、项目路径等没有任何区别。
  • 我不会全部公开/etc,只会公开最基本的信息。
  • 内容$HOME/.claude.json会被注入到沙箱中,因此沙箱中的任何更改都不会保存到真实环境中。
  • $HOME/.claude/目录内容已映射为读写模式,因此 Claude 可以保存和修改其中的文件(例如会话数据)。
  • /opt/node/node-v22.11.0-linux-x64/这是我的自定义nodejs安装位置
  • 我更改了主机名,以便轻松区分主机和沙箱。

我可能会根据需要对脚本进行一些调整,但这对我来说是一个相当不错的起点。

如何自定义

如果你想将此方法应用到其他 AI 代理或你的系统中,我的建议是修改脚本使其运行bash,然后手动运行你的代理,看看哪里出了问题,并进行相应的调整。

一个很有用的命令是strace,它可以跟踪文件访问系统调用,以便查看需要执行哪些操作:

strace -e trace=open,openat,stat,statx,access -o /tmp/strace.log codex

通过检查日志,您可以发现需要哪些文件,并根据需要进行绑定。

blog.senko.net

最新文章

随机文章