本节摘要:第 5.3 节说破了护栏的诚实边界——语义闸门在对抗性文本面前不可靠;权限门再精细,也总有"判错的时刻"。沙箱的立论起点正在于此:不追求判得更准,而是保证判错之后损失是局部的——这个"局部"的大小叫爆炸半径。本节建立三级隔离谱系:进程级(子进程 + 资源限制 + 系统调用过滤思路,开销近乎零、攻击面最大)、容器(namespace + cgroups,gVisor 用用户态内核拦截系统调用居于容器与 VM 之间)、微 VM(Firecracker 类独立内核,攻击面最小、运维最重);给出"攻击面 / 开销 / 运维复杂度"三轴取舍表与选型流程——默认进程级,平台与 CI 升容器,不可信任务上微 VM;并回收 2.1 节 Codex CLI 的启示:隔离档位与审批策略是两个正交的旋钮。
阅读完本节,你应当能够:
先回收两条前置结论:第 4.1 节说"任意执行是风险分水岭——提供 bash 类工具的那一刻,你就需要沙箱";第 5.3 节承认"多层防线不可省"。把这两条放在一起,沙箱的定位就清楚了:
权限门是概率性的(可能被绕过、被骗过),沙箱是物理性的(进程就是够不到那块资源)。前者的错误率可以调低,后者的错误率是结构性的零——代价是开销与运维。
工程上衡量"困得住"的程度用爆炸半径(blast radius):一次失手能波及的范围。三级谱系就是三种把爆炸半径逐级压小的砌墙法。
| 级 | 机制 | 代表 | 隔离了什么 | 没隔离掉什么 |
|---|---|---|---|---|
| 进程级 | 子进程边界 + 资源限制 +(Linux 思路)seccomp 系统调用过滤 | 各 harness 自带的受限执行器 | 文件访问靠路径判界、CPU/时间靠配额 | 与宿主共享内核:内核漏洞即逃逸面 |
| 容器 | namespace(挂载/PID/网络)+ cgroups | Docker;gVisor(用户态内核拦截系统调用) | 文件系统视图、进程空间、网络栈 | 仍共享内核(gVisor 显著收窄接口,算容器与 VM 之间的档位) |
| 微 VM | 独立 guest 内核,每个任务一台极轻量虚拟机 | Firecracker 类(官方自报:百毫秒级启动、MiB 级每 VM 内存开销) | 除虚拟化接口外的一切 | 虚拟化层自身的漏洞(面积极小但非零) |
三点补充:
| 维度 | 进程级 | 容器 | 微 VM |
|---|---|---|---|
| 攻击面 | 最大(共享内核,全量系统调用) | 中(共享内核,接口收窄) | 最小(独立内核,仅虚拟化接口) |
| 每次执行开销 | 近乎为零(毫秒级启动,示意) | 低(镜像缓存后秒级内,示意) | 中(启动百毫秒级 + 每台常驻内存,官方自报 MiB 级起) |
| 冷启动 / 预热 | 无 | 需要镜像构建与分发 | 需要根文件系统镜像与 VM 池预热 |
| 运维复杂度 | 最低(标准库即可) | 中(镜像、存储、网络编排) | 高(VM 生命周期、监控、池化管理) |
| 适用 | 本地 CLI、可信度较高的日常开发 | CI 流水线、内部平台多任务 | 不可信代码执行、对外开放平台 |
读表的方法是先定攻击者模型再定档:任务是"自己仓库里跑测试"(攻击者≈自己手滑)还是"陌生人提交的代码"(攻击者有意逃逸)——前者进程级绰绰有余,后者容器都嫌薄。
选型从低往高配,每升一档都要能回答"上一档接不住的失手是什么":
默认进程级(路径判界 + 超时 + 输出截断) └─ 任务来自 CI / 多人平台,失手涉及别人资产?→ 容器(gVisor 看敏感度) └─ 代码不可信 / 对外开放,失手即事故?→ 微 VM
配置形态上,把档位做成显式的 profile(与 5.1 节权限配置平级、互不嵌套):
# sandbox-profiles.yaml —— 隔离档位配置示意(写法示意,以实际工程为准) profiles: local-dev: # 本地日常开发:进程级 isolation: process fs: {root: read-only, writable: ["workspace/**"], masked: [".git", ".env*"]} net: deny # 默认禁网(6.2 节) limits: {timeout_s: 120, max_output_chars: 4000} ci: # CI / 平台任务:容器 isolation: container runtime: docker # 敏感场景换 gvisor fs: {root: read-only, writable: ["workspace/**", "/tmp"]} net: {allow_domains: ["pypi.org", "registry.npmjs.org"]} limits: {timeout_s: 600, mem_mb: 2048} untrusted: # 不可信代码:微 VM isolation: microvm # Firecracker 类 fs: {root: ephemeral, mount: {"workspace": "read-write"}} net: deny limits: {timeout_s: 300, vcpu: 2, mem_mb: 1024}
⚠️ 档位是执行环境的属性,不是权限的替代:read-only 档里权限门照样要判(谁能发起执行)、审批照样要问(要不要跑这条命令)。隔离强度与打断频率是两个正交的旋钮——2.1 节 Codex CLI 的"沙箱三档 × 审批策略"组合正是这个原则的产品化(官方)。
档位定了墙的高度,下一节砌墙本身——文件系统与网络这两面最常调的墙,具体怎么落地。
延伸阅读:同站教程库《grok-build》。