Agent 能运行不代表边界可信:用一份可追溯数据集挑选 AI 编程沙箱
让 Claude Code、Codex 一类编程 Agent 直接在开发机上执行命令,最容易犯的错不是“没有装 Docker”,而是把几个不同的问题混成一个问题:误删文件、提示注入诱导外传、以及恶意依赖试图逃逸,分别需要不同强度的边界。容器、系统调用沙箱、微虚拟机和完整虚拟机并不处于同一安全层;“有隔离”更不能自动推出“密钥安全”或“网络安全”。
新出现的 AI Agent Sandboxes 项目提供了一个有价值的思路:它不是又一个执行 Agent 的运行时,而是一份面向 Agent 沙箱与相邻方案的 YAML 数据集。仓库把每项判断连到一手来源,并把“官方说明”“HN 讨论中的说法”“编辑推断”明确分层。对准备给团队制定沙箱基线的开发者来说,这种资料结构比一张只列产品名的横评表更实用:先定义风险,再筛选可验证的能力,最后回到厂商文档复核部署细节。
先把“安全”拆成三类问题
数据集把威胁模型划成三个层级。这个分类并非通行标准,却很适合作为选型讨论的起点:
- 意外操作(T1):Agent 在错误目录执行删除、批量格式化或覆盖配置。这里需要的是工作区隔离、只读挂载、变更预览和可回滚状态。
- 提示注入导致的外传(T2):Agent 读取了不可信网页、Issue 或仓库文本后,被诱导上传环境变量、SSH 凭据或业务文件。只把进程放进容器并不能解决此问题;还需要出站网络控制,以及避免把长期密钥直接暴露给 Agent。
- 恶意代码逃逸(T3):Agent 运行的依赖、构建脚本或测试样本本身带有攻击意图。此时应关注宿主机与来宾之间的隔离边界,完整 VM 或 microVM 的定位与普通 namespace 容器不同。
这三个问题可以同时存在,但并不要求所有日常任务都上最重的边界。比如一次受控的代码生成与单元测试,T1 的副本工作区加人工合并可能足够;若任务会抓取外部内容并访问 GitHub、包仓库或内部 API,T2 就应进入最低验收项;若要让 Agent 无人值守地运行不可信项目,则需要专门评估 T3,而不是只看“支持 Claude Code”的宣传语。
把产品介绍变成可查询的事实记录
该项目的核心文件是 ai-sandboxes.yaml。它不是把“安全性”压成单一评分,而是记录多个可比较的字段:产品角色、执行地点、隔离边界、状态模型、网络策略、凭据处理方式、支持的平台和 Agent,以及已知限制。
尤其值得借鉴的是每个非身份字段都被视为一条 claim。简写字段默认代表来自该条目默认来源的官方说法;需要解释的字段则可写成带 value、ev、src、basis 和 derived_from 的对象。ev 可以是 official、thread 或 editorial。因此,读者能区分“厂商文档明确说明了什么”与“数据集作者根据多个字段作出的合理推断”。当一个产品没有公开说明某个能力时,数据集用 unspecified 表示未知,而不是把空白悄悄当成支持。
这比把 GitHub Star、HN 点数或“推荐指数”作为主要依据可靠得多。热度描述的是注意力,不是隔离实现、默认网络策略或密钥是否进入来宾环境。
读表时最重要的三组交叉条件
1. 隔离边界与风险目标必须配对
数据集将边界从独立 OS 用户、OS 沙箱、容器/namespace、microVM 到完整 VM 分层,并把多道关键边界标为 layered。这个排列可帮助理解设计差异,但不是一条“数值越高就必然越安全”的购买公式:宿主机配置、挂载、特权模式、镜像来源和补丁状态仍然决定实际风险。
例如,数据集中 Clawk 被描述为本地、VM 边界的运行时,并记录其出站 allowlist 与 SSH agent forwarding;这些字段共同解释了它为什么同时面向意外操作、外传和逃逸风险。相对地,agentjail 被归为 policy wrapper:它在工具调用前做检查,可配合代理与凭据 broker,适合约束操作和降低外传面,但项目条目也明确指出它不是完整 VM。不要把“每次调用都检查”误读为“能够替代 hypervisor 边界”。
2. 网络策略与凭据路径要一起看
“禁止网络”会影响安装依赖、模型调用和拉取代码;“开放网络”则可能让提示注入的影响扩展到数据外传。真正值得问的问题是:默认是开放、allowlist、经代理转发,还是由运维方管理?从 Agent 发起的请求,是否经过可审计的出口?
同样,密钥的处理至少有四种不同含义:宿主环境变量直接可见(ambient)、以文件或环境变量挂入来宾(mounted)、通过 SSH agent 等机制转发(forwarded),以及仅在宿主侧对获准请求注入(host-side injection)。后一种并不意味着所有凭据都天然安全,它只说明对应的集成路径没有把秘密直接交给来宾。选型时应把“哪些域名可访问”和“哪些令牌能用于这些域名”写进同一张设计表。
3. 状态模型决定人工复核的成本
临时沙箱可在任务结束后重置,持久工作区便于长任务恢复,copy/diff/apply 则把修改保留在副本中等待人工确认。它们不是互斥的好坏,而是对工作流的选择。
YoloAI 的条目很适合作为阅读这一维度的例子:数据集把它记录为可选择多种后端的本地运行时,并描述 copy/diff/apply 的变更流程、可配置网络模式及按 provider 而异的凭据 broker。这里应得出的结论不是“它保证所有后端有同样的隔离”,恰恰相反:要进一步检查当前 profile 实际选用的是容器、Kata 或 Firecracker 一类后端,随后再判断是否满足任务的 T3 需求。
用 YAML 做团队自己的候选清单
下面的示例不执行任何 Agent,只读取公开 YAML,先找出“网络不是默认开放”且“凭据没有 ambient 标记”的条目。字段形态可能是字符串,也可能是带 value 的 claim object,因此脚本先做一次归一化。实际落地前仍应逐条打开 default_source 对应的一手资料复核。
git clone https://github.com/pjlsergeant/ai-sandboxes.git cd ai-sandboxes python3 -m pip install pyyaml
from pathlib import Path
import yaml
catalog = yaml.safe_load(Path("ai-sandboxes.yaml").read_text())
def value(field):
return field.get("value") if isinstance(field, dict) else field
for item in catalog["sandboxes"]:
kind = value(item["classification"].get("network_policy"))
creds = value(item["classification"].get("credential_mediation"))
if kind in {"allowlist", "proxy_mediated", "none", "configurable"} and creds != "ambient":
print(f"{item['name']}: network={kind}, credentials={creds}")
这个筛选不能产出“安全产品排行榜”。它只是把团队需要人工判断的候选缩小:先看 risk.stated_scope,再检查对应 claim 的 ev 与 basis,最后打开来源中的架构、默认值、限制和版本说明。若某字段是 unspecified,正确动作是补查官方文档或把它当成未满足要求,而不是脑补为安全默认值。
一个可执行的选择顺序
建议不要从工具名开始,而按以下顺序落地:
- 为任务标明 T1、T2、T3 中必须覆盖的风险,并写清哪些数据、域名和凭据允许被 Agent 使用。
- 选择执行位置与状态模型:本地临时副本、远程持久 VM,还是需要每次 diff 后再 apply。
- 用网络策略和凭据路径淘汰不合格候选;特别检查默认网络是否开放、秘密是否会被 mount 到运行环境。
- 用当前版本的一手文档核对命令、平台、默认配置与限制;数据集本身也提醒其中有官方、讨论和编辑推断三种证据等级。
- 先在非生产仓库进行最小权限试运行,记录网络请求、挂载目录和实际产生的变更,再逐步扩大授权范围。
沙箱不是给 Agent 加一个“安全”标签,而是把权限、网络、状态和审计边界显式化。AI Agent Sandboxes 这个项目最值得借鉴的并非它列出了多少工具,而是它把比较依据、证据来源与未知项一起保存下来。面对快速变化的 Agent 运行时生态,这种可追溯的选型过程,往往比一次性的推荐结论更耐用。
还要把“沙箱成功启动”与“控制已生效”分开验收。试运行结束后,检查宿主机目录是否真的没有被意外写入、预期外域名是否确实无法连接、任务日志能否定位到授权与拒绝事件;若策略允许联网,再确认代理、allowlist 和凭据注入是否同时覆盖了这条请求路径。只有把这些观察结果回写到团队的基线配置中,选型表才会从资料收集变成可持续维护的安全控制。