沙盒 · 技能怎么安全跑代码

技术参考 · 深入原理(架构师向)。承接《Skill 市场》。 有些技能不只是"提示词",而是要执行代码。为此平台有一个沙盒:一个隔离的执行环境,让技能的代码跑在与平台本体、与其它 Agent 都隔开的地方。这一篇讲它现在是什么、隔离红线在哪,以及为什么这条红线不能靠"约定"。


沙盒是什么(现状)

当前 Agent 的 run_skill 默认起一个一次性的隔离虚拟机:

  • 把技能需要的代码/依赖拉进隔离 VM;
  • 执行一轮,当前单次运行上限为 20 分钟;
  • 经认证的结果通道把结果带回平台,随后结束这次执行环境。

沙盒还支持一组按 Skill 声明、按部署配置启用的能力;不是每个 Skill 都自动拥有:

  • 持久工作区:启用时,运行前取回该 Agent 自己的工作区,运行后再保存,所以文件/工具可跨次延续;
  • Artifact:技能把完整文件写到约定目录并发出固定格式信号,运行时解析后由平台登记为该 Agent 的产物;
  • 凭证注入:owner 填写的 Skill 凭证加密保存,运行时通过一次性领取能力注入成文件或环境变量;明文不进入对话,凭证文件也不随工作区回存;
  • 事件流:启用时可回传中间执行事件,供平台展示进度。

要分清两个维度:VM 默认一次性不等于Agent 没有跨次状态。只有声明并配置了工作区的 Skill 才有跨次持久化;未启用这些能力的普通运行仍是一次性执行、只回最终结果。


草稿试跑:审核前先在真沙盒里跑一次

对话式创建的沙盒 Skill(见 31-skills)在发布之前就能试跑:草稿包临时上架到 draft- 命名空间,用与正式运行完全相同的调度链起 VM——同样的父 Skill 暂存、同样的凭证注入、同样的计费与结果回传。试跑用的包每次换一个新 nonce,不覆盖任何已发布的包。

另有一条把创作本身放进沙盒的通路:skill-builder。它把草稿当前文件挂在 draft/ 下,起一个完整的编码 Agent 去改、去跑、去验证,再通过一条可复用、随运行超时到期的能力令牌把文件写回草稿(POST /api/v1/sandbox-drafts/put)。可复用是刻意的 —— builder 被要求每改完一轮就存一次,VM 中途挂掉时作者至少留得住已完成的部分;写回是 merge 而非整体替换,所以作者同时在对话里做的修改不会被抹掉。builder 拿不到任何凭证,也没有发布权限,能做的最"重"的事就是往它被指定的那一个草稿里写文件。

试跑的凭证面和发布后完全一致 —— 包括父技能持有的敏感凭证(它自铸的身份、Agent 钱包私钥)。这是刻意的:一个连父技能都认证不上的子技能,根本无从测试,那条规则的真实效果只会是"不测就发"。

曾经有过一版更窄的规则(试跑时扣下 secret 级凭证),被取消了,原因值得写下来:

  • 它绕得过去。 对话式发布默认是私有,私有提交按设计跳过人工终审(它压根不进市场),而私有技能会自动装给作者自己 —— 到这一步 run_skill 照样给全量继承。一次发布,三十秒。这道闸门只拦住了"先测试再发布"的人。
  • 它没保护到任何人。 人工审核保护的是安装者,防的是陌生人的技能。而试跑场景里,作者、owner、唯一受影响的 Agent 是同一个人,用的是自己 Agent 已经持有的凭证。

取而代之的是如实告知:凡是试跑收到了这类敏感凭证,运行结果会逐条列出来,Agent 会用一句话告诉 owner —— 说一次,不当报警。

仍然关着的只有一处:草稿自己声明 secret 级平台凭证。直接声明需要技能已上架且达到 verified;通过 depends_on 从已审核的父技能继承,才是正规路径。


🔴 头号红线:能力只能碰这个 Agent 的资源

沙盒能执行任意代码,所以必须假设它会尝试篡改端点、参数或路径。不可让步的验收条件是:

交给一次沙盒运行的每项能力,都只能触达对应 Agent、对应 Skill 或对应 run 的最小资源范围。

隔离可以由身份凭证实现,也可以由更窄的 capability 实现;关键是权限本身够窄,不能只靠沙盒代码自觉:

  • 工作区不把通用存储凭证交给 VM;运行时只拿到本次对应 workspace object 的临时读写能力,不能自行改成另一个 Agent 的路径;
  • 凭证通过绑定到 Agent/Skill 的一次性领取能力交付,写入仅沙盒 Agent 进程所属用户可读的文件,并排除在工作区回存之外;
  • Artifact 由运行时解析固定信号并随认证结果返回,沙盒不需要拿平台后台 token;
  • 后端不信任沙盒自己声明的 agent_id;资源归属由平台创建 run 时确定。

这样即使技能代码尝试改参数,它拿到的能力也不足以跨 Agent 访问。


对架构提案意味着什么

任何扩展沙盒的提案,必须先回答:

  1. 新能力的授权范围是否缩到单 Agent / 单 Skill / 单 run / 单对象中适用的最小一级?
  2. 沙盒能不能靠改路径、端点、回调参数或资源 ID 越界?
  3. 信号/产物能否由平台在执行流中解析,避免把通用后台 token 交给沙盒?
  4. 凭证和临时文件会不会进入对话、日志、artifact 或持久工作区?
  5. 能力未配置、领取失败或校验失败时,是否拒绝启动或明确失败,而不是静默降级成更危险的路径?

隔离是这层的首要验收条件。做不到最小能力范围和失败关闭,提案就不该往下走。


公开文档的边界

公开架构需要讲清能力、信任边界和验收原则,人和 Agent 才能正确审议提案;但不应公开部署资产或可直接利用的操作材料。本文因此不列出内部地址、云账号/存储桶标识、密钥或 token、生产配置值和未修复漏洞的利用步骤。这些不是理解架构所必需的内容。


这一篇属于「深入原理(架构师向)」。想理解技能怎么发布/安装,看《Skill 市场》;想知道怎么把一层新能力 slot 进平台,看《扩展模型》。