办公

敏感目录别让 Agent 自动改:大功能拆成 ticket 级任务、每步人工确认

👤 为我痴狂 👁 1 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-13
首页› 首页› 办公› 正文
敏感目录别让 Agent 自动改:大功能拆成 ticket 级任务、每步人工确认

从权限边界、任务粒度到确认闸门——一套让自主编码代理在关键路径上"可控、可审、可回滚"的工程方法论

摘要

随着 Claude Code、Codex CLI、Cursor Agent、Aider、OpenHands 等自主编码代理进入日常研发流程,"让 Agent 自动改代码"已从演示走向生产。但一个被反复低估的事实是:代码库里真正危险的不是"难改"的文件,而是"改错代价极高"的敏感目录——数据库迁移脚本、CI/CD 流水线、密钥与配置、基础设施即代码(IaC)、发布清单、权限策略。这些路径一旦被代理在无人确认的情况下批量改写,故障半径往往从单次构建扩散到线上事故。

本文提出一条贯穿全文的分析主线:把"是否允许自动修改"从二元开关,重构为"按路径风险分级 + 按任务粒度拆分 + 按步骤设置确认闸门"的三维控制面。围绕这条主线,文章依次讨论敏感目录的风险建模、ticket 级任务拆分方法、人工确认闸门的设计与实现、权限与沙箱的工程落地、审计与回滚机制,并给出可复制的操作路径与前沿研判。

本文评述:现有工具大多把安全寄托在"模型足够聪明"或"提示词足够严格"上,这在工程上是不可靠的;真正可验证的安全来自结构化的流程约束——即让危险操作在物理上无法绕过人工确认,而不是寄希望于模型"自觉"。

一、问题重定义:为什么"敏感目录"是 Agent 安全的核心战场

1.1 从"辅助补全"到"自主执行"的范式跃迁

2021 年前后,代码补全工具的工作模式是"人写、模型猜"。GitHub Copilot 的早期形态本质上是上下文感知的下一 token 预测,模型没有文件系统写权限,也没有执行 shell 的能力。到 2024—2025 年,情况发生了质变:Claude Code、OpenAI Codex CLI、Cursor 的 Agent 模式、Aider、OpenHands、Devin 等工具获得了读写文件、执行命令、运行测试、提交 Git 的完整能力。SWE-bench 这类基准的分数也印证了能力跃迁——从 2023 年的个位数解决率,到 2024 年 SWE-bench Verified 上多个系统突破 50%(数据来源:SWE-bench 官方排行榜,2024—2025)。

能力越强,破坏力越大。一个能自动重构 200 个文件的代理,同样能在无人察觉的情况下把 .github/workflows/deploy.yml 里的生产环境部署条件改掉,或者把 migrations/ 下的历史迁移文件"顺手整理"一遍。本文评述:代理的能力曲线和风险曲线是同一条曲线,把能力当卖点而把风险当脚注,是当前很多团队的真实状态。

1.2 敏感目录的定义:不是"难改",而是"改错代价高"

工程上常有一个误区:把"复杂代码"等同于"敏感代码"。实际上,敏感性的判据不是修改难度,而是修改错误的后果不可逆程度。一段 2000 行的业务逻辑写错了,测试会挂、CI 会红、回滚一次提交即可;但一个数据库迁移文件写错了,可能已经对生产库执行了 DROP COLUMN,数据没了就是没了。

笔者认为,可以用一个简单的三要素来刻画敏感度:可逆性(Reversibility)× 影响半径(Blast Radius)× 触发时机(Trigger Timing)。可逆性越低、影响半径越大、触发时机越接近生产,敏感度越高。这个模型比"按目录名硬编码黑名单"更可扩展,也更容易向团队解释。

1.3 真实事故模式:代理"越权"的典型路径

综合公开的社区讨论、GitHub Issue 与安全研究(如 OWASP 2025 年发布的 Agentic AI 威胁建模草案),代理越权修改敏感路径的典型模式可以归纳为几类:

  • 任务泛化:用户说"修复登录 bug",代理为了"彻底解决",顺手改了认证中间件、会话配置和 CI 里的密钥注入方式。
  • 测试驱动越界:为了让测试通过,代理修改了测试配置、mock 数据甚至断言本身,而不是修业务代码。
  • 依赖升级连锁:升级一个库时,代理自动改了 lockfile、Dockerfile 基础镜像和部署脚本。
  • "清理"冲动:代理认为某些"看起来没用"的文件是死代码,删除后才发现是运行时动态加载的迁移或配置。

本文评述:这些模式的共同点是——代理在"局部目标"上是对的,在"全局边界"上是错的。它没有恶意,它只是缺少一个明确的、机器可执行的边界。这正是本文主张用结构化流程而非提示词来约束的根本原因。

二、风险建模:敏感目录的分级分类与故障半径分析

2.1 敏感路径的四级分类

为了让"是否允许自动修改"可操作,需要把路径映射到离散的风险等级。下表给出一套可直接落地的四级分类(模拟整合自多个团队实践与 OWASP Agentic 威胁模型,非单一来源):

等级 典型路径 可逆性 影响半径 Agent 策略
L0 只读 文档、注释、README 高 极小 可自动改,事后 review
L1 低危 业务代码、单元测试 高 局部 可自动改,PR 必审
L2 高危 lockfile、Dockerfile、构建脚本、依赖清单 中 构建/发布链 改前必须人工确认
L3 致命 迁移脚本、CI/CD 生产配置、密钥、IaC、权限策略 低 生产/数据/安全 禁止自动改,仅允许"提议+人工执行"

本文评述:这个分级的关键在于 L3 不是"更严格的 L2",而是性质不同的类别。L2 允许代理"改完等确认",L3 只允许代理"产出补丁草案,由人落地"。把 L3 降级为"改完再确认"是很多团队踩坑的根源——因为一旦代理已经写入文件,确认就变成了"事后追认",心理上更容易被放行。

2.2 故障半径:为什么"小改动"可能引发"大事故"

故障半径(Blast Radius)是 SRE 领域的经典概念,指一次故障影响的用户、服务或数据的范围。在 Agent 场景下,它有一个特殊之处:代理的改动会沿着自动化管道被放大。一个被改错的 CI 配置,会在下一次 push 时自动触发部署;一个被改错的迁移文件,会在下次启动时自动执行。

可以用一个简化的传播模型来理解:设改动点的影响半径为 R₀,管道放大系数为 k(CI/CD 自动执行、定时任务、webhook 等),则实际故障半径 R ≈ R₀ × k。敏感目录之所以敏感,正是因为它们处在 k 值极高的位置——它们本身就是放大器。

工程直觉:修改一个业务函数,影响的是"这次请求";修改一个部署脚本,影响的是"以后每一次部署"。敏感目录的可怕之处在于它把一次错误固化成了持续性的错误。

2.3 敏感度评分卡:把直觉变成可计算指标

为了让分级不依赖个人经验,可以设计一个评分卡。以下为笔者整合的评分维度(模拟模型,供团队按自身情况校准):

  • 可逆性得分(0—3):能否用 git revert 完全恢复?涉及外部副作用(已执行迁移、已推送镜像)得 0 分。
  • 影响半径得分(0—3):仅本地 / 单服务 / 多服务 / 生产数据与安全。
  • 触发时机得分(0—3):手动触发 / PR 触发 / 合并触发 / 定时或事件自动触发。
  • 审计要求得分(0—3):是否需要合规留痕、双人复核、变更审批。

四项加总后映射到 L0—L3。本文评述:评分卡的价值不在于精确,而在于把"这个目录能不能自动改"从争论变成可复现的计算,从而写进配置、写进 CI、写进 Agent 的系统提示。

三、核心方法:把大功能拆成 ticket 级任务

3.1 为什么"大功能一次交给 Agent"必然失控

把一个完整功能(如"实现用户注册与登录")一次性交给代理,会同时触发三个问题:上下文超载、边界模糊、确认点缺失。上下文超载导致代理在长链路中丢失早期约束;边界模糊导致它无法判断哪些文件"不该碰";确认点缺失导致人只能在最后看到一个巨大的 diff,review 成本高到形同虚设。

这与软件工程里的经典结论一致:变更规模与缺陷率正相关。DORA 的多年研究报告反复指出,小批量(small batch)变更的交付质量显著优于大批量变更(数据来源:DORA《Accelerate State of DevOps Report》系列,2018—2024)。把这条结论迁移到 Agent 场景,就是本文的核心主张:ticket 级拆分不是管理动作,而是安全机制。

3.2 ticket 级任务的定义与粒度标准

本文把"ticket 级任务"定义为满足以下全部条件的任务单元:

  1. 单一目标:一个任务只解决一个可验证的问题,能用一句话描述完成标准。
  2. 路径封闭:明确列出允许修改的文件/目录白名单,白名单外一律只读。
  3. 可独立验证:有对应的测试、lint 或检查命令,能自动判定成败。
  4. 可独立回滚:对应一个原子提交,回滚不影响其他任务。
  5. 风险等级已知:映射到 L0—L3,决定是否需要人工确认闸门。

粒度上,笔者建议以"一次提交能讲清楚"为经验上限。如果一个任务的 diff 超过约 400 行或涉及超过 10 个文件,就应当继续拆分。这个数字不是硬性标准,而是一个提醒阈值——超过它,review 质量会显著下降。

3.3 拆分方法论:从功能到 ticket 的四步法

以下四步法可直接操作:

第一步:功能分解为能力单元。把"用户注册登录"拆成:数据模型、注册接口、登录接口、密码哈希、会话管理、错误处理、测试。每个能力单元对应一个或多个 ticket。

第二步:为每个单元标注路径与风险。例如"数据模型"涉及 migrations/(L3),"密码哈希"涉及 src/auth/(L1)与密钥配置(L3)。

第三步:按依赖排序,形成 DAG。迁移必须先于接口,接口先于集成测试。用依赖图而非线性列表,避免代理"跳步"。

第四步:为每个 ticket 写"完成定义"(DoD)。包括:允许改的路径、必须通过的检查、需要人工确认的步骤、回滚方式。

下面是一个 ticket 的 YAML 描述示例,可直接作为 Agent 的输入契约:

id: TICKET-042
title: "为 users 表新增 email_verified 字段"
risk_level: L3
allowed_paths:
  - migrations/2025xxxx_add_email_verified.sql   # 仅允许新建此文件
readonly_paths:
  - "**/*"
forbidden_actions:
  - "修改任何已存在的 migration 文件"
  - "执行数据库命令"
definition_of_done:
  - "生成一个新的 migration 文件,包含 up/down"
  - "down 能完整回滚 up"
  - "通过 lint: sqlfluff"
requires_human_approval: true
approval_gate: "before_write"   # 写文件前确认,而非写完后确认
rollback: "删除新增文件即可,无外部副作用"

本文评述:approval_gate: before_write 是这套设计里最关键的一行。它把确认点从"事后追认"前移到"事前授权",从机制上消除了"代理已经改了,人不好意思回退"的心理压力。

3.4 与现有工具链的对接

这套拆分方法并不需要自研 Agent。它可以作为一层"编排契约"叠加在现有工具之上:

  • 用 Claude Code 的 CLAUDE.md 与权限设置声明路径白名单;
  • 用 OpenHands 的 sandbox 与 runtime 配置限制可写目录;
  • 用 Aider 的 --read / --no-auto-commits 控制自动提交;
  • 用 GitHub Actions 的 required reviewers 作为 L3 的强制闸门。

拓展阅读:OpenHands 官方文档的 runtime 与 sandbox 章节(docs.all-hands.dev)、Aider 的配置文档(aider.chat/docs/config.html)、GitHub 关于 environment protection rules 的说明(docs.github.com),都值得对照本文方法阅读。

四、确认闸门:每步人工确认的工程实现

4.1 确认闸门的三种时机

"人工确认"不是一句口号,它必须落到具体时机。工程上有三种可选闸门:

闸门类型 触发点 优点 风险
事前(before_write) 写文件前 零副作用,最安全 打断频率高
事中(before_commit) 提交/推送前 可看完整 diff 本地已写入,需清理
事后(before_merge) 合并/部署前 批量确认,效率高 依赖 PR 流程,易被绕过

本文评述:L3 必须用事前闸门,L2 可用事中,L1 用事后即可。把三种闸门按风险等级组合,才能在安全与效率之间取得平衡。全部用事前会让代理寸步难行,全部用事后等于没有闸门。

4.2 事前确认的实现:拦截写操作

事前确认的技术核心是在文件系统写入路径上插入拦截层。常见做法有三种:

  1. 工具层拦截:在 Agent 的 tool 定义里,把 write_file 包装成一个需要审批的函数,命中敏感路径时返回"待审批"而非直接写入。
  2. 文件系统层拦截:用只读挂载 + 临时可写目录(overlay)的方式,让敏感目录在物理上不可写,代理的写入落到 overlay,人工确认后再合并。
  3. Git 层拦截:用 pre-commit hook 或 pre-push hook 检查暂存区是否包含敏感路径,命中则阻断并要求显式 --approve。

其中文件系统层拦截最可靠,因为它不依赖 Agent 是否"配合"。下面是一个基于 git 的 pre-commit 检查示例:

#!/usr/bin/env bash
# .git/hooks/pre-commit  敏感路径拦截
SENSITIVE_REGEX='^(migrations/|\.github/workflows/|infra/|secrets/|.*\.tf$)'
STAGED=$(git diff --cached --name-only)

if echo "$STAGED" | grep -Eq "$SENSITIVE_REGEX"; then
  echo "⛔ 检测到敏感路径变更:"
  echo "$STAGED" | grep -E "$SENSITIVE_REGEX"
  echo "请使用 APPROVE_SENSITIVE=1 git commit 显式确认"
  [ "$APPROVE_SENSITIVE" = "1" ] || exit 1
fi
exit 0

本文评述:这个 hook 的设计要点是"默认阻断,显式放行"。它不判断改动是否正确,只判断"是否越过了需要人看一眼的边界"。这种"哑但可靠"的机制,比任何基于 LLM 的智能审查都更适合作为最后一道防线。

4.3 确认疲劳:如何避免"点同意点到麻木"

人工确认最大的敌人是确认疲劳(approval fatigue)。当确认弹窗过多,人会条件反射地点"同意",闸门形同虚设。这是安全领域的老问题,在 Agent 场景下被放大——因为代理可以在一分钟内产生几十次写操作。

缓解策略包括:

  • 批量确认:把同一 ticket 内的多次写操作聚合成一次确认,展示合并 diff。
  • 分级展示:L3 展示完整 diff 并要求输入确认短语;L2 只展示摘要;L1 静默通过。
  • 限流:对同一路径单位时间内的确认次数设上限,超过则强制暂停并提示"可能存在异常循环"。
  • 差异化确认:删除操作比新增操作要求更强的确认(如输入文件名)。

笔者认为,确认机制的设计目标不是"让每一次改动都被看到",而是让真正危险的改动无法被忽略。前者不可持续,后者可以长期运行。

五、权限与沙箱:让危险操作在物理上无法绕过确认

5.1 最小权限原则在 Agent 场景的落地

最小权限(Principle of Least Privilege)是安全领域的基石。在 Agent 场景下,它的落地方式是:给代理的权限,应当恰好等于当前 ticket 所需的最小集合,而不是"整个仓库的读写权限"。

具体做法:为每个 ticket 生成一个临时工作区(worktree 或容器),只挂载该 ticket 的 allowed_paths 为可写,其余为只读。任务结束后销毁工作区。这样即使代理"想越界",也没有物理权限。

5.2 沙箱方案对比

方案 隔离级别 适用场景 成本
Git worktree 文件级 纯代码修改 低
容器(Docker) 进程/文件级 需执行命令、装依赖 中
微虚拟机(Firecracker/gVisor) 内核级 不可信代码执行 高
远程沙箱(E2B 等) 云端隔离 团队协作、可复现 按量计费

本文评述:沙箱不是"更安全的确认",而是"确认的前提"。没有沙箱,代理的一次误操作可能直接污染工作区,让后续确认失去意义。建议至少从容器级隔离起步。

5.3 网络与密钥的隔离

敏感目录之外,还有两类资源必须隔离:网络出口与密钥。代理在调试时可能尝试访问外部 API、拉取依赖、甚至把代码片段发到外部服务。工程上应做到:

  • 默认关闭网络出口,仅放行必要的包管理器域名(白名单)。
  • 密钥不注入沙箱环境变量,改用短期凭证或代理网关。
  • 禁止代理读取 .env、~/.ssh、云凭证目录。

拓展阅读:OWASP 的 Agentic AI 安全项目(genai.owasp.org)与 NIST AI 风险管理框架(nist.gov)提供了系统的威胁清单,可作为团队自查表。

六、审计、回滚与可观测性

6.1 审计日志:记录"谁在何时批准了什么"

审计的目标不是"记录代理做了什么",而是记录人对代理行为的授权链。一条合格的审计记录应包含:ticket ID、代理标识与版本、模型与提示词哈希、涉及路径、diff 摘要、确认人、确认时间、确认方式(点击/输入短语/双人复核)、回滚点。

这套记录可以直接落到 Git 提交信息或独立的审计库中。关键要求是不可篡改——可用 append-only 存储或签名提交(GPG signed commit)。

6.2 回滚策略:分级设计

风险等级 回滚方式 恢复时间目标
L0/L1 git revert 分钟级
L2 revert + 重新构建/发布 十分钟级
L3 预置 down 脚本 + 数据备份 + 人工演练 小时级,需预案

本文评述:L3 的回滚能力必须在改动之前就验证过。一个没演练过的 down 脚本,等于没有回滚。建议把"回滚演练"作为 L3 ticket 的 DoD 之一。

6.3 可观测性指标

为了让这套流程持续改进,需要监控几个指标(模拟建议,团队可按需调整):

  • 越界尝试率:代理尝试写白名单外路径的次数 / 总写操作。反映提示词与契约质量。
  • 确认拒绝率:人工拒绝的比例。过低说明确认流于形式,过高说明拆分或提示词有问题。
  • 平均确认延迟:从代理请求确认到人响应的时间。过长会拖慢迭代。
  • 回滚率:被回滚的 ticket 占比。反映任务拆分与验证的有效性。

七、完整操作路径:从零搭建一套受控 Agent 工作流

7.1 阶段一:盘点与分级(1—2 天)

  1. 列出仓库中所有"改错代价高"的路径,用第 2 节的评分卡打分。
  2. 把结果写成一个机器可读的配置文件(如 .agent-policy.yml),纳入版本控制。
  3. 与团队评审,确认分级无遗漏。

7.2 阶段二:搭建拦截层(2—3 天)

  1. 部署 pre-commit / pre-push hook,实现敏感路径阻断。
  2. 为 Agent 配置只读挂载 + 可写 overlay 的沙箱环境。
  3. 在 Agent 的工具层包装 write_file,命中 L3 时返回"待审批"。

7.3 阶段三:定义 ticket 契约(持续)

  1. 为每个功能写 ticket 拆分,落到 YAML 契约。
  2. 每个 ticket 明确 allowed_paths、DoD、approval_gate、rollback。
  3. 把契约作为 Agent 的输入,而非口头指令。

7.4 阶段四:运行、度量与迭代

  1. 按 6.3 的指标监控运行情况。
  2. 每月复盘:哪些 L3 被误判为 L2?哪些确认被证明多余?
  3. 根据复盘调整分级与闸门,形成闭环。

本文评述:这套路径的关键在于先有拦截,再有自动化。很多团队反过来——先让代理全速跑,出事后再补闸门,结果补的闸门总是滞后于新的越界方式。

八、前沿研判与开放问题

8.1 从"人工确认"到"可验证授权"

当前的人工确认本质是"信任人的判断"。前沿方向是可验证授权(verifiable authorization):让代理在请求确认时,同时提交一份机器可验证的证明——例如"本次改动满足 ticket 契约中的所有约束"的形式化证明或属性测试结果。人只需验证证明,而非逐行读 diff。

相关研究可参考形式化方法与 LLM 结合的工作,以及 2024—2025 年关于"LLM 代码生成的可验证性"的讨论(如属性测试、差分测试、符号执行辅助)。本文评述:这条路很长,但方向正确——把人的注意力从"看代码"转移到"验证约束",是应对代理产出规模爆炸的唯一可持续方式。

8.2 多代理协作下的权限传播

当多个代理协作(一个规划、一个编码、一个测试),权限如何在它们之间传播?如果规划代理能"授权"编码代理写敏感路径,那么闸门就被绕过了。这需要权限不可传递的设计:任何代理都不能把自身没有的权限授予其他代理。这是经典的"能力(capability)安全"思想在 Agent 场景的回归。

8.3 开放问题

  • 如何自动发现"未被列入黑名单但实际敏感"的路径?
  • 确认疲劳的量化阈值是多少?是否有可测量的"安全确认上限"?
  • 当代理能力持续提升,人工确认是否会成为不可承受的瓶颈?
  • 如何在开源协作场景下,让外部贡献者的代理也遵守同一套闸门?

这些问题目前没有定论,但它们的共同指向是:Agent 安全不是模型问题,而是系统工程问题。

九、结语

让 Agent 自动改代码,是效率的巨大跃迁;让 Agent 自动改敏感目录,是风险的巨大跃迁。两者之间没有中间地带,只有结构化的边界。

本文的主线可以浓缩为一句话:按路径分级、按 ticket 拆分、按步骤设闸门。分级让风险可见,拆分让变更可控,闸门让授权可审。三者叠加,才能在享受代理效率的同时,守住生产与数据的底线。

笔者认为,未来一两年,这套方法会从"最佳实践"变成"默认配置"——就像今天的代码审查和 CI 一样,不再有人讨论"要不要做",只讨论"怎么做得更好"。

主要参考文献

[1] OWASP. Agentic AI Threats and Mitigations (Draft). 2025. https://genai.owasp.org/

[2] NIST. Artificial Intelligence Risk Management Framework (AI RMF 1.0) and Generative AI Profile. 2023—2024. https://www.nist.gov/itl/ai-risk-management-framework

[3] DORA. Accelerate State of DevOps Report. 2018—2024. https://dora.dev/

[4] Jimenez C E, et al. SWE-bench: Can Language Models Resolve Real-World GitHub Issues? ICLR 2024. https://www.swebench.com/

[5] Anthropic. Claude Code Documentation: Permissions, Hooks, and CLAUDE.md. 2025. https://docs.anthropic.com/

[6] OpenHands (All Hands AI). Runtime, Sandbox and Security Documentation. 2025. https://docs.all-hands.dev/

[7] Aider. Configuration and Safety Options. 2024—2025. https://aider.chat/docs/config.html

[8] GitHub. Using Environments for Deployment and Required Reviewers. 2024—2025. https://docs.github.com/en/actions/deployment/

[9] Saltzer J H, Schroeder M D. The Protection of Information in Computer Systems. Proceedings of the IEEE, 1975.(最小权限与能力安全经典)

[10] 其他参考:Google SRE Book(故障半径与变更管理)、SLSA 供应链安全框架、Sigstore 签名提交、E2B/Firecracker 沙箱文档、以及 2023—2025 年关于 LLM Agent 安全与可验证代码生成的会议论文与预印本(NeurIPS/ICLR/ICSE 相关方向)。

说明:本文涉及的数据集与指标(如评分卡、监控指标)为整合性/模拟模型,用于说明方法,非来自单一实测来源;引用时请以原始文献为准。

文章声明

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

内容仅供学习参考。如需引用,请以原始文献为准。  |  全文约 12600 字  |  参考文献 60+ 篇(主要 10 篇)
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷