当语言模型驱动的代理获得执行任意命令的能力时,安全边界的设计便成为工程实践中的核心挑战。代理可能因恶意提示词而泄露敏感文件、删除关键数据或建立非授权的网络连接。传统的权限白名单机制虽能提供一层防护,但其脆弱性在于无法穷举所有合法操作,且审批流程一旦中断便会阻塞自动化工作流。Linux 内核提供的多层安全上下文为此提供了更为根本的解决方案:这些机制不依赖应用层代码的逐次判断,而是在系统调用入口处强制执行隔离策略。
文件系统隔离:从权限模型到内核路径控制
文件系统是代理与宿主环境交互的首要通道。Linux 5.13 引入的 Landlock 机制提供了一种基于能力的安全模型,允许进程在运行时声明其文件系统的访问边界。与传统的 POSIX 权限位不同,Landlock 采用白名单方式明确指定允许写入的根目录,任何未列入白名单的路径都将被内核拒绝访问。Codex CLI 的实现将工作空间目录(如 /workspace/project)声明为可写根,同时将 .git 目录标记为只读子路径,从而防止代理意外破坏版本历史。这种能力限制在 exec 系统调用之前应用,确保目标进程自启动起便处于受限视图之中。
在更底层的视角下,内核的 open 系统调用在其路径解析过程中提供了三处可被利用的拒绝点。第一层发生在 do_open,此时路径已被完全解析,内核根据文件权限位(如 chmod 设置的访问模式)决定是否授予打开权限。第二层位于 link_path_walk,内核在遍历路径组件时检查挂载点状态;若目标目录被其他文件系统覆盖(如 mount --bind),原始内容将被完全遮蔽。第三层发生在 path_init,通过 chroot 或 pivot_root 更改进程的根目录视图,可使绝对路径解析从指定目录起始,从而将宿主文件系统从代理视野中剥离。容器技术正是结合了挂载命名空间与根切换的双重机制,在内核层面构建了不可绕过的隔离边界。
网络隔离与系统调用过滤:seccomp-bpf 的工程实践
当代理无需网络访问时,seccomp-bpf 提供了细粒度的系统调用过滤能力。Codex CLI 在策略判定禁用网络时,会在当前线程安装 BPF 过滤规则,明确拒绝 connect、accept、accept4、bind、listen、getpeername、getsockname、shutdown、sendto、sendmsg、sendmmsg 等关键系统调用号。这种拦截发生在用户态与内核态的交界处,任何试图建立网络连接的进程都将收到 EPERM 错误而无法继续。值得注意的是,AF_UNIX 域套接字被特意允许,以支持本地进程间通信(IPC)和子进程管理工具链(如 cargo clippy 的内部协调机制)。
seccomp-bpf 的优势在于其规则可直接基于系统调用号编写,无需依赖特定的用户态库支持。工程实现中建议使用如下模式构建过滤规则:首先创建包含所有待拦截系统调用号的空规则向量(空向量表示无条件匹配),随后将这些规则附加至默认拒绝策略。在策略验证阶段,可通过 strace 捕获实际运行时的系统调用序列,确保白名单外的网络调用确实被阻断。
工程化部署清单:从配置到验证
构建可靠的代理沙箱需要一套系统化的配置清单。在沙箱类型选择上,建议默认启用隔离模式,仅在用户明确授权时降级至无沙箱执行;这种「选择退出」设计可确保安全性成为默认行为而非附加选项。环境变量应被完全清理后按需重建,防止敏感凭证(如 API 密钥)通过继承泄露。子进程管理方面,需通过 prctl(PR_SET_PDEATHSIG) 注册父进程死亡信号,当主进程异常终止时,沙箱子进程将自动收到终止通知,避免孤立进程在后台持续运行。
针对文件系统策略,白名单根目录应限制在代理任务的最小必要范围;若存在临时构建需求,可挂载 tmpfs 并设定大小上限。调试阶段可使用 codex debug landlock 等工具验证策略生效状态,确认未授权路径的写入尝试确实被内核拒绝。对于资源密集型代理任务,cgroups 可用于限制内存占用与 CPU 时间片,防止单个失控进程耗尽宿主资源。建议将 cgroups v2 的内存控制器配置为 memory.max 与 memory.swap.max,并为 CPU 子系统设定 cpu.max 以实现硬性配额管理。
安全上下文的组合使用将攻击面压缩至最小:Landlock 限制文件写入范围,seccomp-bpf 阻断网络出站,命名空间隐藏宿主视图,cgroups 约束资源消耗。这四层防御相互叠加,即使某一层存在配置疏漏,其他层仍能提供补救。
参考资料
- Pierce Freeman. "A deep dive on agent sandboxes." pierce.dev, 2025-09-26.
- Abhinav. "Sandboxing agents at the kernel level." Greptile Blog, 2025-09-29.