文章

零信任云沙箱架构:运行 AI 代理的机器不持有凭据与敏感信息

执行大模型生成代码的服务器部分与数据库及解密密钥进行了物理级彻底隔离。即使代理逃逸出容器,它也只能看到工作目录,绝无任何凭据可供窃取。

一个逃逸出容器的代理不应在机器中找到任何有价值的机密。这一安全属性取决于机器本身持有什么,而不仅仅取决于容器加固得有多严密。因此我们将系统一分为二:运行代理的一半完全不配置数据库连接,也不持有任何解密密钥。

A locked boundary. The database and the key stand on the control side; the sandbox holds only agents and a working tree.controlsandboxdatabasekeynever crosses/workspace
所有能够解密机密数据的组件位于一侧,另一侧只有代理和纯粹的项目代码树。

一个进程无法同时兼顾两个物理位置

负责认证的一端需要访问数据库(账户、画布、加密的代码仓库凭据),数据库运行在无公网端口的内网中。负责运行代理的一端执行模型编写的代码,必须与内网核心设施彻底隔离。

权限判断逻辑被设计为纯函数,不执行任何 I/O 操作,也不读取数据库或系统时钟,确保双端逻辑完全一致。

export function checkFrame(access: ConnectionAccess, frame: ClientMsg["type"]): AccessCheck

接口层面的最小化权限裁剪

向执行端暴露的方法经过了极度严苛的数据精简:

身份获取方法只返回姓名与邮箱,绝不传递包含 Argon2id 密码哈希的完整用户行。

凭据获取严格限定于当前画布上下文,并在 Git 推送完成后立即从内存中抹除。

最小化暴露是安全基石,而非仅仅为了编码方便。

通过单一二进制的 Role 架构实现解耦

系统采用统一的二进制文件,通过严格受检的 Role 标识进行行为控制:

export const ROLES = ["all", "control", "sandbox"] as const;

export function needsDatabase(role: Role): boolean {
  return role !== "sandbox";
}

export function servesBrowsers(role: Role): boolean {
  return role !== "sandbox";
}

sandbox 角色运行在无数据库模式下,并且直接拒绝对外提供 Web 服务,仅接受来自控制平面的中继连接。

关于沙箱隔离的机制请参阅 面向 AI 代理的云沙箱,实测数据请参阅 云沙箱实测发现

直接回答

当代理使用 GitHub 凭据时,密钥保存在哪里?

加密保存在控制端,绝不放在运行代理的机器上。执行模型代码的机器没有数据库连接,也没有解密密钥。

如果代理逃逸出容器,它能接触到什么?

只能接触到当前项目的代码目录以及允许的外联网络。接触不到账户数据表、Token 凭证,也接触不到任何解密密钥。

这种设计比单纯加固容器更安全吗?

两者相辅相成:容器加固降低逃逸几率,而无秘密架构则让逃逸失去破坏价值,从根本上消除了数据泄露的可能。