命令边界
沙箱改变环境,命令仍用同一个内核
进程级沙箱是围绕一个命令及其子进程设置的运行边界。比如让 agent 编译项目:它需要读编译器和依赖、写构建产物,却未必需要写整个主目录或连接外网。边界明确后,同一台电脑上的任务也更容易各自运行。
bubblewrap(命令名 bwrap)是 Linux 上用来搭这份环境的低层工具。它先创建空的挂载命名空间,也就是这组进程自己的“路径到文件”的视图,再把选定路径挂进去。你可以复用宿主的软件,无需先制作镜像;相应地,它也不会替你锁定软件版本。[1–2]
- 先看普通命令:“完全放开”指没有额外沙箱,仍受原有用户权限约束。它能使用宿主允许的文件与网络。
- 把 / 只读挂入新视图:
--ro-bind / /。系统程序还在,但通过这份挂载不能写。先猜:工作目录也在 / 下,此时还能保存构建产物吗? - 再用
--bind把工作目录覆盖为可写挂载。保存位置明确了,写入会落到宿主的原目录。 - 用
--unshare-net创建独立网络命名空间,不接宿主网卡,也不配置外网路由。先猜:只读的主目录会因此变得不可读吗? - 补上独立的进程编号空间及对应的
/proc、最小/dev,清理继承的环境变量。路径、进程和变量是不同的设置项。 - 命令退出,临时视图随沙箱进程结束回收。工作目录是绑定的宿主目录,产物仍在;这不是把写入回滚。
只读不等于不可读。图中的 --ro-bind / / 仍暴露当前用户本来能读的文件,包括主目录里的文件。如果任务还要求“只看见项目”,就要从空视图只挂入必要路径,或另外配置读取限制;不能把这张教学图当作完整产品配置。
预测与验证
先读配置,再预测每一次访问
先准备两个相邻目录:work 存产物,other 留在只读视图中。以下命令在你自己的 Bash 终端运行,不要给 bwrap 加 sudo。安装包用系统管理员权限,运行沙箱用普通用户身份。选项含义依据 Ubuntu 的 bwrap(1)。
命令中的两次 "$workdir" 分别是宿主来源与沙箱目标:同一路径、同一批文件。--chdir 只设置起始工作目录;允许写入的是前面的挂载配置。
启动成功后,哪组预测符合这份配置?假设原有文件权限允许读取,work 归你所有。
选第二组。--bind 只为 work 建立可写挂载,其他宿主目录仍在只读视图中。--unshare-net 改变网络环境,和你 cd 到哪个目录无关。
现在在新打开的沙箱 Bash 中逐行验证。预期是:第一行创建文件,第二行写入被拒绝,第三行能读到先前准备的文本;第四行不能建立到外网的 HTTP 连接。curl 需已安装,若提示找不到命令,只说明缺工具,不能作为断网证据。--clearenv 清除了继承的代理变量,这里又用 IP 地址避开域名解析;不把 DNS 失败误当成网络隔离。
退出后,在原终端用 ls ./inside.txt 查看产物。它应仍然存在,因为可写挂载指向宿主目录。--setenv HOME 只是让程序把这里当作主目录,--clearenv 只清变量;它们都不会让原主目录从只读视图中消失。
深入一点:启动失败时,先检查哪一层?
如果连新 Bash 都没打开,先区分工具是否安装、内核是否允许用户命名空间、外层容器是否限制相关系统调用,以及 Ubuntu 的 AppArmor 策略是否允许该程序使用用户命名空间。这和“沙箱内写文件被拒绝”是不同阶段。不要为了跑通实验全局关闭隔离;换到合适的虚拟机,或对照官方排查说明检查配置。
/proc 是内核提供的进程信息接口,/dev 提供基础设备接口。这里的“只放开工作目录”指普通宿主目录的写入;这些新建的内核接口不能当作普通磁盘文件来理解。此例没有另设 CPU/内存配额,也没有完整过滤系统调用或文件套接字。
同伴说:“把 --ro-bind 改成 --bind / /,再保持 HOME 指向 work,就能保留相同的写入边界。”你怎么判断?
HOME 是程序读取的环境变量,不是内核的挂载权限。
文件与网络分别配置,断网不会把文件系统变成只读。
--bind / / 会撤掉这层只读挂载限制。原有用户权限仍在,所以它不会让普通用户随意写系统文件,但会重新允许许多原本能写的个人文件。限制来自挂载方式,不来自 HOME。
内核规则
Landlock 限制动作,不必重画目录树
Landlock 让普通进程也能为自己和未来的子进程追加访问限制。例如程序保留原来的路径视图,却只允许写项目目录。已有用户权限和其他内核策略仍要同时满足:Landlock 不能凭空授予原本没有的权限。[3]
bwrap:重组“看见的目录树”
Landlock:追加“允许哪些动作”
因此,判断边界时要问两个问题:进程看到什么?它可以对这些资源做什么? bwrap 主要帮你组装视图,Landlock 在支持的动作上追加规则;工具也可以组合多种机制。它们都不会自动提供虚拟机那样的独立内核。
把四个描述归到负责的机制。按“由谁实现这个具体动作”分类。
- 将宿主 work 挂到沙箱内指定路径
- 把根目录以只读方式挂入
- 进程为自己追加文件访问规则
- 未来子进程继承这些追加限制
前两项回答“文件树如何呈现”,后两项回答“进程受到哪些额外动作限制”。路径仍然可见,并不保证对它的每种操作都允许。
深入一点:有 Landlock,就能限制所有网络访问吗?
不能这样推断。运行器要探测内核提供的接口版本,再选择支持的规则;不同版本支持的文件、网络等动作范围不同。Landlock 也不是按域名维护白名单的 HTTP 代理。看到产品写“使用 Landlock”,仍要继续查它实际启用了哪些规则,以及不支持时如何处理。
实际案例
agent 的运行环境由几层边界共同组成
把 agent 当作能干的协作者:你给它项目、工具链和完成任务所需的访问范围。本地命令沙箱回答“这一条命令能接触哪里”;云端会话回答“这一整份环境放在哪里、如何与其他任务分开”。两者可以叠加,出口代理和凭据管理又各有职责。
- 本地运行时:限制命令的文件与网络。截至 2026-11-06,Claude Code 官方说明其命令沙箱在 Linux 使用 bubblewrap,在 macOS 使用 Seatbelt(macOS 的进程访问限制机制)。规则会作用到命令及其子进程;这不等于每种文件工具、插件或外部服务都在同一边界里。[4–5]
- 云端会话:为任务准备一份环境。平台可以按任务创建临时容器或虚拟机,再回收环境;需要留下的代码和产物先提交或导出。容器共享宿主内核,虚拟机有自己的来宾内核。microVM 是设备模型经过裁剪的轻量虚拟机,例如 Firecracker;不能仅凭“云端沙箱”就判断用了哪种实现。[7]
- 网络出口:让必要的请求有路可走。完全断网适合离线构建;要拉依赖时,可以只经代理访问允许的目标。代理按目标放行,具体协议、地址和规则仍以产品配置为准。
- 凭据边界:允许使用服务,不一定交出密钥。代理可以在请求离开会话后加入匹配的认证信息。命令能完成授权范围内的访问,原始 token 却不用写进项目文件或环境变量。凭据的作用范围还可回看密钥与凭据怎么保管。
把示意落到一个具体案例:截至 2026-11-06,Claude Code 云端官方文档说明,Anthropic 托管会话运行在隔离的 VM 中,提供网络访问控制;Git 凭据与签名密钥留在沙箱外,由代理代为认证。其 network secrets(按请求目标使用的网络密钥)同样在请求离开会话后加入。这里按文档写 VM,不推断它是 microVM;自托管环境的凭据与出口由部署方负责。[6]
这些是特定产品、特定功能的配置方式,不是所有 agent 的共同默认值。尤其是你自己放进环境变量的 token,不会因为“用了沙箱”就自动搬到外部代理。并且云端的“关闭网络”仍可能保留模型服务通信,不能把它等同于上面的 bwrap 实验。
一个云端任务能读取私有仓库,但环境变量里没有 Git token。用两句话解释可能的结构,并说出还要检查哪个边界。
Git 请求可以经会话外的代理,由代理加入限定范围的凭据;命令因此无需持有原始 token。还要检查请求是否必须走代理、代理允许哪些仓库或操作,以及其他工具是否也走相同路径。
- 区分“能使用服务”和“持有原始凭据”
- 指出认证发生在会话之外
- 指出出口与授权范围需要分别检查
取舍与回顾
隔离越细,越要明确任务依赖什么
边界收紧通常能减少共享与可访问范围,但会增加准备工具、挂入缓存、放行网络的工作。目标是让环境一致、并行任务互不干扰、权限范围可解释。因此先列任务依赖,再选边界:离线转换文件可能只需进程沙箱;需要固定系统依赖时用容器;需要独立内核时再看虚拟机。
| 收紧的边界 | 得到什么 | 要补充什么 |
|---|---|---|
| 系统目录只读,项目可写 | 产物位置清楚 | 工具的缓存与临时目录安排 |
| 不接外网,或只经出口代理 | 联网范围清楚 | 预备依赖,或列出所需域名与协议 |
| 每个任务一份容器环境 | 工具链与文件环境可按任务配置 | 镜像、依赖版本与产物保存 |
| 增加虚拟机边界 | 使用独立来宾内核 | 镜像、启动与资源管理 |
agent 已能在 work 保存文件,但安装依赖失败。任务确实需要访问一个包仓库。哪种调整更符合“明确边界”?
写目录和建立网络连接属于不同边界,调整前先看失败发生在哪一层。
虚拟机提供内核边界,网络出口和认证仍需各自配置。
已能保存文件,说明项目写入路径可用;取依赖还需要网络出口,私有仓库可能另需认证。先区分缺工具、缺路由、代理未放行和缺凭据,再补任务需要的那一项,才能解释调整后的环境。
- 进程沙箱:仍用当前内核;读、写、网络和资源配额要分别看。
- bwrap 与 Landlock:前者组装环境视图,后者追加进程访问规则;都不自动固定软件版本。
- agent 环境:区分命令沙箱、会话容器或 VM、出口代理、凭据存储。
- 任务取舍:限制更细时,要明确依赖、缓存和产物怎么安排;只读仍然可读。
运行边界说清之后,还需要知道长期运行的程序由谁启动、状态在哪里看。下一页进入服务与日志:systemd、systemctl、journalctl。
来源
来源与实测范围
核对日期:2026-11-06。Ubuntu 26.04 LTS 的命令语义按对应 man 页;产品实现按下列官方文档。此页没有声称实测通过的 Ubuntu 终端输出,练习依据配置语义预测。
- Ubuntu 26.04 LTS:bwrap(1):空挂载视图、绑定挂载、网络命名空间、环境设置与命令生命周期。
- bubblewrap 官方 README:工具定位、由调用者定义配置,以及示例与局限。
- Linux 内核:Landlock:无特权进程追加限制、子进程继承和内核接口兼容性。
- Anthropic:Claude Code sandboxing:Linux bubblewrap、macOS Seatbelt 与边界外代理。
- Claude Code:Sandboxing:命令沙箱的覆盖范围、网络控制、凭据配置和 Ubuntu 排查。
- Claude Code 云端:Security and isolation:托管 VM、出口控制、Git 凭据、签名密钥与 network secrets。
- Firecracker 官方介绍:使用 KVM 构建 microVM,与容器共享内核的结构不同。