安全说明
Preworld Review 会运行你们交给它的代码,还会故意去攻击它,所以隔离是整个设计的核心。这一页说明哪些措施在保护你们和你们的数据,每一项都标了状态:已就位 是现在已经在用的;计划中 是已排进计划、还不能用的。供应商安全评审常问的问题,见安全问卷答案。
云端运行的隔离
适用于连 GitHub 仓库和自带镜像。
- 每次运行一台全新的虚拟机 已就位。每次运行、每次预跑都有自己的一台虚拟机,从我们的机器镜像(Ubuntu 24.04 LTS)启动,运行结束即删除。虚拟机开在伦敦的 Google Compute Engine 上;项目的运行云选了 Azure 时,开在 Microsoft Azure 上,现在是瑞典中部(Sweden Central),英国南部(UK South,伦敦)对我们开放后搬过去。虚拟机从不复用,不在运行之间、客户之间共用。
- 单次运行最长时间 已就位。平台执行组织设的上限(默认 120 分钟)。离上限还剩 5 分钟时,运行在当时那次执行结束后停下,并出部分报告。到了上限还在跑的运行会被停下,虚拟机也被删除。作为兜底,Google Cloud 上的每台虚拟机建的时候都带有「最长运行时间」,等于上限加 10 分钟,到点由 Google 直接删除。Azure 没有这个设置。那里的每台虚拟机都带一个自动关机计划,到上限加 15 分钟时由 Azure 直接关机并释放,平台随后再删除。这个计划只认每天的某个时刻,所以组织的上限不超过 1420 分钟(23 小时 40 分)时项目才能在 Azure 上跑。
- 单独的网络 已就位。沙盒虚拟机在自己的 VPC 网络里(生产环境里还在单独的 Google Cloud 项目里),没有外网 IP。入站全部拒绝;出站只放行 TCP 443 和 80 端口,经 Cloud NAT 的一个固定地址出去。Azure 上同样的规则,在单独的虚拟网络和资源组里,经 NAT 网关的另一个固定地址出去。80 端口是给构建镜像时的软件源用的;你们的 Agent 本身只能走 443(见下一条)。
- 没有云身份 已就位。沙盒虚拟机不挂服务账号,元数据服务发不出任何 Google Cloud 凭证;在 Azure 上不挂托管身份,虚拟机扩展也关掉了。启动脚本来自机器镜像,不从元数据读取。
- Agent 以单独的无特权用户运行 已就位。测试机和 Agent 是两个不同的 Linux 用户。
agent用户不在 Docker 组里(Docker socket 等同于 root),没有 sudo,读不到测试机的文件和主目录。按用户设置的防火墙规则让它访问不了元数据服务(在 Azure 上还有平台的主机地址,域名解析除外)、控制面和容器网络。它能访问的是 localhost 上的 services,以及外网的 443 端口。 - 每次执行一个受限的作用域 已就位。每次执行都在单独的 systemd 作用域里启动 Agent,内存上限是规格档内存减去 1 GB,进程数上限 512,并有自己的工作目录。这次执行结束时整个作用域被杀掉,包括 Agent 起在后台的进程。
- 一次性令牌 已就位。虚拟机开机时带一个 10 分钟有效、只能用一次的引导令牌;测试机用它换一个只对这一个任务有效的会话令牌,任务结束时会话令牌被吊销。
- 不自动重跑 已就位。虚拟机在运行中途没了,运行记为「没跑完」而不是重跑,因为 Agent 可能已经改过测试后端里的数据。
自动隔离检查
每一版新的机器镜像,我们都在它启动的虚拟机上跑 27 项自动检查,x86 和 ARM 两种架构都跑。现在这一版镜像在 2026 年 9 月 29 日 27 项全部通过。Azure 的镜像(只有 x86)多 4 项,共 31 项:Agent 和它的容器连不上 Azure 的主机代理地址(WireServer,80 和 32526 端口),root 拿不到托管身份的令牌。结果:31/31(2026-10-01)。
| 方面 | 检查什么 |
|---|---|
| 网络 | Agent 读不到元数据服务;到不了控制面;HTTP 重定向到元数据服务同样被拦;明文 HTTP(80 端口)被拦。Agent 能访问外网 443 端口、能解析域名;测试机能到控制面。 |
| 本机权限 | Agent 用不了 Docker、用不了 sudo、读不到测试机的主目录、列不出测试机的工作目录。 |
| services | Agent 能访问发布在 localhost 上的 service,但直接到不了容器网络。 |
| 每次执行的作用域 | 测试机以 agent 用户、带着本任务的环境变量启动 Agent;Agent 和它用 nohup 起的后台子进程都在作用域里;杀掉作用域后不留任何 Agent 进程;超过内存上限的这次执行被杀掉;进程数上限拦住 fork 炸弹。 |
其他接法
- 本地测试机:Agent 在你们自己的机器上以普通进程运行,只拿到
review.yaml交给它的环境变量。那里没有容器隔离,所以请用专用的测试机。测试机只向外连接;平台能选跑哪些已确认的测试,但不能下发命令。 - 网页直连对话 AI:平台执行器只发 HTTP 请求,从不运行你们的代码。地址解析出的每个 IP 都会检查并固定,云厂商元数据地址、内网和本机地址一律拒绝。AI 要求的工具调用只记录,从不执行。
GitHub App 的权限
App 只装在你们选的仓库上,申请这些权限(GitHub 的 App 权限是一整套一起申请的,装的时候不能单独去掉其中一项):
- Repository contents:只读:把要测的提交克隆进沙盒。
- Metadata:只读:在向导里列出仓库和分支。
- Pull requests:读写:在 PR 上自动运行;打开了「GitHub 检查」的项目,在 PR 上留一条带发布门槛表格的评论。App 申请写之前装的安装还是只读,要所有者接受权限更新;在那之前没有评论,只有检查。
- Checks:写:只在打开了「GitHub 检查」的项目上用,每次自动测试在提交上挂一条检查(结论和报告链接)。App 加上这项权限之前装的安装,要由组织的所有者在 GitHub 上接受权限更新;在那之前测试照常跑,只是不挂检查。
App 对代码只读,从不推代码、建 PR;只写那条检查和 PR 上的那一条评论。安装令牌一小时有效,只覆盖所选的仓库。
加密
- 传输中 已就位。网页和 API 只走 HTTPS(TLS 1.2 或 1.3,Let's Encrypt 证书,启用 HTTP 严格传输安全)。测试机和沙盒都经 HTTPS 向外连接平台。
- 你们保存的密钥 已就位。项目密钥和对话 AI 的密钥一到就被密封:用一把新生成的密钥做 AES-256-GCM 加密,这把密钥再用平台的公钥以 RSA-OAEP(SHA-256)包起来。API 只有公钥,能存下你们填的内容,却永远读不回。你们也只看得到末四位。只有平台执行器持有私钥。沙盒凭会话令牌从执行器取回本项目的值,它上传的日志里密钥的值会被替换掉。
- 静态存储 已就位。Google Cloud 默认加密所有存储的数据:数据库、对象存储、备份和磁盘。Microsoft Azure 对在它上面跑的沙盒虚拟机的磁盘也一样。不提供客户自管密钥。
- 平台自己的凭证 已就位。平台的凭证(数据库密码、签名密钥、模型 API 密钥)放在 Google Secret Manager,只在伦敦区复制;开机时读进内存盘上只有服务本身能读的文件。
数据驻留
我们存储的一切都在 Google Cloud 伦敦区(europe-west2):数据库、运行包和证据、测试文件、备份、密钥、日志。数据库备份也在同一区域。沙盒虚拟机也在那里,除非项目的运行云选了 Azure。这样的项目用 Microsoft Azure 瑞典中部(Sweden Central,欧盟)的虚拟机,英国南部(UK South,伦敦)对我们开放后搬过去。虚拟机上的代码、测试数据和运行输出只在运行期间存在,运行包存在伦敦。例外是两家云自己对我们云资源变更的记录。Google Cloud 为我们的云项目记的管理活动和系统事件审计日志(谁改了哪项云资源),存在 Google Cloud 全局的日志存储里;Microsoft Azure 为我们的 Azure 订阅记的活动日志,由 Azure 自己保存。
数据只在用到的服务位于别处时才离开英国:
- 平台的模型:Microsoft Azure 的全球标准部署(GPT-6.1 Sol、GPT-6 Luna)和 Google Vertex AI 的全球端点(Gemini 3.8 Flash)。评审、助手和平台 AI 用的是它们,平台模型对话 AI 也是它们。它们会收到要判定或回答的文字,可能在各自的任意区域处理;语义相似类判断标准的嵌入留在伦敦。
- 美国的 OpenAI 或 Anthropic,只在设置里写着它们的模型时用到。
- 运行云选了 Azure 的项目,在 UK South 开放之前在瑞典中部运行。
- 同意了分析类 cookie 的访问者,会把点击、滚动和页面布局发给 Microsoft Clarity。平台里的文字一律遮住,报告、日志、测试和项目页面从不记录(Cookie)。
- 开始收费后,付款经 Stripe。
见子处理者。
你们的 Agent 自己调用模型时,用你们的密钥发到它要发的地方。连仓库或自带镜像的项目,项目密钥里没有 OPENAI_API_KEY 时,Agent 的模型调用改由项目的模型应答(同上,Microsoft Azure 或 Google Cloud),它会收到 Agent 发出的内容(Agent 的模型)。
各种接法的数据边界
连仓库意味着源码会进我们的云。向导会明说这一点,并在保存绑定前请你们确认。
| 接法 | 进我们云的东西 | 运行结束后留下什么 |
|---|---|---|
| 连 GitHub 仓库 | 指定提交的源码(克隆进沙盒)、.reviewctl/ 测试文件、项目密钥(密封)、依赖缓存 | 运行包(证据、脱敏轨迹、日志)和依赖缓存(只有依赖,30 天)。源码随虚拟机删除。 |
| 仓库带 devcontainer 或 Dockerfile 已就位 | 同上,另加构建出的镜像存档 | 同上,另加镜像存档(按提交,可在设置里删) |
| 自带镜像 已就位 | 镜像(拉进沙盒)、测试文件、项目密钥(密封) | 运行包。镜像随虚拟机删除。 |
| 网页直连对话 AI | 对话内容(测试题和回复)、对话 AI 的密钥(密封) | 运行包 |
| 本地测试机 | 只有运行包和测试文件。源码、数据和凭证都在你们的机器上。 | 运行包 |
| SDK 已就位 | 你们的代码传上来的:每一行的输入、期望、输出和分数,以及你们记录的调用的跨度。Agent 在你们的进程里跑;你们的模型密钥从不到我们这里。 | 实验和它的分数;追踪保留到保留期结束 |
| OpenTelemetry 已就位 | 你们的导出器发来的跨度,带属性、输入和输出 | 追踪,保留到保留期结束 |
| AI Gateway 已就位 | 你们的应用经过它发出的每一次模型调用:请求和回复。放在 x-provider-key 里的服务商密钥只用于这一次调用,从不保存、不记日志 | 每次调用一条追踪,保留到保留期结束 |
只跑和评估 已就位。Preworld Review 从不在你们的代码上运行编码 AI(比如 Claude Code 或 Codex),也从不往你们的仓库推改动。沙盒只为测试构建并运行你们的 Agent,机器镜像里没有装编码 AI。你们自己接入的编码 AI(「开发机 AI」)在你们的机器上、用你们自己的密钥运行。平台把提示词交给它,收下它写的测试草稿;它不能确认测试,也不能开始测试。
任何接法都不是给生产数据用的:我们的条款要求只接测试环境和测试凭证。
保留与删除
| 数据 | 保留多久 | 状态 |
|---|---|---|
| 克隆进沙盒的源码 | 运行结束随虚拟机删除 | 已就位 |
| 依赖缓存 | 30 天 | 已就位 |
| 证据文件和沙盒日志 | 默认 90 天;组织的所有者可以设为 1 到 3,650 天 | 已就位:设置,以及每晚删除过期的证据文件和日志 |
| 报告和结论 | 账号在就一直保留 | 已就位 |
| 删除的项目 | 立即隐藏,可以恢复;30 天后永久删除 | 已就位:隐藏、恢复,以及 30 天后永久删除 |
| 书面请求删除 | 收到你们组织的书面请求后立即删除 | 已就位:运维人员执行管理命令删除项目或整个组织,并记进审计日志 |
| 数据库备份 | 7 天的时间点恢复、14 份每日备份、每日导出保留 90 天 | 已就位 |
| 控制面日志 | 30 天 | 已就位 |
删除的数据在备份到期前(最长 90 天)可能还留在备份里;备份只用于恢复服务,不作他用。
审计记录
- 敏感改动只能由人来做 已就位。确认测试、设通过标准、开始测试、配对测试机、保存密钥、绑定仓库、改组织策略,只能由登录的人在浏览器里完成。命令行令牌做不了,网页里的助手也只能生成卡片,由人点按钮。
- 助手的工具调用 已就位。网页助手的每一次工具调用都有记录。
- 组织审计日志 已就位。记录每一个受管的操作(谁、做了什么、什么时候、从哪个 IP),组织的所有者可以在网页上查看(组织 → 审计日志)。
访问控制
- 租户隔离 已就位。每个查询都按组织过滤;别的组织的资源一律回答「找不到」。
- 最小权限的服务账号 已就位。控制面虚拟机的服务账号只能写日志和指标、读容器镜像、读自己的密钥、读写自己三个桶里的对象,以及只在沙盒项目里建删虚拟机。在 Azure 上,控制面用联合凭据登录,不存任何密钥。它登录用的身份只能在沙盒资源组里建、读、删沙盒虚拟机(连同它们的磁盘、网卡和关机计划),以及读取机器镜像。它建不了公网 IP,用不了远程命令和扩展,也碰不了身份和角色分配。沙盒虚拟机根本不挂服务账号或托管身份。
- 管理访问 已就位。登录控制面只能经 Google 的 Identity-Aware Proxy(22 端口对外网关闭),用 OS Login,没有要管理的 SSH 密钥。数据库只有私有 IP。
- 令牌和会话 已就位。会话、API 令牌和测试机令牌在库里只存 SHA-256 哈希。会话 cookie 设了 HttpOnly、SameSite=Lax 和 Secure。测试机的令牌只能用于它自己项目的测试机协议,随时可以撤销。CLI 令牌 90 天不用、或登录满一年即失效;
reviewctl logout会撤销它,每个人也能在「组织 → 我的 CLI 令牌」里撤销自己的。移除成员时,对方的测试机、令牌和登录会话一并撤销。用 GitHub 或 Google 登录走授权码流程,带 PKCE;state 只用一次,10 分钟内有效,绑定在这个浏览器上。Google 的 ID 令牌要核对签名、签发方、受众、有效期和 nonce。只有服务商验证过的邮箱才能对上账号。服务商给的访问令牌只用一次,不保存。 - 单点登录(SAML / OIDC) 暂不提供。
监控与连续性
- 存活监控 已就位。外部持续检查健康接口,失败时发邮件告警;预算到阈值也会告警。
- 备份和恢复演练 已就位。数据库每日自动备份,带 7 天的时间点恢复;另有一份每日导出放在单独的桶里;对象存储开了版本控制。每季度演练一次恢复;最近一次时间点恢复演练在 2026 年 9 月 28 日通过。
- 更多告警 计划中:错误率、响应时间、数据库存储、沙盒起不来、残留的虚拟机、排队太久。
- 公开的状态页 计划中。见服务状态。
独立验证
- 外部渗透测试 计划中:在第一份企业合同之前做。
- 认证:Preworld Review 没有 SOC 2 或 ISO 27001 认证。底层基础设施是 Google Cloud 的,Azure 上的沙盒则是 Microsoft Azure 的;两家都持有这些认证。
漏洞披露
如果你认为发现了安全问题,请发邮件到 huanting.w@nice2.io,写明发现了什么、怎么复现。请只在你自己的组织里测试,不要访问其他客户的数据,不要影响别人使用服务,并在公开前给我们合理的修复时间。遵守这些规则的善意研究,我们不会追究。