首页
All Posts

Claude Code 工程化实战(三):安全与质量控制:Hooks、Rules、Tools 与 MCP

这张图把安全与质量控制画成一套工程安检门:Tools 是可调用能力,Rules 是通行规则,Hooks 是执行前后的检查点,MCP 是通往外部系统的受控接口。这个画面的含义是:Agent 越能干,越需要清晰边界。安全控制不是让它慢...

安全与质量控制安检门

这张图把安全与质量控制画成一套工程安检门:Tools 是可调用能力,Rules 是通行规则,Hooks 是执行前后的检查点,MCP 是通往外部系统的受控接口。这个画面的含义是:Agent 越能干,越需要清晰边界。安全控制不是让它慢下来,而是让它在高速行动时不越界。

一、真正的风险来自“能行动”

语言模型只输出文本时,风险主要是误导和幻觉;Agent 能读写文件、运行命令、访问外部系统后,风险就变成了真实副作用。它可能改错文件、删除数据、泄露密钥、提交未验证代码、调用错误环境的接口,或者在不了解业务约束的情况下修出新的问题。

因此,安全与质量控制不能只靠一句“请谨慎”。自然语言提醒适合表达意图,但不适合承担边界控制。工程系统需要把风险拆成可执行的层次:哪些工具能用,哪些动作要确认,哪些路径禁止修改,哪些变更必须验证,哪些外部调用必须审计。

这也是为什么 Tools、Rules、Hooks、MCP 要放在一起看。Tools 决定 Agent 能做什么,Rules 决定它应该怎样做,Hooks 决定关键动作是否能过关,MCP 决定它能连接到多远的外部世界。

二、Tools:给能力之前先分级

不是所有工具风险都一样。读文件、搜索代码、运行测试、修改文件、执行 Bash、连接数据库,这些动作的破坏半径完全不同。如果把它们都当成“工具”,安全设计就会过于粗糙。

可以按风险分成四档。

风险档位典型工具主要风险控制方式
低风险读文件、搜索、查看 diff泄露或误读信息限定工作区,避免敏感目录
中风险修改文件、格式化、生成资产改错范围、引入噪声要求 diff 检查,限定路径
高风险Bash、删除、批量替换、安装依赖不可逆副作用、环境污染命令白名单、人工确认、沙箱
外部风险GitHub、数据库、云服务、工单系统数据泄露、越权操作最小权限、审计日志、只读优先

在实际使用中,最容易出问题的是 Bash。因为 Bash 既可以运行测试,也可以删除文件;既可以查日志,也可以改系统环境。它是万能工具,也是高风险入口。对 Bash 的控制应该更细:允许 rglsnpm test,但对 rmcurl、数据库命令、批量脚本保持更严格的确认。

工具分级不是为了让 Agent 每一步都等待批准,而是为了把注意力放到真正危险的地方。读十个文件不需要用户紧张,删除一个目录却必须非常明确。

三、Rules:规范不是权限,权限也不是规范

Rules 经常被写成一段团队约定,比如“保持代码简洁”“优先写测试”“不要破坏兼容性”。这些规则很重要,但它们不是权限系统。

规则回答的是“应该怎样做”。权限回答的是“允许不允许做”。二者要配合,而不是互相替代。

比如规则里写“数据库迁移必须向后兼容”,这能引导 Agent 思考字段默认值、旧数据、回滚路径。但如果权限层允许它直接连接生产数据库执行写操作,那么规则本身拦不住危险动作。

反过来,只有限制也不够。如果权限层禁止所有数据库写操作,但没有规则告诉 Agent 迁移要怎么设计,它仍然可能在代码里做出错误假设。

好的 Rules 应该具备三个特征。

第一,具体。不要只写“注意安全”,而要写“不得读取 .env、密钥文件和生产凭据;发现引用时只报告路径,不输出内容”。

第二,可验证。不要只写“保证质量”,而要写“修改 TypeScript 文件后运行类型检查;修改 API 响应结构后更新相关测试”。

第三,有优先级。比如“用户明确要求只读审查时,不得修改文件”应该高于“发现问题后自动修复”。没有优先级,规则冲突时 Agent 会摇摆。

四、Hooks:把提醒变成硬门禁

Hooks 的价值在于把规则放进执行路径。它们不是文档,也不是建议,而是在特定时机自动触发的检查或动作。

常见 Hook 可以分成几类。

PreToolUse 在工具执行前触发,适合拦截危险动作。比如 Agent 想执行 rm -rf、想读取 .env、想对整个仓库做批量替换,此时 Hook 可以拒绝、要求确认,或提示更安全的替代命令。

PostToolUse 在工具执行后触发,适合检查输出或补自动动作。比如修改文件后运行格式化,生成图片后检查体积,安装依赖后提示检查 lockfile。

Stop 在 Agent 准备结束时触发,适合做最终验收。比如检查是否还有未说明的 diff,是否跑过必要测试,是否引用了不存在的图片,是否遗留临时文件。

SubagentStart / SubagentStop 适合管理子代理边界。比如只读调查代理不能修改文件,安全审查代理必须输出风险等级和证据路径。

Hooks 的设计要避免两个极端。一个极端是没有 Hooks,所有质量动作靠 Agent 自觉;另一个极端是 Hooks 过多,任何动作都被打断,导致效率很低。更好的策略是先抓高价值门禁:危险命令、敏感文件、最终验证、生成资产检查。

五、MCP:连接外部系统时默认最小权限

MCP 能把 Agent 连接到 GitHub、数据库、文档、监控、工单、知识库等系统。它让 Agent 从“本地代码助手”变成“研发流程参与者”。但连接越多,风险也越大。

设计 MCP 权限时,可以遵循四个原则。

第一,只读优先。很多场景只需要读取 Issue、PR、日志或 schema,不需要写权限。先把读路径跑通,再考虑写。

第二,范围最小。能限定仓库就不要给组织级权限,能限定表就不要给整库权限,能限定项目就不要给全空间权限。

第三,审计完整。外部系统调用必须能追踪:谁触发、触发时间、调用了什么、输入输出摘要是什么、是否产生写操作。

第四,凭据隔离。Agent 不应该直接看到长期密钥。凭据应由连接器或运行环境管理,输出里也不应该回显敏感内容。

MCP 的目标不是“让 Agent 能连所有东西”,而是让它安全地连必要的东西。对工程组织来说,可审计的有限能力比不可控的全能连接更有价值。

六、案例:自动修复 CI 失败,但不越过审查边界

设想团队希望 Agent 自动处理 PR 中的 CI 失败。这个需求看起来适合自动化:失败日志可读,代码可改,测试可跑。但如果没有控制,很容易出问题。Agent 可能为了让测试通过而删除断言,可能改了不属于当前 PR 的文件,也可能在没有理解业务意图的情况下扩大重构。

一个更稳的设计如下。

第一,工具权限分层。默认允许读取 PR diff、读取失败日志、搜索仓库、运行相关测试。修改权限只开放给工作区文件,并限制不能改密钥、配置凭据和发布脚本。Bash 只允许常用测试命令,危险命令触发确认。

第二,Rules 写清边界。比如“不得删除测试来规避失败”“不得扩大修改到无关模块”“如果失败来自外部服务不可用,应报告阻塞而不是伪造通过”“最终必须说明验证命令”。

第三,PreToolUse 拦截危险动作。如果 Agent 尝试读取 .env、执行 git push、修改 CI 配置、删除测试文件,Hook 直接阻断或要求人工确认。

第四,PostToolUse 自动检查。修改代码后运行格式化;修改测试后检查是否存在删除大量断言;生成文件后检查是否真的需要提交。

第五,Stop 做最终验收。结束前检查 diff 范围、测试结果、失败是否复现过、修复是否有证据。如果没有验证成功,就不能输出“已修复”,只能说明当前状态和阻塞原因。

这个流程允许 Agent 快速推进,但关键边界始终在系统手里。它可以快速处理简单失败,也会在遇到危险动作时被系统检查拦住。

七、质量控制不等于多跑命令

很多团队把质量控制理解成“多跑测试”。测试当然重要,但质量控制还包括修改范围、可读性、兼容性、可维护性和用户路径验证。

对于一个后端接口修改,单元测试通过只能证明局部逻辑大概率正确,还需要确认 API 响应结构没有破坏调用方,错误码没有改变语义,数据库迁移不会影响历史数据,日志没有泄露敏感字段。

对于一个前端页面修改,类型检查通过不等于交互正确。还需要确认移动端布局、加载状态、空状态、错误状态、图片资源和可访问性。

对于文档和内容资产,构建通过也不够。还要检查链接、图片引用、文件体积、标题层级、是否残留占位语句。

Agent 的质量控制应该围绕“改动类型”选择验证方式,而不是机械执行同一组命令。Harness 可以把这件事沉淀成 Rules 和 Hooks:改 API 就跑契约测试,改 UI 就跑截图验证,改图片就检查体积和引用,改数据库就检查迁移。

八、把安全策略写成矩阵

为了避免安全要求停留在口头,可以把策略写成一张矩阵。

场景默认动作允许范围必须验证
只读审查读文件、搜索、输出问题不得修改文件引用文件和行号
修复单元测试修改相关实现与测试不改无关模块相关测试通过
更新文档修改 Markdown 和图片图片体积受限链接与引用存在
数据库迁移生成迁移和测试不连生产库迁移兼容性
CI 自动修复分析日志并最小修改不推送、不改凭据CI 命令或本地等价验证

矩阵的好处是让 Agent 和人都知道边界。它也方便放进 Memory、Rules 或团队插件里复用。

九、一个实用原则:越自动,越要可回放

当 Agent 只给建议时,人可以自己判断;当 Agent 自动修改代码时,系统必须留下证据;当 Agent 接入外部系统时,系统必须可审计;当 Agent 可以在 CI 或平台里无人值守运行时,所有动作都应该可回放。

可回放包括输入、工具调用、关键输出、diff、验证命令和结果。不是为了追责,而是为了排查和改进。一次失败的自动修复如果没有记录,就只能变成“下次小心”;有记录,就能变成 Hook、Rule 或 Skill 的改进。

安全与质量控制的最终目标不是压制 Agent,而是让它承担更大的任务时仍然可信。工程系统里,速度需要配合边界、检查、审计和回放。没有规则的速度只会制造混乱;有规则的速度才会变成稳定优势。