现在很多团队都在把更复杂的工作交给自动化:CI 不只是跑测试,也会生成代码、跑迁移检查、下载依赖、构建镜像;AI coding agent 则会读仓库、执行命令、改文件,再把结果交给人 review。问题是,这些任务一旦能运行代码,就不只是“工具”了。它们可能碰到凭据、访问内网服务、读取宿主机文件,或者把不该出网的数据发出去。

容器能解决一部分隔离问题,但容器的边界和 VM 不一样。很多 CI 环境为了速度和便利,会给容器较宽的网络、挂载和凭据权限。今天推荐的 buildkite/cleanroom 选择了更窄的问题:在自托管环境里,用 policy-controlled microVM 跑仓库工作负载,并把网络、镜像、凭据和工作区同步这些边界写清楚。

发布时 GitHub 页面显示项目约 49 stars2 forks,主要语言是 Go,许可是 MIT。项目创建于 2026-02-16,最近仍在活跃更新;最新 release 是 v0.11.0,发布于 2026-06-06。

项目概览

属性详情
仓库buildkite/cleanroom
定位自托管、策略控制的 microVM sandbox
Stars约 49
Forks2
主要语言Go
许可MIT
Latest releasev0.11.0

它把“跑仓库命令”拆成几个边界

Cleanroom 的核心不是再做一个通用 CI runner,而是把“这段命令到底能接触什么”拆开管理。

README 里强调了几个边界:

  • 使用硬件虚拟化的 microVM,而不是只靠容器命名空间。
  • 网络默认拒绝,通过仓库里的 cleanroom.yaml 显式放行目标。
  • 凭据留在宿主机侧,由 host-side gateway 代理 git clone、包下载和其他上游请求。
  • 沙箱基础镜像使用标准 OCI image,并鼓励在 policy 里用 digest pin 住。
  • 仓库执行支持显式的 copy-in、copy-out 和 sync,而不是默认把宿主机工作区完整暴露出去。

这套设计很适合今天的 CI 和 agent 场景。问题不只是“不要让代码逃出容器”,还包括“它能不能访问包仓库”“它看到的是哪个 commit”“它能不能把生成文件带回宿主机”“它拿不到 token 时如何 clone 私有依赖”。Cleanroom 把这些问题放在同一个 policy 面里处理。

cleanroom.yaml 是核心接口

Cleanroom 会检查仓库根目录的 cleanroom.yaml,也会检查 .buildkite/cleanroom.yaml。这个文件描述沙箱镜像、资源、网络、依赖缓存、服务准备等配置。

一个简化的网络策略大概是这样:

version: 1
sandbox:
  image:
    ref: ghcr.io/buildkite/cleanroom-base/debian@sha256:...
  resources:
    vcpus: 4
    memory: 8GiB
    disk: 16GiB
  network:
    default: deny
    allow:
      - api.github.com:443
      - registry.npmjs.org:443

这个文件的价值在于可审计。一次测试任务到底允许访问什么,不再埋在 runner 配置、Docker 参数或某段脚本里,而是跟仓库一起 review。对需要控制供应链风险的团队来说,这比“CI 机器能上网,测试里自己小心”要清楚得多。

microVM 不是为了炫技,而是为了隔离模型更明确

Cleanroom 支持 Linux 上的 Firecracker,也支持 macOS 上的 Virtualization.framework backend。README 里把它定位成 hardware VM isolation,而不是 container isolation。

这个选择有两个实际含义。

第一,guest kernel 和 host kernel 之间有 VM 边界。容器仍然共享宿主机内核,而 microVM 更接近“给这次执行一个小虚拟机”。这不等于没有风险,但边界类型不同。

第二,Cleanroom 要处理 VM 带来的性能和易用性问题。它不是说“每次都冷启动一个沉重虚拟机”,而是强调 warm path 上的快速 VM 创建、镜像 rootfs 物化、依赖缓存和服务缓存。也就是说,它想把 microVM 从少数高风险任务的专用工具,拉到日常 build/test loop 能接受的成本区间。

这点很关键。如果隔离工具慢到只能偶尔使用,团队最后还是会绕过它。Cleanroom 有意思的地方在于,它试图把安全边界和 CI 速度一起设计。

凭据留在宿主机侧

CI 沙箱里最难处理的部分之一是凭据。构建私有仓库、拉私有包、访问 artifact registry,往往都需要 token。如果直接把 token 注入 guest,隔离边界就变弱了:不受信任的代码可以读环境变量、抓进程、写日志,甚至主动把 token 发出去。

Cleanroom 的做法是 host-side gateway。README 说明,gateway 可以代理 git clone、包获取、OCI image、Go modules、RubyGems、immutable downloads 等请求,并在上游请求侧注入凭据。换句话说,guest 看到的是受控代理,不是原始 token。

这不是所有场景都能一键解决,但方向是对的。对 CI 和 agent 来说,最危险的不是“它能跑命令”,而是“它跑命令时顺手拿到了广泛凭据”。把凭据放在宿主机边界外,再配合 egress allowlist,能把损害面压小。

仓库感知执行:不只是开一个空沙箱

Cleanroom 可以先创建一个 repo-agnostic sandbox,再在里面执行命令:

cleanroom doctor
cleanroom sandbox create --image ghcr.io/buildkite/cleanroom-base/alpine:latest
cleanroom exec --in <sandbox-id> -- uname -a

但它更贴近 CI 的用法是 repo-aware run。README 的例子会用 --repo-url 指向 GitHub 仓库,在沙箱启动前解析到具体 commit,加载该 commit 上的 policy,然后执行命令:

cleanroom exec \
  --repo-url https://github.com/buildkite/agent.git \
  -- mise x -- go run . --version

这能避免一个常见歧义:沙箱到底跑的是本地脏工作区、某个 branch 头部,还是 CI 应该看到的已提交代码?Cleanroom 要求你更明确地表达。对于未提交的本地改动,可以使用 --copy-in--sync;对于生成结果,可以用 --copy-out 带回宿主机。

这种显式同步对 AI agent 也有意义。一个 agent 可以在隔离环境里跑测试、生成文件、尝试修复,然后只把需要 review 的结果同步出来,而不是默认拥有整个宿主机上下文。

还能把服务暴露回来

隔离不代表完全不能交互。Cleanroom 支持在沙箱运行期间把服务暴露到宿主机,例如原始 TCP 或本地 HTTPS 路由。README 里的例子包括把 sandbox 内的 PostgreSQL 暴露到 host 的 127.0.0.1:15432,也包括把开发服务器暴露成 cleanroom.localhost 下的 HTTPS 路由。

这对真实测试很重要。很多仓库不是只跑 go testnpm test,还需要启动数据库、Web server、浏览器测试或集成服务。Cleanroom 允许服务存在,但依然让暴露动作成为 policy 和命令的一部分。

v0.11.0 的重点:仓库感知创建和策略加固

最新 release v0.11.0 的重点是 repo-aware sandbox creation、显式 system warmup,以及 gateway/policy 的进一步加固。

Release 说明里提到,远程调用方现在可以在创建 sandbox 时传入 repository checkout,而不必自己编译并发送 policy。Cleanroom 会把 checkout 解析到具体 commit,从该 commit 加载 cleanroom.yaml.buildkite/cleanroom.yaml,编译 policy,再继续创建流程。

这让它更像一个可被其他系统调用的沙箱控制平面,而不仅是本地 CLI。CI 平台、内部开发工具或 agent orchestrator 可以把“我要跑这个仓库的这个 revision”交给 Cleanroom,由它负责按仓库 policy 建沙箱。

同一个 release 还包含一批安全加固,例如更严格地处理 policy host、DNS、Git gateway 端口、OCI cache 作用域、未知 key ID 的 JWKS 刷新、执行输出保留和 Git mirror command output 等。对这种工具来说,安全细节不是边角料,而是产品主体的一部分。

适合放在哪里

我会把 Cleanroom 放在三类场景里考虑。

第一类是自托管 CI。团队已经有自己的 runner,希望在不把工作负载交给第三方的前提下,让高风险测试、依赖安装、代码生成和构建任务跑在更强的隔离里。

第二类是 AI coding agent。agent 需要运行仓库命令,但不应该天然拥有宿主机文件、凭据和任意网络访问。Cleanroom 可以作为 agent 的执行层,让它在明确的 policy 下试错。

第三类是供应链敏感的构建和测试。比如要运行第三方生成器、插件、脚本或不完全可信的测试 fixture;你仍然需要网络访问,但希望它只访问声明过的 host。

需要注意的边界

Cleanroom 仍是一个年轻项目,采用时要看清楚边界。

  • microVM 不是“绝对安全”,仍然需要宿主机配置、backend 能力和更新维护。
  • Linux Firecracker 与 macOS darwin-vz 的能力不完全一致,README 也明确写到 macOS backend 仍有功能缺口。
  • 网络 allowlist 会增加维护成本,尤其是现代前端和多语言仓库依赖来源很多。
  • 凭据代理和缓存机制需要团队理解,否则容易在“为什么这个包拉不到”上花时间。
  • 它更适合有自托管 CI/runner 能力的团队,不是给纯浏览器用户准备的轻量工具。

这类工具不能只看 demo。真正试用时,应该先选一个依赖关系清楚的小仓库,写最小 cleanroom.yaml,跑 cleanroom doctor、policy validate、一次 repo-aware test,再逐步加入缓存、服务和网络规则。

小结

buildkite/cleanroom 值得关注,是因为它把 CI、agent 和供应链风险里的几个真实问题放到了一起:隔离强度、默认拒绝网络、凭据不进 guest、仓库 policy、显式工作区同步,以及可被其他系统调用的执行 API。

它不是一个马上替换所有 CI runner 的通用答案,也不是“用了 microVM 就安全”的简单叙事。更准确地说,它是一个把仓库任务边界写得更清楚的工具。对于正在让自动化和 agent 执行更多代码的团队,这类边界会越来越重要。