# Threat Model

> 威胁建模与安全设计评审（STRIDE）：画数据流与信任边界 → 逐边界过 STRIDE → 写成攻击者视角的滥用用例 → 每条威胁配一条**可验证的缓解措施 + 测试用例编号** → 残余风险登记。产出落 `dev/design/`。 它在**写代码之前**发现问题：越权设计、凭据流转、多租户隔离、幂等与重放、文件上传、日志与留存、 第三方数据外发——这些在静态代码审计阶段发现时，改的成本已经翻了十倍。 触发词：「威胁建模」「安全设计评审」「STRIDE」「攻击面」「攻击面分析」「滥用用例」「这个设计安全吗」 「数据流图」「信任边界」「多租户隔离怎么做」「上传功能安全吗」「合规要求怎么落到设计里」「等保 / GDPR 怎么对」， 或 `dev-master` 阶段 3 概要设计完成、进详细设计之前。 不适用：写完代码后的静态安全审计与密钥扫描（`pm-ai-ship-audit`）、渗透测试与漏洞验证（不在本库）、 发布期的回滚与应急（`release-rollout`）、功能测试用例（`pm-test-cases`）。

- Skill: `idwong/threat-model` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add idwong/threat-model`
- Raw SKILL.md: https://api.skillmd.com/api/skills/idwong/threat-model/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: iDWong (https://skillmd.com/u/idwong)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/idwong/threat-model

---


# threat-model：威胁建模与安全设计评审

> 一句话定位：**在概要设计之后、详细设计之前**把「谁会怎么打这个系统」想清楚，
> 并把结论变成详细设计里的鉴权列、字段约束与测试用例编号。不产出「建议加强安全性」这类句子。

## 输入门禁

| 必需 | 从哪来 | 缺了怎么办 |
|---|---|---|
| `SPEC_SOURCE`（合格 SRS） | `dev/SRS/*.md` | 回 `dev-master` 阶段 1；只有 PRD 时走 `req-doc` Step F |
| 模块划分与部署拓扑 | 阶段 3 `hld-design` 的概要设计 | 概要设计缺失时，至少要用户口述「有哪些服务、谁和谁通信、数据存哪」，并在产出里标「拓扑为口述，未成文」 |
| 角色与权限矩阵 | SRS 的角色章节 | 缺则先补——**没有角色矩阵就做不了越权分析**，这是本技能最值钱的部分 |
| 数据分级（哪些是敏感数据） | SRS 非功能章节／用户确认 | 缺则现场问一句：哪些字段属于个人信息、凭据、商业敏感 |

## Step 1：资产、信任边界与数据流

1. 列**资产**：数据（分级）、凭据与密钥、可用性本身、业务规则（如余额、库存、审核状态）
2. 画**数据流图**：外部实体 → 进程 → 数据存储，标出**信任边界**（公网↔内网、前端↔后端、租户之间、
   自有服务↔第三方）。图一律走 `diagram-generator`，**禁止手绘 ASCII**
3. 每条跨边界的流写清：谁发起、带什么凭据、传什么数据、走什么协议、对端如何验证

**边界数量决定工作量**：典型三端项目 5–8 条边界；一条都列不出来说明拓扑还没搞清楚，回 Step 0。

## Step 2：逐边界过 STRIDE

对**每条信任边界**过六类威胁，检查项见 `references/stride-checklist.md`（进入本步时读它）：

| 字母 | 威胁 | 典型问法 |
|---|---|---|
| **S** Spoofing | 冒充 | 对端身份怎么验证？token 从哪来、会不会被重放？ |
| **T** Tampering | 篡改 | 参数/价格/状态能否被客户端改？完整性怎么保证？ |
| **R** Repudiation | 抵赖 | 敏感操作有没有留痕？日志能不能被改？ |
| **I** Information Disclosure | 信息泄露 | 越权读、错误信息带堆栈、日志带敏感字段、第三方外发 |
| **D** Denial of Service | 拒绝服务 | 无界查询、大文件、无限重试、缺限流 |
| **E** Elevation of Privilege | 权限提升 | 普通用户能不能拿到管理端能力？前端隐藏按钮是否等于后端校验？ |

**多租户/多角色系统必做一项**：把权限矩阵的每个「否」格子当成一条待验证威胁——
**「按 id 查询时校验归属」要落到详细设计的每个接口上，不是写一句总则**。

## Step 3：滥用用例（攻击者视角）

每条留下来的威胁写成一条可执行的滥用用例，格式与功能用例对称，便于 `pm-test-cases` 直接接手：

```
AU-03 | 越权读取他人草稿
前置：用户 A 与用户 B 各有一篇未发布草稿
步骤：以 A 的会话调用 GET /api/posts/{B的草稿id}
预期：403，且日志记录一次越权尝试（不返回草稿内容，也不返回"不存在"以外的信息差）
```

## Step 4：缓解措施回写（本技能的交付核心）

每条威胁必须落到**一个具体位置**，否则只是清单：

| 威胁去向 | 回写到哪 |
|---|---|
| 需要接口层强制 | 详细设计（`lld-design`）的接口表：鉴权要求列 + 数据范围列 |
| 需要字段约束 | 详细设计的表结构：唯一键、非空、长度、校验规则 |
| 需要非功能要求 | SRS 非功能章节：限流阈值、日志留存期、加密要求、脱敏规则 |
| 需要验证 | `pm-test-cases` 的用例编号（滥用用例进「安全/权限」分类） |
| 暂不处理 | 残余风险登记表（见 Step 5） |

**硬规则：一条威胁 → 一条可验证缓解 + 一个测试用例编号。** 写不出测试用例的缓解措施，说明它还不够具体。

## Step 5：残余风险登记

不做的也要成文：风险描述、为什么不做（成本/阶段/概率）、影响面、触发后的应对、复核时间点、确认人。
**「以后再说」不是理由**；残余风险没有确认人时，默认挂给项目负责人并在交付说明里列出。

## 产出

`dev/design/威胁模型-{项目}-V{版本}.md`，结构：

```markdown
## 一、范围与资产（含数据分级）
## 二、数据流图与信任边界（图由 diagram-generator 生成）
## 三、STRIDE 逐边界结果
| # | 边界 | 类别 | 威胁 | 可能性 | 影响 | 缓解措施 | 回写位置 | 用例编号 | 状态 |
## 四、滥用用例（AU-xx）
## 五、残余风险登记
## 六、复核记录（每次架构变更后回来更新）
```

## 硬规则

1. **不写空话**：「加强权限校验」「注意数据安全」不算一条；必须写成「哪个接口、加什么校验、怎么验」
2. **不重复通用清单**：只写**这个系统**的威胁；OWASP Top 10 逐条抄一遍没有价值
3. **可能性×影响定优先级**：高×高必须在阶段 7 之前落到设计里，不能留到上线审计
4. **图走 `diagram-generator`**，与其它设计文档一致
5. **架构一变就复核**：新增第三方依赖、新增外部入口、改鉴权方式 —— 回来更新第六节

## 在 dev-master 流程里的位置

挂 **阶段 3（概要设计）** 的 `also`：概要设计定完架构与部署拓扑后立刻做，结论作为**阶段 4 详细设计的输入**。
阶段 11 `pm-ai-ship-audit` 会反过来核对「威胁模型里的缓解措施，代码里到底做没做」——两者一前一后，不重叠。

**门禁（进阶段 4 前）**：高×高威胁全部有缓解措施与回写位置；残余风险有确认人。

