核心摘要

Cloud Coding Agent 是远程软件执行系统,模型只是其中一个组件。生产架构还必须控制:

text
task -> policy -> Run 级身份 -> 隔离 Workspace
-> 工具与网络 -> 仅分支改动 -> 验收证据
-> 人工/策略决策 -> 清理与保留

Pull Request 是待审提案,不是任务正确的证明。安全系统应为每个 Run 签发有边界的身份,把仓库和 Web 内容视为不可信输入,分离 Setup Credential 与 Agent Runtime Secret,限制网络出口,在执行前定义验收门禁,并保证取消或恢复不会重复产生外部副作用。

本文不再讨论“编程进入哪个时代”或引用厂商采用率,而是聚焦团队真正需要评审的运行时架构。

核心要点

  • Cloud 只是运行位置,不是可信属性。 远程执行会改变数据、身份、网络和保留边界。
  • 隔离单位应是单次 Run。 每个 Run 都要有确定的基础 Commit、环境镜像、策略、身份、分支、预算和清理状态。
  • Prompt Injection 会变成系统风险。 Issue、源文件、Package 文档、测试 Fixture、工具结果和网页都是不可信输入。
  • 证据必须可机器验证。 日志和摘要有助于调查;退出码、签名 Commit、Artifact Hash 和最终状态检查才支撑验收。
  • 并行 Agent 会同时放大审查负担和爆炸半径。 并发应受冲突域、预算、环境容量和 Reviewer 吞吐限制。

先定义运行时边界

Cloud Agent 平台至少包含六个平面:

平面 职责 核心控制
控制面 任务、策略、预算、生命周期 不可变 Run Spec
身份面 Git、Cloud、Package、工具凭证 短期最小权限
Workspace Checkout、文件系统、进程、缓存 Run 级隔离与清理
网络面 DNS、HTTP、Registry、内部服务 Deny/Allow 策略与审计
交付面 分支、Commit、Pull Request 受保护主分支与范围化 Push
证据面 命令、测试、Artifact、决策 完整性、保留、脱敏

厂商可以在内部合并这些平面,但企业安全评审应逐一检查。

Run 生命周期

1. 接收任务

先把请求规范化成 RunSpec:

  • 仓库与基础 Commit;
  • 任务文本与可信指令来源;
  • 允许修改的文件范围;
  • 可用工具;
  • 网络策略;
  • 密钥类型;
  • 资源与时间预算;
  • 必须通过的验收门禁;
  • 交付目标;
  • 保留级别。

如果请求权限超过策略,应在 Provision 前直接拒绝。

2. Provision

从固定镜像或经过证明的模板创建专属环境,并记录:

  • Image Digest;
  • CPU、内存、磁盘和时间上限;
  • Tenant 与 Run ID;
  • Host 隔离类型;
  • Mount Volume 与 Cache 来源;
  • 初始策略版本。

“临时 VM”不等于“不保留数据”。Transcript、Snapshot、Build Cache、Artifact 和供应商日志都可能比活动 VM 存活更久,必须逐条评审保留路径。

3. Bootstrap

Checkout 准确的基础 Commit,并在独立 Setup Policy 下安装依赖。

依赖安装会执行第三方代码,必须进入威胁模型:

  • 要求 Lockfile;
  • 固定 Registry 和 Mirror;
  • 在可用时验证 Checksum 或签名;
  • 任务不需要时阻止未评审 Lockfile 变化;
  • 依赖安装期间不注入 Runtime Secret;
  • 来源变化后失效缓存。

4. 执行

Agent Runtime 至少要具备:

  • 有边界的文件系统写权限;
  • 命令与工具策略;
  • 显式网络出口;
  • Run 级预算;
  • 结构化事件采集;
  • 取消传播。

仓库指令是有用上下文,但恶意源文件同样可以包含指令。信任顺序必须明确:平台策略和 Run Spec 高于仓库指令;仓库或外部内容永远无权授予新能力。

5. 验证

验收门禁应独立于 Agent 自己的结论运行:

  • 必需测试和 Lint;
  • 生成文件和 Lockfile 策略;
  • 密钥与依赖扫描;
  • 改动文件 Allowlist;
  • Migration 与 API 兼容性检查;
  • 确定性最终状态断言;
  • 必要时的 UI 或运行时证据。

Agent 可以在预算内尝试修复失败门禁,但不能通过解释“为什么应该通过”来把门禁改成成功。

6. 交付

只允许 Push 到分配分支,并创建或更新审查 Artifact。基础分支继续执行普通仓库规则。Agent 不应绕过:

  • Required Reviewer;
  • CI;
  • Signed Commit;
  • Deployment Approval;
  • Code Owner;
  • Environment Protection。

7. 清理

撤销 Run Credential、停止进程、释放 Lease,只保留获批证据,并安排 Workspace 和 Snapshot 删除。清理本身应可观测、可重试。

身份:一次 Run,一个有边界 Principal

不能把开发者长期凭证复制进 Workspace。

源码托管身份

优先使用 Git App 或 Credential Broker,确保:

  • 只能读取指定仓库;
  • 只能 Push 到 Run 分支;
  • 不能修改 Branch Protection;
  • 不能批准或合并自己的改动;
  • Agent Commit 可归因并签名;
  • 凭证随 Run 到期。

GitHub 官方文档说明其 Cloud Agent 在临时 Actions 环境中工作,并围绕单一任务分支执行。Anthropic 则说明 Hosted Cloud Session 使用短期 Session Credential、通过代理访问 Git,并限制 Push 到当前工作分支。这些是有用的架构参照,但不能替代对实际套餐和配置的核验。

Cloud 与内部服务身份

在可行时使用 Workload Federation:

text
Run Attestation -> OIDC Token -> Cloud Role Exchange
-> 短期、Audience-scoped Credential

授权绑定:

  • 组织与仓库;
  • Run ID;
  • 环境;
  • 允许动作;
  • 过期时间;
  • Audience;
  • 可选资源标签。

即使 Token 泄漏,也应无法离开该窄范围使用。

密钥:分离 Build、Runtime 与模型可见性

按暴露面分类:

密钥类型 示例 模型可见性 生命周期
Build-only 私有 Package Registry Broker 时不可见 Bootstrap
Runtime Tool 测试 API Token 尽量 Broker/脱敏 单次 Run
Deploy Approval 生产发布 Token 永不可见 外部门禁系统
User Data Key 解密生产记录 默认永不可见 避免签发

Redaction 只是纵深防御,不是隔离。进程可以在不打印原值的情况下转换或外泄密钥。优先使用 Proxy 代执行授权操作,不把原始 Credential 放进 VM 或模型上下文。

生产密钥绝不能出现在:

  • Prompt;
  • 仓库文件;
  • 被 Commit 的 .env;
  • 无限制 Shell History;
  • Demo Artifact;
  • Agent 摘要。

网络出口本身就是授权面

联网 Agent 可以通过看似正常的请求外泄代码。Allowlist 会降低可达范围,但每个允许目的地仍是一条数据通道。

策略模式

模式 适用场景
禁用 Hermetic Test 与预装依赖
仅 Proxy/Cache 语言依赖与已知文档
严格 Allowlist 已批准 API 与 Registry
临时审批 有日志的例外目的地
无限制 敏感仓库应避免

OpenAI 公开了带允许、拒绝和需审批目的地的托管网络策略。Cursor 明确把 Prompt Injection 导致外泄列为 Cloud Agent 风险,并提供可配置 Egress。Anthropic 也说明 Cloud Session 默认限制网络访问,可配置 Domain Allowlist。

Domain 之外的控制

  • 通过受控 Proxy 解析;
  • 防止直接 IP 和其他协议绕过;
  • 考虑 DNS Rebinding 与 Redirect;
  • 分离只读文档站和可写 API;
  • 限制请求大小和速率;
  • 记录目的地、决策、工具和 Run ID;
  • 适当扫描或分类出站 Payload;
  • 拒绝 Metadata Service 和内部控制面。

Package Registry 必须特殊处理,因为下载 Package 会执行代码。

Prompt Injection:把上下文当数据

潜在注入来源包括:

  • Issue 与 Pull Request 描述;
  • 仓库文档和注释;
  • 测试 Fixture;
  • Package README 与 Install Script;
  • 网页与搜索结果;
  • Compiler Error 与工具输出;
  • MCP 或 Plugin 返回。

控制必须是结构化的:

  1. 能力只来自策略,不能来自内容;
  2. 不可信文本要隔离并标记;
  3. 高风险工具需要独立授权判断;
  4. 注入发生后,Egress 与 Secret 仍被限制;
  5. 受保护文件和分支配置不可修改;
  6. 可疑序列产生证据并停止或升级。

Prompt Filter 不能成为唯一防线。应假设部分注入会被模型解释,并限制其实际后果。

Go 示例:Provision 前校验 Run Policy

下面的标准库示例拒绝宽泛网络、无范围写权限、缺失验证和自助合并。生产 Policy Engine 还应评估组织、仓库敏感度、任务类型和签名策略包。

go
package main

import (
	"errors"
	"fmt"
	"path/filepath"
	"strings"
	"time"
)

type RunSpec struct {
	Repository       string
	BaseCommit       string
	Branch           string
	WritableRoots    []string
	AllowedDomains   []string
	RequiredChecks   []string
	MaxDuration      time.Duration
	CanMerge         bool
	ProductionSecret bool
}

func Validate(spec RunSpec) error {
	if spec.Repository == "" || spec.BaseCommit == "" || spec.Branch == "" {
		return errors.New("repository, base commit, and branch are required")
	}
	if spec.CanMerge {
		return errors.New("agent runs cannot merge their own changes")
	}
	if spec.ProductionSecret {
		return errors.New("production secrets are not allowed")
	}
	if spec.MaxDuration <= 0 || spec.MaxDuration > 2*time.Hour {
		return errors.New("run duration is outside policy")
	}
	if len(spec.WritableRoots) == 0 || len(spec.RequiredChecks) == 0 {
		return errors.New("write scope and required checks must be explicit")
	}
	for _, root := range spec.WritableRoots {
		clean := filepath.Clean(root)
		if clean == "." || clean == "/" || strings.HasPrefix(clean, "..") {
			return fmt.Errorf("unsafe writable root %q", root)
		}
	}
	for _, domain := range spec.AllowedDomains {
		if domain == "*" || strings.HasPrefix(domain, "*.") {
			return fmt.Errorf("wildcard domain %q is not allowed", domain)
		}
	}
	return nil
}

func main() {
	spec := RunSpec{
		Repository:     "org/service",
		BaseCommit:     "4d2f7c1",
		Branch:         "agent/run-42",
		WritableRoots:  []string{"internal", "tests"},
		AllowedDomains: []string{"proxy.example.test"},
		RequiredChecks: []string{"go test ./...", "go vet ./..."},
		MaxDuration:    45 * time.Minute,
	}
	fmt.Println(Validate(spec))
}

Runtime Enforcement 必须与这份校验一致。只有当文件系统、Proxy、Credential Broker 和 Git Provider 都执行它时,Run Spec 字段才是真正的安全控制。

验收证据,而不是 Agent 自证

Evidence Bundle

每次 Run 都应返回:

text
run_id
task_hash 与可信指令版本
policy_version
environment_image_digest
base_commit 与 final_commit
Credential 签发与撤销
命令、时间戳与退出码
网络 Allow/Deny/Approval 决策
改动文件与 Diff Hash
测试、扫描与最终状态检查
Artifact URI 与 Hash
未解决失败和 Degraded 状态
分支与 Pull Request 标识
Teardown 状态

根据威胁模型,使用 Append-only Storage、签名 Statement 或平台审计控制保护完整性。

证据层级

证据 能证明什么
Agent 摘要 Agent 声称做了什么
Terminal Transcript Shell 返回了什么文字
Exit Code 进程是否报告成功
Test Report 哪些测试执行及其结果
Artifact Hash Artifact 身份
Final-state Assertion 必需状态是否存在
独立 CI Run Agent Workspace 外的验证
Reviewer Approval 可问责人工判断

单一证据无法证明整体正确。应按任务风险组合证据包。

取消、超时与恢复

远程 Run 一定会失败:供应商超时、VM 消失、测试卡死、Base Branch 前进,或人工取消。

必需语义

  • 取消传播到子进程和工具调用;
  • 即使 Teardown 部分失败,也撤销 Credential;
  • Lease 和预算由服务端到期;
  • Checkpoint 区分安全重放和外部副作用;
  • 恢复后的 Run 记录新 Execution Attempt;
  • Base Commit 过期时触发 Rebase 或 Restart Policy;
  • 重复投递不会创建两个分支或两次外部变更;
  • 部分 Artifact 标为 Incomplete,而不是 Passed。

如果某个步骤已发消息、改数据库、发布 Package 或修改 Cloud Infrastructure,除非操作有 Idempotency Key 且已验证状态,否则不能自动重试。

任务选择与自主等级

任务 默认模式 原因
文档修复 Branch-only 自主执行 Diff 客观且爆炸半径小
聚焦补测试 自主执行 + CI 验收可复现
依赖更新 限制 Egress + Lockfile 评审 供应链代码执行
Auth 重构 先计划 + 人工 Checkpoint 高安全影响
Schema Migration Sandbox 模拟 + 审批 不可逆数据风险
生产故障 监督执行,先只读 在线系统不确定性
多仓发布 编排工作流,不使用单个宽权限 Agent 身份与回滚复杂

自主程度应由风险和可验证性决定,而不是模型语气有多自信。

运营指标

采用率和 PR 数量不能证明价值,应衡量:

  • Eligible Task 中被接受的任务比例;
  • First-pass Gate Rate;
  • 人工修正时间;
  • Escaped Defect 与 Rollback Rate;
  • P50/P95 运行与排队时间;
  • 每个接受变更的计算、模型和环境成本;
  • 取消与基础设施失败率;
  • Prompt Injection 与 Policy Denial 事件;
  • Reviewer Backlog 与可问责审批时长;
  • 证据和 Teardown 完整的 Run 比例。

必须与同类任务的旧工作流比较。生成更多 PR 可能因为审查需求或缺陷风险上升而降低真实吞吐。

发布检查清单

  1. 每次 Run 都有不可变范围、Base Commit、策略和预算。
  2. Workspace 隔离与保留 Snapshot 已记录。
  3. Git 和 Cloud 身份短期且 Run-scoped。
  4. 默认不存在生产凭证。
  5. Egress 被禁用或显式 Allowlist,并完整记录。
  6. 仓库和外部内容无法授予新能力。
  7. 受保护文件、分支规则和合并控制由外部强制执行。
  8. 验收门禁独立于 Agent 自我评估运行。
  9. 已测试取消、过期 Base、重复任务和 Teardown 失败。
  10. 证据保留与删除符合仓库敏感度。
  11. 高风险改动由人工或可问责策略 Owner 批准。
  12. 指标比较接受结果,而不是生成活动。

常见问题

Cloud Agent 比本地 Agent 更安全吗?

两者风险不同。Run 级隔离与 Egress Policy 可能强于开发者电脑;Cloud Storage、无人值守执行和远程凭证又引入新风险。应比较实际控制,而不是运行位置。

Draft Pull Request 是否足以构成人在回路?

只有当 Branch Protection、Required Check、Reviewer 和 Deployment Approval 都不可绕过时才足够。Draft 标签本身只是展示状态。

Agent 是否应该联网?

只有任务价值足以支持这条通道时才应联网。优先无网络、可信缓存或严格 Allowlist,并把依赖访问与任意浏览分开。

Secret Redaction 能防止外泄吗?

不能。Redaction 只能防止部分原值出现在日志或模型上下文,无法阻止进程使用、转换或发送 Credential。应最小化签发并使用 Broker。

应并行运行多少个 Cloud Agent?

并发应由环境预算、冲突域、Reviewer 容量和任务独立性决定。无限并发会制造队列、冲突分支和无法审查的输出。

一手资料

关联学习路径

总结

Cloud Coding Agent 适合范围明确、环境可复现、验收客观,且产出停留在可回滚分支的任务。其价值并不是移除人,而是把执行迁移到受控、可观测运行时,同时保留可问责审批。

在扩大自主程度前,应先设计身份、Egress、Secret、分支限制、证据、取消和清理。缺少这些控制时,所谓“后台执行”只是套着有说服力界面的无人值守代码执行。