摘要: 企业 Coding Agent 的 Tool Approval 不能只做成“运行 Shell 前弹一个确认框”。真正有效的审批体系要同时判断动作类型、目标资源、数据敏感度、环境、可逆性、网络去向和调用身份。本文结合 OpenAI Codex、Claude Code、GitHub Copilot Cloud Agent 与 MCP 官方资料,给出 Shell、文件、Git、数据库、网络、Secrets 和 MCP 操作的四级审批矩阵,并提供可落地的 YAML 策略、审批流程、日志字段、回滚与测试方案。结论是:只读且限定在工作区内的低风险动作可以自动允许;删除、覆盖、外传、发布、付款、权限变更、生产环境写入和高权限 MCP 必须人工批准或直接禁止。
核心结论
企业 Coding Agent 应采用“默认拒绝、按能力授权、按上下文升级”的 Tool Approval,而不是简单地把某几个命令加入白名单。审批对象必须是一次完整的工具调用,包括命令、参数、工作目录、目标资源、身份、网络去向与预期副作用;否则同一个 python、git 或 MCP 工具既能做安全检查,也能删除数据或把源码发送到外部。
- 可自动允许: 工作区内只读检索、格式检查、编译、无网络单元测试、读取公开文档,以及写入临时构建目录等可逆操作。
- 必须人工批准: 工作区外读取、覆盖或删除文件,安装依赖,访问外网,推送 Git 分支,创建或合并 PR,发送消息,调用可写 MCP,读取 Secrets,以及任何生产环境操作。
- 原则上禁止: 绕过审计、关闭安全控制、导出凭据、破坏性生产数据库命令、修改 IAM/MFA、不可恢复删除、匿名上传企业源码等行为。
- 审批不能替代隔离: 沙箱、最小权限令牌、网络出口白名单、短时凭据、分支保护和数据库只读副本必须先于人工确认存在。
- 实施重点: 将审批策略版本化,绑定调用身份与任务,记录请求—决定—执行—结果四段证据,并用红队案例验证规则无法被命令拼接、脚本包装或 MCP 别名绕过。
为什么 Tool Approval 是 Coding Agent 的核心控制面
结论:Coding Agent 的风险不在“会写错代码”这一点,而在它能把错误转化为真实系统动作。 普通聊天模型输出一条危险命令,还需要人复制执行;Coding Agent 可以直接调用 Shell、编辑文件、访问 GitHub、使用云凭据或连接 MCP 服务。如果权限范围过大,一段被污染的 README、Issue、网页或依赖文档就可能诱导 Agent 读取私密文件、外传源码或改变基础设施。
OpenAI 官方说明,Codex 本地运行时使用操作系统强制沙箱限制可触达范围,通常限定在当前工作区,并由审批策略决定何时停止并请求用户许可;默认网络访问关闭。Claude Code 则提供 allow、ask、deny 权限规则,并可通过 PreToolUse Hook 在调用前阻止或升级审批。GitHub 官方文档显示,Copilot Cloud Agent 配置仓库 MCP 后会自主使用可用工具,并不会在每次使用前请求批准。这说明产品交互层不同,企业策略不能假设所有 Agent 都会弹窗。
MCP 规范也没有强制统一的人机交互模型。MCP Tool 是“模型可控”的能力,客户端可以自主决定界面和批准方式。因此,“MCP 已有 OAuth”“工具带了只读标记”不等于它已经满足企业审批要求。身份认证回答“你是谁”,授权回答“你能访问什么”,Tool Approval 还要回答“这一次具体动作是否可以在此时、对此资源执行”。
如果正在搭建统一 Agent 治理体系,可结合 AI Stack Nav 的 MCP 安全教程检索 和 AI Agent 安全沙箱检索 一起设计,而不是把审批做成孤立插件。

四级审批模型:自动允许、一次确认、每次确认、禁止
结论:审批级别应该由“能力风险 × 调用上下文”共同决定。 同一个命令在开发容器和生产服务器上的风险完全不同;同一个文件读取动作,读取 README.md 与读取 .env 也不能共用规则。
| 级别 | 决策 | 典型动作 | 有效范围 | 企业要求 |
|---|---|---|---|---|
| L0 | 自动允许 | 工作区只读搜索、无网络测试、格式化检查 | 单次任务或受控会话 | 沙箱内、无 Secrets、可审计 |
| L1 | 会话一次确认 | 安装已锁定依赖、写入构建目录、访问批准域名 | 限时、限目录、限命令参数 | 显示影响范围,可随时撤销 |
| L2 | 每次人工确认 | 删除/覆盖、工作区外读取、Git push、可写 MCP、外发数据 | 仅批准当前调用 | 展示完整参数、差异、身份和目的 |
| L3 | 禁止或双人特批 | 生产删库、导出密钥、修改 IAM/MFA、关闭审计 | 不提供长期授权 | 独立审批、变更单、回滚与复核 |
“始终允许”不应是 L2/L3 操作的可选按钮。审批授权要绑定参数摘要、资源标识和短时间窗口,而不是只绑定工具名称。例如批准 git push origin agent/fix-123,不应同时授权 git push --force origin main;批准读取 ./src,不应扩展到用户主目录。
风险评分可以怎么计算
企业可把每次调用拆成七个维度:动作是否写入、是否可逆、环境是否生产、目标是否敏感、是否出网、令牌权限多大、输入是否来自不可信内容。审批等级取最高风险项,而不是取平均值。一个只读动作如果同时读取私密源码并向外部 API 发送,也必须升级到 L2 或禁止。
推荐使用“污染传播”规则:只要当前任务读取了网页、Issue、邮件、第三方代码或用户上传文件,就把会话标记为 untrusted_input=true。在该状态下,任何同时具备“读取私密数据”和“向外发送”能力的路径都需要强制阻断或人工批准。MCP 官方博客也把 reads_private_data、sees_untrusted_content、can_exfiltrate 这类标注视为风险词汇,但注解只能提供信号,不能被当作可信授权本身。
Shell 操作:哪些命令可以自动执行
结论:Shell 审批必须解析真实执行链,不能只匹配第一段字符串。 bash -c、管道、重定向、命令替换、脚本文件、别名和解释器都能把危险动作藏在看似安全的前缀后面。
建议自动允许的低风险命令
在受限工作区、无网络、无提权的条件下,可自动允许:
pwd、ls、find、rg、git status、git diff等只读检查;- 锁定依赖后的本地编译、静态分析和单元测试;
- 向
.tmp/、dist/、测试报告目录写入可重新生成的产物; - 读取项目内非敏感配置模板,如
.env.example; - 由企业封装的只读脚本,且脚本内容、哈希和参数范围都已登记。
自动允许的测试命令也要有 CPU、内存、进程数、磁盘和超时限制,防止死循环、Fork Bomb 或无限日志。测试框架可能执行仓库内恶意脚本,因此首次运行陌生项目的 npm test、pip install 或构建脚本,不能因为命令名称常见就直接视为安全。
必须每次批准的 Shell 动作
sudo、su、管理员 PowerShell、修改系统服务与防火墙;rm、rmdir、覆盖重定向、批量移动、磁盘与文件系统工具;curl、wget、ssh、scp、rsync、任意外网请求和反向连接;pip install、npm install、brew install、apt等会下载或执行安装脚本的命令;docker run挂载主机目录、特权容器、宿主网络、Docker Socket;kubectl apply/delete/exec、Terraform apply/destroy、云 CLI 写操作;- 读取环境变量、系统凭据目录、浏览器配置、SSH/GPG 密钥;
- 运行来自互联网、Issue、邮件或生成内容的脚本。
原则上禁止的命令模式
禁止规则应覆盖语义而不只是文本:递归删除广泛路径、清空磁盘、修改审计日志、上传 Secrets、关闭 EDR、防火墙或分支保护、在生产环境执行未限定条件的数据库删除。禁止项不得通过用户点击“一直允许”绕过;若业务确实需要,应转为独立变更流程并使用专门受控工具。
文件操作:读取、修改、删除分别审批
结论:文件权限应以规范化后的真实路径为准,并防御软链接、路径穿越与大小写差异。 仅检查输入字符串包含 /workspace 不够,因为 ../、符号链接和挂载点可能逃出工作区。
| 文件动作 | 默认策略 | 需要升级审批的条件 |
|---|---|---|
| 读取项目源码 | L0 | 仓库被标记为机密、任务含外发工具 |
| 读取配置模板 | L0 | 文件可能含真实 Token、Cookie 或账号信息 |
读取 .env、密钥、凭据缓存 |
L2/L3 | 原则上交由凭据代理,不直接展示给模型 |
| 新建项目文件 | L0/L1 | 超出允许扩展名、体积或目录配额 |
| 修改已有源码 | L0/L1 | 关键认证、支付、安全策略、CI 配置升级为 L2 |
| 覆盖二进制或锁文件 | L2 | 依赖供应链与可复现性风险 |
| 删除临时产物 | L1 | 必须验证路径和可恢复性 |
| 删除源码、备份或工作区外文件 | L2/L3 | 不可恢复或范围不明确时禁止 |
企业应强制 Agent 在写入前生成差异预览,在删除前列出精确文件清单、数量、总大小和恢复方式。批量操作的批准应绑定清单哈希;文件列表一旦变化,原审批立即失效。对认证、支付、权限、加密、CI/CD 和基础设施代码,建议增加 CODEOWNERS 或专门安全评审,不因 Agent 已获得文件写权限而跳过。
Git、PR、CI/CD 与发布操作
结论:本地提交与远程变更必须分开授权。 git commit 在隔离分支中通常可回滚,而 git push --force、合并 PR、发布 Release 或触发生产部署会影响共享系统。
- 自动允许:
git status、git diff、读取日志、在临时分支创建本地提交。 - 会话确认: 创建普通工作分支、推送到 Agent 专属命名空间、运行只读 CI 查询。
- 每次确认: 向远程推送、创建 PR、修改工作流文件、触发部署、发布包、创建 Release、添加标签。
- 禁止或双人审批: 强推受保护分支、绕过必需检查、修改分支保护、批准自己的 PR、替换发布制品、删除仓库或环境。
审批页面应显示目标仓库、基础分支、提交列表、文件差异、CI 状态、使用的机器人身份和将触发的工作流。企业令牌只授予当前仓库与必要 API Scope;GitHub MCP 默认只读当前仓库的思路值得借鉴,但一旦更换更宽权限 Token,风险边界也随之扩大。
MCP 操作:不能只看工具名和注解
结论:MCP Tool Approval 的最小对象是“服务器身份 + 工具版本 + 参数 + 资源 + Token Scope + 数据流向”。 send_message、create_issue、query_database 这些名称并不能说明实际副作用;服务器升级后,同名工具的行为也可能变化。
MCP 规范允许服务端暴露可由模型自动发现和调用的工具,但没有规定必须弹出批准界面。GitHub Copilot Cloud Agent 的官方文档进一步说明,仓库配置的 MCP 工具可被 Agent 自主使用且不逐次请求批准。因此企业应在 MCP Gateway、服务端或身份提供方实施不可绕过策略,而不是依赖客户端 UI。
MCP 工具分类建议
- 只读查询: 限定数据集、字段和行数,可在脱敏后 L0/L1 运行。
- 内部写入: 创建草稿、Issue 或测试记录,通常 L1/L2。
- 外部通信: 发邮件、群消息、Webhook、CRM 更新,必须 L2。
- 资金与权限: 下单、退款、云资源采购、IAM、MFA、共享权限,L3 或双人审批。
- 代码与基础设施: 合并 PR、部署、Kubernetes、数据库写入,按环境和可逆性至少 L2。
- 跨域组合: 同时读取私密数据并允许网络外传的工具链,默认阻断。
接入新的 MCP Server 时,应固定包版本或镜像摘要,验证发布者,读取工具 Schema,测试超时、错误与幂等行为,并分配专用短时 Token。企业可以采用 MCP Enterprise-Managed Authorization,通过 IdP 集中决定员工可访问的 MCP 服务并统一撤销;但集中授权仍不能替代逐调用的业务审批。
可落地的策略配置示例
结论:策略应声明式、版本化、可测试,并把拒绝规则放在最高优先级。 下面是厂商无关的示意 YAML,不代表某一产品可直接读取;实际接入时应映射到 Codex Rules、Claude Code 权限规则/Hook、MCP Gateway 或内部 Policy Engine。
policy_version: "2026-09-25"
default_decision: deny
context:
workspace_roots:
- "/workspace/repos"
production_environments:
- "prod"
- "production"
approved_egress_domains:
- "api.github.com"
- "registry.npmjs.org"
rules:
- id: deny-secret-export
match:
data_classes: [secret, credential, private_key]
destination: external
decision: deny
- id: approve-prod-write
match:
environment: production
effect: write
decision: require_two_person_approval
- id: ask-destructive-shell
match:
tool: shell
effects: [delete, overwrite, privilege_escalation]
decision: require_each_time
- id: allow-workspace-read
match:
tool: file
effect: read
path_within_workspace: true
data_classes: [public, internal]
decision: allow
- id: ask-mcp-write
match:
tool_type: mcp
effect: write
decision: require_each_time
limits:
max_runtime_seconds: 900
max_output_mb: 100
max_tool_calls: 80
max_retries: 2
审批系统解析调用时,应先把命令和路径规范化,再做 deny 检查,然后做资源、环境和数据分类,最后才允许更宽松规则命中。任何解析失败、参数缺失、工具版本变化、资源清单变化或策略服务不可用,都应 Fail Closed。
Claude Code Hook 的防护示例
下面示例展示如何在 PreToolUse 阶段阻断包含危险数据库语句的 Bash 调用。官方文档说明退出码 2 会阻止工具调用;退出 0 只代表 Hook 不反对,正常权限流程仍继续。
#!/usr/bin/env bash
set -eu
INPUT="$(cat)"
COMMAND="$(printf '%s' "$INPUT" | jq -r '.tool_input.command // ""')"
if printf '%s' "$COMMAND" | grep -Eiq \
'(^|[;&|[:space:]])(drop[[:space:]]+table|truncate[[:space:]]+table)'; then
echo "Blocked: destructive database command requires a change ticket" >&2
exit 2
fi
exit 0
这只是辅助防线,不应单独承担安全边界。字符串匹配会被编码、脚本包装、变量展开和其他客户端绕过;真正的数据库权限还应限制账号角色,让 Agent 身份根本没有生产 DDL 权限。
九步落地流程:从资产盘点到灰度上线
结论:先盘点 Agent 实际能调用什么,再写策略;从命令黑名单开始通常会遗漏更危险的业务工具。 推荐按以下步骤实施:
- 建立工具资产清单: 列出 Shell、文件、Git、浏览器、云 CLI、数据库、MCP、连接器、插件和子 Agent。
- 标注能力与数据: 为每个工具标记读/写/删除/外传/付费/权限变更,以及可访问的数据分类和环境。
- 定义身份: 为 Agent 创建专用账号、短时 Token 与最小 Scope,不复用开发者个人凭据。
- 建立四级矩阵: 把常见动作映射为 L0—L3,明确谁能批准、授权持续多久、能否委派。
- 设置硬边界: 启用沙箱、只读挂载、出口白名单、资源限制、分支保护和生产只读副本。
- 部署策略执行点: 在客户端规则、工具代理、MCP Gateway、CI/CD 和目标服务端多层执行,避免单点绕过。
- 设计审批界面: 展示自然语言目的、原始参数、目标、差异、敏感数据、凭据身份、风险理由和回滚方案。
- 红队与回归测试: 测试命令拼接、路径穿越、软链接、提示注入、工具改名、Token 提权、并发和重试。
- 灰度上线并复盘: 先在非生产仓库和少数团队运行,统计误拦截、漏拦截、审批时延和异常调用,再逐步扩大。

审批界面必须展示什么
结论:用户无法理解影响范围的确认框不是真正的知情批准。 “允许 Agent 使用 Bash?”信息量远远不够,审批者至少要看到以下内容:
- Agent 正在完成什么任务,当前步骤为什么需要该工具;
- 完整命令或 MCP 参数,不能只显示工具名;
- 工作目录、目标文件、仓库、分支、数据库、云项目与环境;
- 使用哪个身份和 Token Scope,权限何时过期;
- 是否读取敏感数据、是否出网、数据发送到哪个域名或租户;
- 将新增、修改、删除什么,提供 Diff 或资源计划;
- 是否可回滚,失败后由谁处理;
- 批准一次、批准本会话、拒绝和转交双人审批的区别。
审批者不应在高频低价值弹窗中被训练成机械点击。解决办法不是永久放行高风险工具,而是把低风险动作安全地移入 L0,把多个相关动作合并成一个有清晰边界的执行计划,并对 L2/L3 保持稀缺、具体的确认。
审计、幂等、超时与回滚
结论:只记录“用户点击了允许”远远不够。 完整审计链必须证明系统批准了什么、实际执行了什么、结果是什么,以及两者是否一致。
建议记录:任务 ID、会话 ID、Agent/模型版本、用户与审批人、策略版本、工具服务器和版本、原始参数的脱敏副本、规范化资源、风险标签、审批决定、理由、时间、令牌标识、执行结果、输出摘要、产生的文件 Diff、外部对象 ID 和回滚状态。Secrets 不写入日志,只记录引用与哈希。
所有写操作都应有幂等键,避免 Agent 重试时重复创建 Issue、重复付款、重复发送消息或重复部署。工具调用应设置超时、重试上限与退避;遇到不确定结果时先查询外部状态,而不是盲目重跑。审批过期、参数变化、代码 Diff 变化、Token Scope 扩大后必须重新批准。
回滚应在执行前生成,而不是故障后临时想办法。文件修改保留 Git Commit 或快照;数据库使用事务、备份或影子库;云资源采用 Plan/Apply 分离;发布使用可回退版本;外部通信则通过草稿、延迟发送或撤回窗口降低不可逆性。
常见错误与绕过方式
结论:最常见的失败是按工具名授权,而攻击者利用参数和组合路径改变工具语义。 企业测试至少覆盖以下案例:
- 白名单允许
python,但 Agent 用 Python 读取主目录并上传; - 允许
git,但通过 Git Hook、外部 Diff 驱动或子模块执行代码; - 路径检查允许工作区,软链接却指向
/etc或凭据目录; - 允许读取和允许联网分别看似安全,组合后形成数据外传;
- MCP 标注
readOnlyHint=true,服务端实现却发生写入; - 批准第一次调用后,Agent 修改参数重复重试;
- 使用宽权限个人 Token,使工具代理层的限制失去意义;
- Agent 在 PR 中修改审批策略、CI Workflow 或审计 Hook,从而关闭防线;
- 子 Agent、后台任务或非交互模式无法弹窗时默认为继续执行。
正确做法是将授权绑定到能力、参数和资源,并在目标系统再次执行权限校验。Claude Code 官方文档指出,后台子 Agent 在不能交互提示且没有 Hook 决定时会拒绝调用,这种 Fail Closed 行为适合作为企业默认模式。
选型建议:产品内审批、Gateway 还是自建策略引擎
结论:小团队可以从产品内规则开始,企业应把关键控制下沉到统一 Gateway 和目标系统。 客户端配置容易部署,但可能被用户修改,且难以覆盖云 Agent、MCP 与跨平台调用;统一策略层更便于集中治理、撤销和审计。
| 方案 | 优点 | 局限 | 适用范围 |
|---|---|---|---|
| 产品内审批规则 | 上手快、上下文贴近用户 | 各产品语法不同,可能无法集中强制 | 个人与小团队开发环境 |
| Shell/工具代理 | 可统一解析命令与网络出口 | 需要维护代理与资源映射 | 多种本地 Coding Agent |
| MCP Gateway | 统一身份、工具清单、Scope 与审计 | 只覆盖经过 Gateway 的 MCP 调用 | 企业 MCP 生态 |
| CI/CD 与目标系统控制 | 最接近真实资产,难以绕过 | 上下文体验较弱,需多系统集成 | 生产发布、云与数据库 |
| 统一 Policy Engine | 跨 Agent 一致、可测试和版本化 | 建设与运营成本最高 | 中大型企业、强合规场景 |
最佳实践不是五选一,而是纵深防御:客户端提供可理解的交互,Gateway 执行统一策略,目标系统实施最小权限,审计平台汇总证据。更多企业治理方案可以参考 AI Stack Nav 的 Coding Agent 安全检索。
事实依据与来源
OpenAI 官方文档确认 Codex 本地采用操作系统强制沙箱与审批策略,默认网络关闭;Codex Rules 可对沙箱外命令前缀设置 prompt 等决策,但官方同时标注 Rules 仍为实验性能力。Anthropic 官方文档确认 Claude Code 具有 allow、ask、deny 权限规则,并能用 PreToolUse Hook 做 allow、deny 或 ask 决策;Hook 的允许不能覆盖更高优先级的 deny/ask 与企业受管规则。
GitHub 官方文档确认 Copilot Cloud Agent 配置的 MCP 工具可被自主调用且不会逐次询问,并说明默认 GitHub MCP 使用只读当前仓库的特定范围 Token。MCP 官方规范确认协议没有强制统一的用户交互模型;Enterprise-Managed Authorization 扩展则提供通过企业 IdP 集中控制 MCP Server 访问与撤销的方案。
本文的四级审批矩阵、风险评分、YAML 结构、九步落地流程和审计字段属于编辑实施建议,不是任何一家厂商的统一标准。本文未进行第三方性能测试,也没有声称某一 Coding Agent 的安全性绝对高于另一家。企业仍需结合产品版本、部署方式、操作系统、现有 IAM、数据分类与合规要求进行验证。
FAQ
所有 Shell 命令都应该人工批准吗?
不应该。工作区内只读检索、无网络的测试和静态检查可以在沙箱与资源限制下自动执行;把所有命令都弹窗会造成审批疲劳。真正需要每次确认的是提权、删除、覆盖、出网、安装依赖、云与生产操作,以及解析器无法确定实际行为的复合命令。
git commit 和 git push 应该使用同一审批级别吗?
不应相同。隔离分支中的本地 Commit 通常可回滚,可以 L0/L1;Push 会改变远程共享状态并可能触发 CI/CD,至少应 L1/L2。向受保护分支强推、合并 PR、修改分支保护或发布 Release 应每次批准或双人审批。
只读 MCP 工具可以自动允许吗?
只有在服务端可信、工具版本固定、Token Scope 最小、返回数据已分级且不存在外传组合路径时才可以。MCP 注解是提示而非强制保证,企业 Gateway 应根据真实调用、身份与数据流重新判定风险。
OAuth 已经授权,为什么还要 Tool Approval?
OAuth 主要解决身份和 Scope,不能判断本次动作的业务意图、参数、目标环境和不可逆后果。一个具有 repo:write Scope 的合法 Token 仍可能被 Agent 用来错误推送、修改 Workflow 或泄露数据,因此写操作仍需要逐调用策略。
是否可以允许 Agent 读取 .env 后自动调用服务?
不建议把 .env 明文交给模型。更安全的方式是由凭据代理向具体工具注入短时令牌,模型只看到凭据引用;审批系统记录使用哪个身份和 Scope,但不记录或展示 Secret 本身。
人工批准后是否可以跳过沙箱?
不可以。批准表示某个受限动作在当前上下文中被接受,不代表取消文件、网络、资源和身份边界。沙箱和最小权限应始终存在,审批只是在硬边界内释放精确能力。
非交互 Agent 无法弹窗时怎么办?
默认应拒绝需要批准的调用,将请求转入审批队列,批准后凭短时授权恢复任务。不能因为是夜间自动任务、后台子 Agent 或 CI 环境就自动放行高风险操作;无法获得明确决定时必须 Fail Closed。
Tool Approval 会不会严重拖慢开发?
设计不当会。降低摩擦的正确办法是安全地扩大低风险 L0 范围、提供批量计划审批、缩短审批信息、设置明确责任人,而不是永久授权删除、外传和生产写入。应持续统计审批时延、误拦截率和高风险调用量来优化规则。
如何验证审批规则没有被绕过?
建立自动化策略测试与红队用例,覆盖命令拼接、解释器包装、软链接、路径穿越、参数变化、MCP 工具改名、提示注入、并发重试和 Token 提权。每次策略、Agent、MCP Server 或工具版本更新后都重新执行回归测试。
参考来源
- OpenAI:Codex Agent approvals & security
- OpenAI:Codex Rules
- Anthropic:Claude Code 设置与权限规则
- Anthropic:Claude Code Hooks 指南
- GitHub:MCP 与 Copilot Cloud Agent
- Model Context Protocol:Tools 规范
- Model Context Protocol:Enterprise-Managed Authorization
- Model Context Protocol Blog:Tool Annotations as Risk Vocabulary
内容核验日期:2026 年 09 月 25 日
会员充值与订阅排查资料
适合阅读会员充值、订阅购买、权益对比和支付问题类文章后继续转化。