---
url: /wave-agent/specs/commands/code-security.md
description: 会话内自动拦危险模式、按需多 agent 深扫、`/security-review` 单次过分支三层代码安全能力及其分发渠道
---

# 功能规格说明：代码安全审核

**创建日期**：2026-10-13

## 背景

代码安全审核由三个**可分发的产物**组成，按触发时机分层，互补而非互相替代：

| 产物                   | 分发渠道     | 触发方式                           |
| ---------------------- | ------------ | ---------------------------------- |
| Security Guidance 插件 | 官方插件市场 | 自动，发生在 Claude 写代码的过程中 |
| Security Audit 插件    | 官方插件市场 | 手动，会话内按需发起               |
| `/security-review`     | 产品内置     | 手动，单次过一遍当前分支           |

归属依据是**能力与产品流程的耦合度**：需要常驻在会话回合循环里、随每次写入与每轮结束自动介入的能力，作为插件分发——用户可以自行取舍是否安装，且它的规则依赖项目自己的安全约定；而一次性的、不依赖任何附加组件、开箱即用的分支审查，作为内置能力随产品发布。

三层都不替代用户已有的静态分析与依赖扫描：它们推理的是代码语义，与确定性检查互补。三层都**不阻塞**写入或提交，发现以提示的形式回到正在写代码的那个 Claude，由它在同一会话内修正。

## 机制依赖

三层各自复用已有的会话机制，本节只记依赖关系与它落在哪个规格，机制细节以被引规格为准：

| 层                      | 依赖的机制                                                                                              | 落在                                                |
| ----------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| 逐次编辑比对            | `PostToolUse` 事件 + `hookSpecificOutput.additionalContext`（以"上下文"而非"报错"的档位把告警送进模型） | `automation/hooks.md`                               |
| 回合结束复核            | `asyncRewake`：后台运行、发现问题（退出码 2）时回灌并唤醒模型——这是「不延迟原回复」得以成立的前提       | `automation/hooks.md`                               |
| 提交推送前复核          | `PreToolUse` 事件（识别 Claude 自己发起的提交/推送）                                                    | `automation/hooks.md`                               |
| 按需深度扫描 / 补丁复核 | 子代理与后台代理的多 agent 编排                                                                         | `multi-agent/`                                      |
| `/security-review`      | 内置斜杠命令 + 正文注入命令；其权限校验与失败语义按被引规格执行                                         | `ui/slash-commands.md`、`ecosystem/agent-skills.md` |

## 用户场景与测试 *（必填）*

### 用户故事：写码时的即时危险模式告警（优先级：P1）

作为开发者，我希望 Claude 每写完一个文件就被检查一次已知的危险调用模式，以便问题在它还没离开这个文件时就被点出来，而不是留到 PR。

**为什么是这个优先级**：这是唯一能在写入的那一刻介入的层，也是三层里唯一不产生模型调用成本的一层——它必须便宜到可以每次编辑都跑。

**独立测试**：让 Claude 写入一个含危险调用的文件，验证告警在**同一次会话的后续步骤**中出现在 Claude 的上下文里，且无需用户额外操作。

**验收场景**：

1. **假设**插件已启用，**当**Claude 通过编辑工具写入一个文件，**则** 该文件的新内容被与危险模式清单比对。
2. **假设**新内容命中某条危险模式，**当**比对完成时，**则** 一条说明该模式与建议改法的告警被追加进 Claude 的上下文，Claude 在后续步骤中可见。
3. **假设**同一文件重复命中同一条模式，**当**该模式在本会话内已被报过时，**则** 不再重复报出，避免同一处告警刷屏。
4. **假设**新内容未命中任何模式，**当**比对完成时，**则** 不产生任何输出，也不打断 Claude 的流程。
5. **假设**插件未启用，**当**Claude 写入文件时，**则** 不发生任何比对，行为与未安装插件完全一致。

***

### 用户故事：回合结束的安全复核（优先级：P1）

作为开发者，我希望每一轮 Claude 干完活之后，有一个独立的复核看过这一轮改动，以便字符串匹配抓不到的问题（权限绕过、越权访问、注入、弱加密）也能在当轮被指出并修正。

**为什么是这个优先级**：这是唯一能覆盖「语义类漏洞」的自动层。字符串匹配只能抓固定模式，而语义类问题需要读懂上下文。

**独立测试**：让 Claude 在一轮内做出一个含越权访问的改动，验证该轮结束后出现安全发现，且 Claude 在随后的回合里对它做出了修改。

**验收场景**：

1. **假设**某一轮内工作区发生了文件改动，**当**该轮结束时，**则** 针对这一轮全部改动的安全复核被发起，且**不延迟** Claude 对用户的原回复。
2. **假设**改动来自编辑工具、Bash 命令或子代理中的任意一种，**当**计算这一轮的改动范围时，**则** 三种来源的改动都被算进去。
3. **假设**复核发现了问题，**当**发现产出后，**则** 正在写代码的 Claude 被重新唤起并处理这些发现，用户在同一会话中能看到**发现本身**与 **Claude 的处理**两者。
4. **假设**复核连续多次都产出新发现，**当**连续次数达到上限时，**则** 交出控制权给用户，不再自动继续。
5. **假设**一轮内改动的文件数超过单轮上限，**当**复核启动时，**则** 复核按上限截取，并在结果中说明覆盖范围。
6. **假设**该轮没有任何文件改动，**当**该轮结束时，**则** 不发起复核。

***

### 用户故事：提交与推送前的复核（优先级：P2）

作为开发者，我希望在 Claude 自己提交或推送之前，有一次读得更深的复核，以便「单看像危险、放在这个代码库里其实安全」的模式不会变成误报，而真正的问题不会进到历史里。

**为什么是这个优先级**：更正一次已经进入历史的错误，代价高于更正一次工作区里的错误。但它比回合结束复核少见，所以排在后面。

**独立测试**：让 Claude 提交一个单看可疑、但调用方已有校验的改动，验证复核读到周边代码后不报，或报出的内容包含对周边代码的判断。

**验收场景**：

1. **假设**Claude 通过其命令执行能力运行提交或推送，**当**该动作发生时，**则** 一次比回合结束复核更深的复核被发起，它会读取相关调用方、校验点与邻近文件来判断发现真伪。
2. **假设**用户在会话中用自己的 shell 逃逸直接运行提交，**当**该动作发生时，**则** 不触发这一层复核——这一层只覆盖 Claude 自己发起的提交与推送。
3. **假设**这一层的发现与回合结束复核已经报过的内容重复，**当**结果产出时，**则** 不重复唤起 Claude，一次干净的提交不产生可见输出。
4. **假设**滚动一小时内的提交次数超过上限，**当**达到上限时，**则** 不再发起这一层复核。

***

### 用户故事：按需深度扫描代码库或一段改动（优先级：P1）

作为开发者，我希望在需要的时候发起一次多 agent 的深度扫描，覆盖整个代码库、一个分支的 diff、一个 PR 的 diff 或单个提交，以便清查**已经存在**的问题——包括从来不是 Claude 写的、历史遗留的那些。

**为什么是这个优先级**：自动层只能看见 Claude 自己改动的东西。存量清查是它结构上做不到的事，这是本层存在的唯一理由。

**独立测试**：在一个含已知漏洞、且该漏洞文件从未被 Claude 改动过的仓库里发起全库扫描，验证该漏洞出现在报告里。

**验收场景**：

1. **假设**用户发起本插件而没指明要做哪一件事，**当**进入时，**则** 先在「扫全库 / 扫改动 / 出补丁」三件事里选一件，选定后才进入该件事自己的范围菜单；用户已明确指名某件事时跳过这道选择。
2. **假设**用户发起扫描，**当**扫描启动前，**则** 先呈现可选的扫描范围（整库或聚焦区域）及每项的文件数与相对成本，并在用户确认前**不执行任何动作**。
3. **假设**用户确认全库扫描，**当**扫描执行时，**则** 扫描先梳理架构、建立威胁模型，再查找漏洞，最后对每一条发现由**独立于发现者的**复核者验证后才写入报告。
4. **假设**当前分支存在其基线分支没有的提交，**当**用户发起扫描时，**则** 提供只扫描这段 diff 的选项。
5. **假设**工作区有未提交的改动，**当**用户发起改动扫描时，**则** 只扫描已提交部分，并提示用户先提交或改用全库扫描。
6. **假设**仓库不在版本控制下，**当**用户发起全库扫描时，**则** 扫描照常执行；改动扫描则不可用。
7. **假设**扫描完成，**当**结果落盘时，**则** 在一个带时间戳的独立目录里产出人读报告、机器可读结果、以及一份按弱化类别分类的标准化静态分析格式（SARIF）日志。
8. **假设**报告已产出，**当**用户阅读时，**则** 每条发现带编号、影响、利用场景、严重度、置信度与修复建议。
9. **假设**扫描完成，**当**用户查看仓库改动时，**则** 扫描对该目录之外的检出**没有任何改动**，且该目录自身不会被普通 `git add` 误收。
10. **假设**同一份代码被扫描两次，**当**两次结果比较时，**则** 两次的发现**允许不同**——扫描是随机的，报告需要能归因到它描述的确切代码与设置。

***

### 用户故事：把扫描发现变成可评审的补丁（优先级：P2）

作为开发者，我希望把选定的发现变成补丁，但补丁必须由我自己决定是否应用，以便我不必信任一个未经复核的自动改写。

**为什么是这个优先级**：只报不修会让发现堆积成待办；直接自动改写风险更高。补丁是被独立复核过、但由人拍板的中间形态。

**独立测试**：选定一条发现生成补丁，验证源码在被应用前未被改动，且补丁旁附带一段说明。

**验收场景**：

1. **假设**用户选定若干发现，**当**补丁被起草时，**则** 起草发生在仓库的临时副本中，用户的源文件保持不动。
2. **假设**补丁已起草，**当**交付前，**则** 由一个**独立于起草者**的复核者检查它：在项目有测试时运行测试，并独立阅读 diff 判断是否引入新问题。
3. **假设**复核无法同时确认「解决了该发现」「未引入新漏洞」「其余行为不变」三点，**当**交付时，**则** 不产出补丁，改为给出一段说明。
4. **假设**报告所描述的代码在生成补丁前已经变更，**当**用户要求补丁时，**则** 跳过对应发现并提示重新扫描，而不是基于过期报告改写。
5. **假设**补丁已产出，**当**写入时，**则** 每个发现一个补丁文件并附一段说明；补丁**从不自动应用**。

***

### 用户故事：单次过一遍当前分支的安全审查（优先级：P1）

作为开发者，我希望有一条开箱即用的命令，一次过完当前分支相对远端默认分支的全部改动，以便在不安装任何插件的前提下就能在提交前自查。

**为什么是这个优先级**：这是三层里唯一不需要安装任何东西的一条，也是内置于产品的入口。

**独立测试**：在一个安装状干净、未启用任何插件的会话中运行 `/security-review`，验证产出安全审查报告。

**验收场景**：

1. **假设**当前分支相对远端默认分支有改动，**当**用户运行 `/security-review` 时，**则** 审查覆盖这批改动的全部内容，并只关注**本批新增**的安全问题。
2. **假设**存在既有但本批未触碰的安全隐患，**当**审查执行时，**则** 不报出——本命令只对本批改动负责。
3. **假设**用户希望实现修复，**当**审查完成时，**则** 用户可以直接要求 Claude 落实修复，无需离开当前会话。
4. **假设**仓库没有配置远端默认分支的引用，**当**运行该命令时，**则** 明确告知缺少该引用及补建方式，而不是给出不完整的审查结果。
5. **假设**该命令未被用户主动调用，**当** Claude 正常工作时，**则** 不自动运行。

***

### 用户故事：用项目自己的安全规则扩展审核（优先级：P2）

作为团队维护者，我希望用仓库里的规则文件描述本项目的威胁模型与危险模式，以便审核贴合本项目的约定，而不只是通用清单。

**为什么是这个优先级**：通用清单覆盖共性，团队真正关心的往往是本项目特有的约束（多租户必须带租户过滤、某类字段不得进日志）。

**独立测试**：添加一条本项目的规则，验证审核据此产生发现；再确认写一条「忽略某类漏洞」不会让该类发现消失。

**验收场景**：

1. **假设**仓库里存在安全指引文件，**当**每轮改动的复核执行时，**则** 指引内容作为附加上下文加载，与内置清单一起使用；提交前的复核不读该文件，该层的判断只来自代码本身。
2. **假设**用户级、项目级与项目本地三个作用域都存在指引文件，**当**加载时，**则** 全部加载并拼接，合计不超过其上限。
3. **假设**用户级、项目级与项目本地三个作用域都存在危险模式规则文件，**当**逐次编辑的比对执行时，**则** 三者的自定义规则全部与内置模式一同生效，各自的规则名与提示文案随告警给出。
4. **假设**自定义规则数量超过上限，**当**加载时，**则** 只加载到上限为止。
5. **假设**指引文件要求忽略某一类漏洞，**当**模型驱动的复核执行时，**则** 该类发现**不被抑制**——规则是给复核者的指引，不是屏蔽机制。
6. **假设**需要硬性阻止，**当**用户配置时，**则** 应改用能阻断编辑的 hook 或 CI 检查，本能力的任何一层都不承担阻断职责。

***

### 边界情况

* 三层都不阻断写入、提交或合并；它们把发现交给 Claude 或用户，而不是拦住动作。
* 模型驱动的复核可能漏报。三层是纵深防御中的若干层，不是完整方案。
* 逐次编辑的比对与模型驱动的复核口径不同：前者是确定性的字符串匹配，能被它抓到的模式有限。
* 扫描结果具有随机性，两次扫描同一份代码可能给出不同发现；它以是否定期执行来补足，而不是以确定性来保证。
* 会话内的自动层只覆盖 Claude 自己产生或发起的改动；用户在自己的终端里做的改动不在其视野内。
* 整个能力面向用户自有或已获授权的代码；不用于扫描第三方代码。
* 项目本地作用域的规则文件属于个人覆盖，应加入版本控制忽略清单。

## 假设

* **A-001**：自动层的启用与否完全由插件开关决定，默认关闭；卸载插件等价于三层全部不存在，不残留任何产物或后台动作。
* **A-002**：自动层的三层各自可独立关闭，但内置的危险模式清单不可单条移除，只能由自定义规则追加。
* **A-003**：扫描产物目录带自己的忽略规则，因此不会进入用户的提交；用户若要将报告纳入版本历史，需显式移除该忽略规则。
* **A-004**：补丁应用始终是用户的手动动作，产品不提供自动应用的入口。
