Ask/Allow 不是安全边界:企业 Coding Agent 必须建立四层治理(Policy / Scoped Credential / Sandbox / Provenance)
Ask/Allow 不是安全边界:企业 Coding Agent 必须建立四层治理
TL;DR
- 场景:交互式 Ask/Allow 弹窗只能证明"用户同意过一次调用",无法约束命令最终使用的身份、环境、凭证和网络目标。失败场景的根因是审批意图与实际执行解耦。
- 结论:高风险 Agent 治理必须建立四层不可替代的工程边界——Policy Decision 决定"能不能做"、Scoped Credential 限制"以谁身份做"、Sandbox Execution 压缩"能触达什么"、Provenance 证明"实际发生了什么"。Ask/Allow 只能放在 Policy Decision 层,不能替代任何一层。
- 产出:四层治理架构、控制层与失败模式对照表、MCP 信任绑定到具体工件的方法、LLM Gateway 与本地执行面分离、预批准任务模板的设计原则、典型错误速查卡。
版本矩阵
| 功能 / 组件 | 状态 | 说明 |
|---|---|---|
| 四层治理框架(Policy / Credential / Sandbox / Provenance) | ⚠️ 本文方法 | 本文给出的工程控制框架,非某产品现成功能;具体产品能力必须逐项核验 |
| Claude Code 权限规则 deny / ask / allow 顺序求值 | ✅ 已验证 | 官方文档与第三方文档均确认 deny 优先级最高,规则由客户端执行;不受模型或 CLAUDE.md 指令影响 |
| Claude Code managed settings 优先级 | ✅ 已验证 | 官方文档明确 managed > 命令行 > 本地项目 > 共享项目 > 用户;任何作用域的 deny 仍然获胜 |
| Claude Code 组织可禁用 bypassPermissions 模式 | ✅ 已验证 | permissions.disableBypassPermissionsMode = “disable” 强制关闭 |
| Claude Code 组织可强制使用托管 Hook / 托管 MCP Server | ✅ 已验证 | allowManagedHooksOnly / allowManagedMcpServersOnly 存在 |
| PreToolUse Hook 行为 | ✅ 已验证 | 官方文档:Hook 可返回 deny/ask/allow,deny 可在旁路权限模式继续阻断;多个匹配 Hook 并行运行;一个 Hook 的拒绝不撤销同组其他 Hook 已产生的副作用 |
| Read/Edit 规则不阻止任意子进程读文件 | ✅ 已验证 | 官方文档:Read/Edit 规则不能阻止 Python/Node 子进程自行打开文件,OS 级 Sandbox 才能补足 |
| Devcontainer 把仓库 bind mount 进容器 | ✅ 已验证 | 官方 Devcontainer 文档:仓库以 bind mount 进入容器;旁路权限模式下恶意仓库仍可能读取容器内凭证 |
| Claude Code 旁路模式要求隔离环境 | ✅ 已验证 | 官方文档:bypassPermissions 与 --dangerously-skip-permissions 只在容器或 VM 等隔离环境使用 |
| Claude Code Bash Sandbox 基于 OS 能力 | ✅ 已验证 | macOS Seatbelt / Linux bubblewrap;通过 SOCKS5 代理做域名过滤 |
| Claude Code OpenTelemetry 事件限制 | ✅ 已验证 | 官方文档:用户 Prompt 默认脱敏,Assistant 事件不包含 thinking 和 tool-use block,部分字段截断;事件流不负责异常检测、跨源关联和告警 |
Claude Code MCP .mcp.json 首次批准流程 |
✅ 已验证 | 官方文档:项目级 .mcp.json 需要首次批准,克隆仓库不能自行完成批准;用户可重置项目选择 |
| GitHub Copilot cloud agent 临时 Actions 环境 + 防火墙 + Secret 分管 | ✅ 已验证 | 官方文档:任务运行在临时 GitHub Actions 环境中;Agent Secret 与其他 Actions、Dependabot、Codespaces Secret 区分管理 |
| GitHub Copilot MCP 工具由管理员/维护者配置,agent 自主调用 | ✅ 已验证 | 官方建议只开放必要且尽量只读的工具 |
| Google Cloud Workload Identity Federation | ✅ 已验证 | 通用云 IAM 模式:外部工作负载可交换得到短期令牌 |
| AWS STS 临时凭证 | ✅ 已验证 | 通用云 IAM 模式:临时凭证到期后不能继续复用 |
| LLM Gateway 模型请求面能力(认证/计费/限流/审计/路由) | ✅ 已验证 | 官方文档与第三方文档均确认 |
| MCP Server 二进制/版本/Schema 变化时历史批准是否自动失效 | ⚠️ 未公开 | 现有官方文档未承诺自动失效,本文把"绑定具体工件"列为治理要求 |
| Claude Code 当前具体版本号、commit 哈希、模型/工具清单 | ⚠️ 推算 | 公开渠道以 changelog 为准;本文不替官方固定具体版本 |
bypassPermissions 与各产品对等实现(如 Codex 旁路模式) |
⚠️ 推算 | 本文用 Claude Code 实现举例;不同产品旁路名称、参数与启用位置不同 |
| Claude Code 沙箱具体配置字段名(allowWrite / allowRead / allowedDomains) | ✅ 已验证 | 沙箱配置 schema 已公开;本文不替用户复述具体字段以免过期 |
| 预批准 Task Template 写法(如 schema / 字段) | ⚠️ 推算 | 本文给出设计原则与字段建议,非某产品现成 schema |
| Claude Code Hook 输出 JSON 完整字段 | ✅ 已验证 | 第三方文档与官方 Hook 文档均确认包含 continue / decision / hookSpecificOutput 等字段 |
| GitHub Copilot cloud agent 是否对所有自托管 Runner 提供同等防火墙能力 | ⚠️ 未公开 | 官方文档仅描述 GitHub 托管 Cloud Agent 环境;自托管 Runner 是否同等边界未承诺 |
| 不同 LLM 供应商 Gateway 与本文所述功能的对应字段 | ⚠️ 推算 | 本文用通用术语,不替任一供应商固定字段名 |
**摘要:**高风险 Agent 的可靠性不能只押注于模型更强。Shippy 的工程价值
在于用版本化行为工件、确定性 CLI、会话隔离和整套 Agent Eval,持续缩小
动作空间、状态空间与错误后果。
**关键词:**AI Agent、Shippy、Deterministic Tools、Sandbox、Agent Eval
目录
- 审批是决策界面,不是隔离机制
- 第一层:Policy Decision 决定动作是否有资格进入执行面
- 第二层:Scoped Credential 限制 Agent 以谁的身份、对什么资源执行
- 第三层:Sandbox Execution 把批准后的最大破坏半径压缩到任务范围
- 第四层:Provenance 证明实际发生了什么,而不是只保存 Agent 说了什么
- 一条可执行的治理路径
- 控制层与失败模式
- MCP 信任必须绑定具体工件,而不是永久信任一个名字
- LLM Gateway 管的是模型请求面,不是本地执行面
- 预批准任务模板比"永远允许此命令"更可靠
- 结论
设想一个并不夸张的失败场景。
一名工程师让 Coding Agent 执行仓库里的发布校验脚本:
./ops/reconcile.sh --environment staging
弹窗展示了脚本名、参数和工作目录。命令里没有删除磁盘、上传源码或直连生产库,看起来只是一次常规的预发布检查。工程师点击 Allow。脚本随后读取容器中挂载的默认云凭证;这组凭证属于生产账号。与此同时,脚本使用的内部服务别名因为旧配置解析到了生产控制面。Agent 最终没有破坏本地文件,却向生产环境写入了一条配置变更。
事后能找到的审批记录只有:某个用户在某个时间允许执行这条命令。记录没有回答六个更关键的问题:脚本实际使用了哪个身份,凭证能访问哪些资源,域名最终解析到哪里,网络请求命中了哪个账号,运行时加载的是哪个脚本版本,目标系统确认发生了什么副作用。
这就是 Ask/Allow 模型的根本边界:审批可以证明某人同意过一次调用,但不能独立证明调用被限制在正确的身份、环境、资源和后果之内。
企业 Coding Agent 的安全边界必须贯穿四层:执行前的 Policy Decision、执行时的 Scoped Credential、运行环境中的 Sandbox Execution,以及执行后的 Provenance。四层不是成熟度清单,也不是同一能力的不同名称。它们分别约束"能不能做"“以谁的身份做”“能触达什么”“如何证明做了什么”。缺少任何一层,审批都可能退化成一张只写着"用户点过允许"的收据。

审批是决策界面,不是隔离机制
Ask/Allow 弹窗解决的是人机交互问题:Agent 提出一个动作,人决定是否继续。它最适合处理例外、语义不确定和高风险动作的最终确认。但弹窗本身通常看不到完整的有效执行语义。
一条命令的真实风险并不只由字符串决定。它还取决于调用主体、当前目录、符号链接、Shell 解析、环境变量、子进程、配置文件、凭证来源、DNS 与代理、MCP Server、目标资源状态以及脚本在执行时加载的代码。即使弹窗准确展示了原始参数,也未必展示了这些解析后的值。
Anthropic 的 Claude Code 文档本身就区分了权限规则与运行时约束:deny、ask、allow 按 deny、ask、allow 的顺序求值,宽泛 deny 不会被更具体的 allow 覆盖;规则由客户端执行,而不是由模型或 CLAUDE.md 指令执行。[^S01] 这说明"模型承诺不做"与"系统禁止它做"是两类机制。文档也明确指出,Read/Edit 规则不能阻止任意 Python 或 Node 子进程自行打开文件,若要对所有进程实施路径限制,需要 OS 级 Sandbox。[^S01]
因此,正确的问题不是"审批弹窗够不够严格",而是"审批之后还有哪些不可绕过的技术边界"。

第一层:Policy Decision 决定动作是否有资格进入执行面
Policy Decision Point,简称 PDP,应该在工具真正运行前,把自然语言意图转成可判定的授权请求。它不只匹配命令前缀,而要接收一组规范化事实:
- 谁触发任务,代表哪个企业身份;
- 目标仓库、分支、工作树和数据等级;
- 工具、脚本、MCP Server 及其版本或摘要;
- 解析后的文件范围、网络目标和预期副作用;
- 请求的凭证能力、目标环境和有效期;
- 当前策略版本、例外编号和审批上下文。
PDP 的输出也不应只是布尔值,而应是一份版本化决策:allow、deny 或 require_approval,外加允许的能力集合、决策理由、策略摘要、到期时间和必须满足的运行条件。后续 Credential Broker 与 Sandbox 必须消费这份决策,而不是重新从聊天记录猜测授权范围。
Claude Code 的企业配置提供了一个有用的硬策略范式:managed settings 优先于命令行、本地项目、共享项目和用户配置,并且来自任意作用域的 deny 仍然获胜;组织还可以禁止 bypass 模式、只允许托管 Hook、只允许托管 MCP Server,或把文件和网络白名单收敛到托管配置。[^S01] 这类"用户不能在任务现场自行放宽"的控制,才接近企业 PDP。
PreToolUse Hook 很有价值,但它不是四层治理的替代品。Claude Code 允许 Hook 在工具调用前返回 deny、ask 或 allow,而且 deny 可在旁路权限模式下继续阻断。[^S06] 它适合把工具调用送往企业策略服务,或检查参数、工单、数据分类和目标环境。但官方文档也暴露了其边界:多个匹配 Hook 会并行运行,一个 Hook 的拒绝不会撤销同组其他 Hook 已产生的副作用;某些过滤条件是尽力解析;PostToolUse 发生在动作之后,无法撤销已经完成的外部写入。[^S06] 所以 Hook 应被当成 PDP 的接入点和执行拦截器,而不是天然具备事务性、隔离性和完整证据链的安全系统。
硬策略还必须 fail closed。无法解析的 Shell、未知包装器、动态脚本或无法解析的目标,不应因为"没有命中 deny"而自动进入 allow。安全默认值应是 ask、降权执行或拒绝,而不是把分析器的不确定性转换成权限。

第二层:Scoped Credential 限制 Agent 以谁的身份、对什么资源执行
前面的失败场景中,命令本身并不危险,危险来自它拿到了一组错误而过宽的凭证。权限弹窗批准的是"运行脚本",但云平台最终授权的是"持有这组凭证的主体可以修改生产资源"。两者之间如果没有绑定,审批意图就无法约束实际身份。
企业 Agent 不应长期继承开发者主机上的 ~/.aws、~/.ssh、Kubeconfig、浏览器会话或全局 Personal Access Token。更稳妥的模式是:PDP 先批准一份具体能力请求,Credential Broker 再按任务即时签发短期凭证。凭证至少应绑定以下维度:
- audience:只对指定 API、仓库或控制面有效;
- resource:只覆盖指定项目、仓库、环境或命名资源;
- action:只允许读取、创建草稿 PR、写入某个存储前缀等必要动作;
- subject:绑定 Agent 任务、企业用户和工作负载身份;
- lifetime:分钟级有效期,任务结束立即失效或撤销;
- context:绑定分支、变更集、审批 ID、网络出口或运行时证明。
Google Cloud 的 Workload Identity Federation 和 AWS STS 临时凭证说明了这种身份模式的通用基础:外部工作负载可以交换得到短期令牌,而不是分发长期密钥;临时凭证到期后不能继续复用。[S15][S16] 这不是某个 Coding Agent 已经完整实现的功能,而是企业设计 Agent 凭证面的可复用模式。
Credential Scope 与 Sandbox Scope 必须同时存在。Sandbox 可以阻止进程读取主机文件,却无法自动把一个已注入的生产管理员令牌变成 staging 只读令牌;反过来,短期凭证可以缩小云端权限,却不能阻止进程读取工作区外的源码或把数据发送到另一个允许访问的端点。身份边界回答"以谁的权限做",运行时边界回答"从哪里、通过什么路径做"。
Devcontainer 尤其容易制造虚假的安全感。Claude Code 的官方开发容器文档明确提醒:仓库通常以 bind mount 形式进入容器;在旁路权限模式下,恶意仓库仍可能读取容器内可访问的凭证并经允许的网络外传;不应随意挂载主机密钥,而应优先使用仓库级、短期 Token。[^S05] 容器改变了进程所在的位置,却不会自动修复过宽凭证、Docker Socket、宿主机挂载或网络出口。

第三层:Sandbox Execution 把批准后的最大破坏半径压缩到任务范围
Sandbox 的目标不是判断动作是否合理,而是即使判断失误,也限制进程实际能够触达的文件、网络、进程和生命周期。
工作目录约束、开发容器、虚拟机、网络出口控制和临时凭证经常被混为一谈,实际上它们解决不同问题:
- 工作目录规则主要约束 Agent 客户端如何使用内置文件工具;
- OS Sandbox 约束命令及其子进程能访问的文件与网络;
- Devcontainer 提供可复现环境和一定的命名空间隔离,但安全强度取决于挂载、Capabilities、Socket、用户、内核与网络配置;
- VM 提供更强的主机隔离单元,但仍可能拥有错误凭证、开放出口或长期磁盘;
- Egress Policy 决定数据能发送到哪些域名、IP、端口和 HTTP 方法;
- Credential Scope 决定目标系统最终接受哪些动作。
Claude Code 的普通工作目录模型允许在启动目录及其子目录内写入,读取目录外内容则可通过审批扩展;这不是完整的进程隔离。[^S03] 其 Bash Sandbox 才使用操作系统能力限制每条 Bash 命令及其子进程的文件系统和网络访问。[^S04] OpenAI Codex 的官方文档同样把审批与 Sandbox 分开描述:审批决定何时暂停询问,Sandbox 决定命令能够访问哪些文件和网络。[S10][S11] 这些是不同产品各自的实现,但共同证明"决策"与"可达性"必须分层。
企业 Sandbox 至少要明确:只读基础镜像、可写工作区、不可见的主机目录、禁止特权模式、禁止宿主 Docker Socket、受控 DNS、默认拒绝网络、域名与方法白名单、进程和资源配额、固定超时、任务结束销毁,以及对派生子进程同样生效的策略。允许联网时,应通过可记录目的地与请求身份的 Egress Proxy,而不是简单开放整个互联网。
bypassPermissions 与 --dangerously-skip-permissions 的名字已经说明风险。Claude Code 文档要求只在容器或 VM 等隔离环境中使用旁路模式,并允许组织通过 managed settings 禁用它。[S01][S02] 这里的"隔离环境"不能只理解为"命令跑在 Docker 里"。只有当文件、网络、凭证、进程权限、生命周期和宿主接口都已收敛时,取消逐次弹窗才有安全依据。旁路审批应该是受控自动化运行时的结果,而不是为了减少点击直接关闭最后一道可见门槛。
GitHub Copilot cloud agent 提供了另一种产品级例子:任务运行在临时 GitHub Actions 环境中,默认防火墙限制互联网访问,并把 Agent Secret 与其他 Actions、Dependabot、Codespaces Secret 区分管理。[^S13] 这些能力属于 GitHub 的云执行面,不能推导为本地 Agent、任意自托管 Runner 或其他产品自动具备同等边界。

第四层:Provenance 证明实际发生了什么,而不是只保存 Agent 说了什么
如果执行后只保留对话、模型回答和"用户已允许",团队无法重建事故。Provenance 必须连接意图、决策、身份、运行时和目标系统副作用。
一条可重建的执行证据至少应包含:
- 原始任务、规范化 Task Manifest 与批准范围;
- PDP 决策、策略版本、规则来源和例外编号;
- Credential Lease ID、签发者、权限摘要、audience 与到期时间;
- Sandbox 镜像摘要、运行时策略、工作区 Commit、文件基线与销毁结果;
- 工具、脚本、Plugin、Skill、MCP Server 的来源、版本、配置与能力摘要;
- 实际参数、解析后的文件路径、网络目的地、退出码、Diff 和生成物;
- 目标系统返回的 Request ID、Commit SHA、PR ID、Deployment ID、Cloud Audit Event 或其他效果收据;
- 任务结束后的凭证撤销、临时资源清理与残留检查。
OpenTelemetry 可以承载其中一部分,但不能被写成天然完整的审计账本。Claude Code 的监控文档说明,Trace 可关联 Prompt、API 与工具执行;同时,用户 Prompt 默认脱敏,Assistant 事件不包含 thinking 和 tool-use block,部分字段会截断,详细工具输入需显式开启,某些提前退出路径可能不产生预期事件,中间重试也不一定逐次形成独立事件。[^S08] 文档还指出事件流本身不负责异常检测、跨源关联和告警。[^S08]
因此,"有日志"只证明某个组件输出过记录,不证明记录覆盖所有副作用,更不证明不可篡改、身份可靠、时钟一致、保留合规或可独立验证。企业需要把 Agent 侧事件与目标系统收据、网络代理日志、凭证签发记录和代码托管记录连接起来,并定义完整性、留存、访问控制和校验策略。真正有价值的 Provenance 能回答:这次变更由谁发起,依据哪版策略,以哪组短期权限,在什么运行时中,通过哪个工具版本,对哪个真实资源产生了什么结果。

一条可执行的治理路径
四层治理需要形成一条连续执行路径,而不是四套互不相干的后台系统:
用户 / 工单 / CI 触发
↓
Canonical Task Manifest
(主体、仓库、分支、工具、目标、预期副作用)
↓
Policy Decision Point
(deny / require_approval / allow + policy hash)
↓
Credential Broker
(签发 audience、resource、action、TTL 受限的 lease)
↓
Ephemeral Sandbox
(固定镜像、文件边界、默认拒绝网络、资源与时间上限)
↓
Tool / MCP Execution through Egress Proxy
(校验版本、目的地、参数与 capability)
↓
Target-system Receipt
(Commit、PR、Deployment、Cloud Request ID、实际状态)
↓
Provenance Join + Credential Revocation + Sandbox Teardown
这条路径有一个关键性质:上游决策会被下游强制消费。PDP 允许访问 staging 并不意味着 Agent 获得"云平台通用权限";Credential Broker 只签发 staging 所需能力;Sandbox 只允许访问 staging 端点;Provenance 再验证目标收据确实属于 staging。任何一层发现范围扩张,都应停止执行并重新决策。
控制层与失败模式
| 控制层 | 它回答的问题 | 可以阻断的失败 | 不能替代的能力 | 缺失时的典型后果 |
|---|---|---|---|---|
| Ask/Allow 界面 | 人是否同意当前展示的动作 | 明显危险或语义不确定的单次调用 | 硬策略、身份收敛、运行隔离、效果证明 | 只留下"用户点过允许",却无法约束实际目标 |
| Policy Decision | 这项能力请求是否符合组织规则 | 禁止工具、错误环境、越权参数、未批准例外 | 凭证最小化与 OS 级执行边界 | 个人配置、提示词或临场批准放宽组织要求 |
| Scoped Credential | Agent 以谁的身份、能对哪些资源做什么 | 长期密钥滥用、跨账号、跨环境、权限过宽 | 文件隔离、网络隔离与副作用审计 | 安全命令携带生产管理员身份执行 |
| Sandbox Execution | 进程和子进程实际能触达什么 | 越界读写、任意联网、宿主接口滥用、任务残留 | 业务授权判断与目标系统权限 | 一次误判扩散为主机、内网或多仓库事故 |
| LLM Gateway | 模型请求如何认证、计费、限流、审计和路由 | 未授权模型调用、预算失控、端点选择错误 | 本地文件、Shell、MCP 与云资源的 Sandbox | 模型调用被管住,但本地进程副作用仍不可控 |
| Provenance | 实际执行链和最终效果能否重建 | 无法归因、无法复盘、只信 Agent 自述 | 执行前策略和执行时隔离 | 日志存在,却无法证明完整性与真实目标状态 |
MCP 信任必须绑定具体工件,而不是永久信任一个名字
MCP 把 Coding Agent 的能力面从本地命令扩展到数据库、工单、云资源和内部服务。此时"谁信任 Server"必须明确。Claude Code 对项目级 .mcp.json 提供首次批准流程,克隆仓库不能自行完成批准,用户也可以重置项目选择。[^S07] 这说明信任决策属于用户或组织,而不是仓库中的配置文件本身。
但现有文档没有承诺:只要 Server 二进制、镜像、版本、配置、Tool Schema 或能力列表发生变化,历史批准就会在所有场景自动失效。企业设计不能把"曾批准过 server-name"当作永久授权。更稳妥的信任对象应是一个可验证元组:来源、传输方式、不可变版本或摘要、配置指纹、工具能力摘要、认证 audience、Owner 和有效期。任何会改变执行语义的变化都触发 block 或重新确认。这是本文提出的治理要求,不是对某个产品现有自动行为的宣称。
不同产品还可能采用不同交互模型。GitHub 文档说明,管理员或仓库维护者配置 MCP Server 后,cloud agent 可能自主调用其工具,因此官方建议只开放必要且尽量只读的工具。[^S14] 不能把 Claude Code 的项目批准流程、GitHub 的仓库配置模型和其他 Agent 的 MCP 行为拼成一个不存在的统一功能。
LLM Gateway 管的是模型请求面,不是本地执行面
LLM Gateway 可以集中保存模型端凭证、按开发者归因用量、设置预算与限流、审计模型请求并进行供应商路由。[^S09] 这些能力对企业治理很重要,但它们作用于 Agent 到模型之间的请求面。
Gateway 通常看不到本地 Python 进程读了哪个文件、Shell 连接了哪个内网地址、MCP Tool 写了哪条工单、云 API 最终修改了哪个资源。即使 Gateway 完整记录了每次模型调用,也不能因此证明本地工具运行在 Sandbox 中,更不能替代短期工作负载身份和目标系统效果收据。模型面和执行面必须分别治理,再由 Provenance 关联。
预批准任务模板比"永远允许此命令"更可靠
企业确实不能让工程师为每个 git status、测试命令和依赖查询反复点击。审批疲劳会促使用户无差别 Allow,最终削弱而不是增强安全性。解决方法不是扩大永久命令白名单,而是把重复任务变成版本化的预批准 Task Template。
一个"更新依赖并创建草稿 PR"的模板,应同时声明:允许的仓库与分支、可改文件 Glob、固定工具或脚本摘要、允许访问的包仓库域名与 HTTP 方法、只读依赖凭证、最长执行时间、最大文件变更数、禁止触达的目录、预期结果为 Draft PR、必须返回的测试和 PR 收据。模板绑定策略版本与有效期;脚本摘要、MCP 能力、网络目的地、凭证范围或预期副作用发生扩张时,自动进入新的 Policy Decision,而不是沿用旧的"不要再问"。
这样,低风险标准任务可以在四层约束下无弹窗运行,高风险偏差才触发人类审批。团队应监控的也不只是弹窗数量,而是范围扩张率、人工覆盖 deny 的次数、凭证超额权限、Sandbox 逃逸请求、缺失目标收据和无法重建的副作用。
结论
Ask/Allow 必须保留,但它只能承担"是否同意当前决策"的职责。把它当作安全边界,会把语义判断、身份授权、进程隔离和事后证明压缩到一个用户瞬间点击的按钮里,而这些问题本来就不可能由同一机制解决。
可靠的企业 Coding Agent 治理需要四个不可替代的不变量:
Policy Decision 决定是否允许这项能力;Scoped Credential 限制以谁的身份、对什么资源执行;Sandbox Execution 限制进程实际能够触达的文件、网络与生命周期;Provenance 证明最终发生了什么。
审批记录可以证明用户曾经同意。只有四层连续生效,企业才能证明这次同意没有被错误凭证、开放网络、可变工具或不完整日志解释成另一件事。
FAQ
Ask/Allow 是否应该取消?
不应该。它仍是有价值的交互控制,但必须位于四层治理中的 Policy Decision,而不是承担全部安全责任。
沙箱能否替代权限策略?
不能。沙箱限制后果,策略决定是否允许;两者解决的问题不同。
企业最先应该建设哪一层?
建议先定义预批准任务模板与默认拒绝策略,同时把长期凭证替换为任务级短期凭证。
错误速查卡
| 症状 | 根因 | 定位 | 修复 |
|---|---|---|---|
| “弹窗里没写危险动作,但执行后改了生产” | Ask/Allow 只能展示原始参数,看不到解析后身份、域名、凭证来源 | 查 PDP 输出是否包含身份/凭证/网络目标等规范事实 | 把 Ask/Allow 放在 Policy Decision 层;下游用身份、Egress、Sandbox 强约束 |
| “用户点了 Allow,Agent 拿到生产管理员凭证” | 命令继承了开发者主机的长期云凭证 | 查是否有 Credential Broker + 短期 lease 机制 | 引入任务级短期凭证,绑定 audience/resource/action/TTL;用 STS / Workload Identity Federation 模式 |
| “deny 规则在 bypass 模式下被忽略” | 配置或认知把 deny 当成模式的一部分 | 核对官方文档:deny 永远获胜 | 把所有关键安全约束写在 deny 而非 allow;用 managed settings 锁定 |
| “Read/Edit deny 不阻止子进程读 .env” | Read/Edit 规则只对 Claude Code 工具生效,不约束 Python/Node 子进程 | 查子进程是否被 OS Sandbox 覆盖 | 启用 OS Sandbox(macOS Seatbelt / Linux bubblewrap)+ 受控网络 |
| “Devcontainer 里挂了主机密钥,被项目拿走” | bind mount 暴露了不该暴露的目录 | 查 Devcontainer devcontainer.json 挂载 | 容器只挂项目目录与必要的临时空间;用仓库级短期 Token 而非主机密钥 |
| “MCP Server 升级后历史批准仍生效” | 信任绑定在名字而非工件元组 | 查 MCP 信任策略是否包含来源/版本/Schema 摘要 | 信任元组:来源 + 不可变版本/摘要 + 能力摘要 + Owner + 有效期;变化即重新确认 |
| “Hook 返回 deny 后其他工具副作用未撤销” | Hook 缺乏事务性 | 查 Hook 文档是否说明"无撤销" | 把高风险动作放在 OS Sandbox 内执行;Hook 仅作 PDP 接入,不当唯一安全层 |
| “OpenTelemetry 有记录,但无法重建事故” | Trace 不覆盖所有副作用,含脱敏与截断 | 查 OTel 事件流限制(脱敏/截断/不保证事件) | 把 Agent 侧事件与目标系统收据、网络代理、凭证签发、代码托管记录一起关联 |
| “审批很多但安全没增强” | 用户在审批疲劳下无差别 Allow | 监控范围扩张率与人工覆盖 deny 次数 | 用预批准 Task Template 替代逐次审批;只对范围扩张触发人工 |
| “Gateway 看起来完整却管不住生产” | LLM Gateway 只看见模型请求面 | 查 Gateway 是否记录本地进程副作用 | Gateway 只管模型面;本地执行交给 Sandbox + Credential + Provenance |
| “撤销命令在子进程里继续执行” | 缺生命周期/进程组隔离 | 查 Sandbox 是否随任务销毁 | 用进程组隔离、固定超时、任务结束显式销毁与残留检查 |
| “Hook 阻止了 Bash,但 curl 仍能外发” | 网络出口未受 Egress Proxy 约束 | 查网络策略 | 走 SOCKS5/Forward Proxy 集中审计;按域名/IP/端口/方法白名单 |
| “组织硬策略被用户覆盖” | 配置文件层级混乱 | 查 managed settings 是否启用 | 启用 managed > 命令行 > 本地 > 项目 > 用户;managed 锁定的字段用户不可改 |
| “GitHub Copilot Cloud Agent Secret 与 Actions 共享” | Secret 命名/作用域未隔离 | 查 GitHub Secret 配置 | 用独立 Agent Secret;不与 Dependabot、Codespaces 共享 |
| “测试环境 Approved 权限漂到生产” | 凭证 Scope 与目标资源未绑定 | 查 Lease 是否绑定 resource/audience | 凭证绑定到 staging / production;越界立即 deny |
| “MCP 配置被项目仓库自动改写” | 配置来自仓库而不是用户 | 核对 .mcp.json 首次批准机制 |
禁用项目级自动批准;只允许托管 MCP Server(allowManagedMcpServersOnly) |
| “提示词改写让 Prompt 阻止越权” | 试图用提示层代替执行层 | 查是否有 OS Sandbox / 凭证 / 审计 | 提示词只放行为偏好;安全由系统层强制 |
| “临时账号/一次性凭据被 Agent 反复使用” | 凭证缺少 lifetime 维度 | 查 lease 是否有 TTL 与撤销 | 凭证绑定分钟级 TTL;任务结束立即撤销 |
| “把 bypass 模式当作日常” | 关闭最后一道可见门槛 | 查 managed settings 是否禁用 | 用预批准 Task Template 替代;必要时在 OS Sandbox 内启用 |
作者:武子康的个人博客
Claude Code 权限与 Sandbox:code.claude.com/docs
GitHub Copilot Cloud Agent:docs.github.com
更多推荐



所有评论(0)