@modus-ai/modus 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -42
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +9 -8
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/global.js +1 -1
- package/dist/commands/global.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +37 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/status.js +2 -2
- package/dist/generators/claude.d.ts.map +1 -1
- package/dist/generators/claude.js +1 -37
- package/dist/generators/claude.js.map +1 -1
- package/dist/generators/codebuddy.d.ts.map +1 -1
- package/dist/generators/codebuddy.js +3 -1
- package/dist/generators/codebuddy.js.map +1 -1
- package/dist/generators/codex.d.ts +10 -0
- package/dist/generators/codex.d.ts.map +1 -0
- package/dist/generators/codex.js +178 -0
- package/dist/generators/codex.js.map +1 -0
- package/dist/generators/copilot.d.ts.map +1 -1
- package/dist/generators/copilot.js +0 -1
- package/dist/generators/copilot.js.map +1 -1
- package/dist/generators/cursor.d.ts.map +1 -1
- package/dist/generators/cursor.js +36 -7
- package/dist/generators/cursor.js.map +1 -1
- package/dist/generators/custom.d.ts +55 -0
- package/dist/generators/custom.d.ts.map +1 -0
- package/dist/generators/custom.js +166 -0
- package/dist/generators/custom.js.map +1 -0
- package/dist/generators/index.d.ts +1 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +10 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/utils/config.d.ts +38 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +10 -2
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +2 -1
- package/dist/utils/file-system.js.map +1 -1
- package/package.json +1 -1
- package/schemas/harness-schema.yaml +178 -53
- package/schemas/knowledge-schema.yaml +111 -1
- package/templates/agents/modus-analyst.md +1 -1
- package/templates/behavior-guard.md +165 -0
- package/templates/commands/auto.md +61 -25
- package/templates/commands/commit.md +63 -0
- package/templates/commands/harness.md +97 -30
- package/templates/commands/init.md +43 -10
- package/templates/commands/modus.md +55 -28
- package/templates/commands/plan.md +60 -18
- package/templates/commands/spec.md +69 -25
- package/templates/commands/upgrade.md +54 -0
- package/templates/commands/vibe.md +56 -6
- package/templates/knowledge-catalog.md +74 -32
- package/templates/skills/modus-agents/analyst/SKILL.md +18 -3
- package/templates/skills/modus-agents/deployer/SKILL.md +114 -62
- package/templates/skills/modus-agents/designer/SKILL.md +104 -92
- package/templates/skills/modus-agents/developer/SKILL.md +107 -66
- package/templates/skills/modus-agents/perf-auditor/SKILL.md +98 -61
- package/templates/skills/modus-agents/reviewer/SKILL.md +61 -11
- package/templates/skills/modus-agents/security-auditor/SKILL.md +111 -67
- package/templates/skills/modus-agents/skill-creator/SKILL.md +30 -12
- package/templates/skills/modus-agents/tester/SKILL.md +100 -54
- package/templates/skills/modus-auto/SKILL.md +581 -109
- package/templates/skills/modus-design-brief/SKILL.md +45 -19
- package/templates/skills/modus-harness/SKILL.md +150 -85
- package/templates/skills/modus-init/SKILL.md +1145 -319
- package/templates/skills/modus-plan/SKILL.md +125 -48
- package/templates/skills/modus-platform/SKILL.md +271 -0
- package/templates/skills/modus-spec/SKILL.md +175 -331
- package/templates/skills/modus-vibe/SKILL.md +256 -55
|
@@ -1,116 +1,153 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: modus-perf-auditor
|
|
3
|
-
description: Use this skill when the Harness orchestrator needs to perform static performance audit on code
|
|
4
|
-
allowed-tools: Read,
|
|
3
|
+
description: Use this skill when the Harness orchestrator needs to perform static performance audit on changed code. Detects N+1 queries, missing batch operations, unprotected large data queries, deep pagination risks, and ES query issues. Quantifies each risk by data volume impact and grades as high/medium/low. Generates 04-perf-report.md with HANDOFF block. Triggered by modus-harness in parallel with tester and security-auditor after Gate A passes.
|
|
4
|
+
allowed-tools: Read, Glob
|
|
5
5
|
disable: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# modus-perf-auditor(性能审计 SubAgent)
|
|
9
9
|
|
|
10
|
-
**调用方:** Harness Orchestrator
|
|
11
|
-
**输入:** `02-sprint-contract.md
|
|
10
|
+
**调用方:** Harness Orchestrator(Gate A 通过后,与 03/05 并行触发)
|
|
11
|
+
**输入:** `02-sprint-contract.md`(变更文件列表)+ 代码变更 + 业务 Skill(≤ 2 个)
|
|
12
12
|
**产出物:** `modus/plans/active/{story-id}/04-perf-report.md`
|
|
13
13
|
|
|
14
14
|
## 职责
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
对本次代码变更进行静态性能审计,重点检测高频性能反模式,量化每个风险的潜在影响(N 条数据 → N 次 SQL),按高/中/低分级输出报告。不执行代码,不修改文件。
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## 检测规则
|
|
21
21
|
|
|
22
|
-
### 1
|
|
22
|
+
### Rule 1:N+1 查询(高风险)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
- 循环体内包含 DB 查询调用(`for/while` 内调用 `mapper.select*`)
|
|
26
|
-
- 循环内调用 RPC/HTTP 接口
|
|
24
|
+
**触发条件:** Service / Manager 类的 for 循环 / forEach / stream 内包含 Mapper 调用
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
```java
|
|
27
|
+
// ❌ 触发 N+1
|
|
28
|
+
for (Long orderId : orderIds) {
|
|
29
|
+
Order order = orderMapper.selectById(orderId); // N 次 SQL
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// ✅ 正确:批量查询
|
|
33
|
+
List<Order> orders = orderMapper.selectByIds(orderIds); // 1 次 SQL
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**量化影响:** `N 个订单 → N+1 次 SQL(实测 1000 条 ≈ 1001 次查询)`
|
|
37
|
+
**修复建议:** 改用 `selectByIds(ids)` 批量查询,结果用 Map 分组后使用
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
### Rule 2:无分页保护的大数据量查询(高风险)
|
|
42
|
+
|
|
43
|
+
**触发条件:** Mapper/SQL 中存在以下任一情况:
|
|
44
|
+
- `selectAll()` / `SELECT * FROM table` 无 WHERE 限制
|
|
45
|
+
- 列表查询缺少 `LIMIT` 或时间范围条件
|
|
46
|
+
- 分页参数未设置最大页大小保护
|
|
47
|
+
|
|
48
|
+
**量化影响:** `全表扫描,数据量增长后 OOM 风险`
|
|
49
|
+
**修复建议:** 添加 `LIMIT` 或时间范围条件;分页接口验证 `pageSize ≤ 200`
|
|
35
50
|
|
|
36
51
|
---
|
|
37
52
|
|
|
38
|
-
###
|
|
53
|
+
### Rule 3:深分页风险(中风险)
|
|
39
54
|
|
|
40
|
-
|
|
41
|
-
- 循环内调用单条 insert/update
|
|
42
|
-
- 应使用 `insertBatch` 但使用了逐条 `insert`
|
|
55
|
+
**触发条件:** SQL 中使用 `LIMIT offset, size` 且 offset 无上限控制
|
|
43
56
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- 大批量操作分批提交(每批 500-1000 条),避免超大事务
|
|
57
|
+
**量化影响:** `offset=10000, size=10 → 扫描 10010 行,只返回 10 行`
|
|
58
|
+
**修复建议:** 改用游标分页(`WHERE id > lastId LIMIT size`)或设置 offset 上限
|
|
47
59
|
|
|
48
60
|
---
|
|
49
61
|
|
|
50
|
-
###
|
|
62
|
+
### Rule 4:循环内批量写操作(中风险)
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
- 查询无 LIMIT 限制
|
|
54
|
-
- 分页查询缺少总数上限保护
|
|
55
|
-
- 深分页(`OFFSET` 过大)
|
|
56
|
-
- 全表扫描风险(无索引条件)
|
|
64
|
+
**触发条件:** for 循环内包含 `insert` / `update` / `delete` 调用(而非批量接口)
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- 深分页改用游标分页(基于最后一条记录的 ID)
|
|
66
|
+
**量化影响:** `N 个写入 → N 次 SQL,N 个事务提交`
|
|
67
|
+
**修复建议:** 改用 `insertBatch(list)` / `updateBatch(list)`,单事务批量提交
|
|
61
68
|
|
|
62
69
|
---
|
|
63
70
|
|
|
64
|
-
###
|
|
71
|
+
### Rule 5:缺少索引的高频查询(中风险)
|
|
72
|
+
|
|
73
|
+
**触发条件:** SQL 的 WHERE 条件字段组合在 Entity 注解或已知索引列表中不存在对应索引
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- 缺少 `trackTotalHits: false`(数据量大时计算总数代价高)
|
|
69
|
-
- 聚合查询无 `size: 0`(无需 hits 时)
|
|
75
|
+
**量化影响:** `全表扫描,数据量 > 10 万行后查询超时风险`
|
|
76
|
+
**修复建议:** 添加复合索引 `idx_{field1}_{field2}`
|
|
70
77
|
|
|
71
78
|
---
|
|
72
79
|
|
|
73
|
-
###
|
|
80
|
+
### Rule 6:前缀模糊匹配(低风险)
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
- `@Transactional` 方法内包含远程调用(RPC/HTTP)
|
|
77
|
-
- 事务内包含大量数据查询或处理逻辑
|
|
82
|
+
**触发条件:** SQL 中使用 `LIKE '%keyword%'`(前缀通配符导致索引失效)
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
**量化影响:** `索引失效,全表扫描`
|
|
85
|
+
**修复建议:** 改用全文索引(FULLTEXT)或引入 ES 搜索
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 执行流程
|
|
90
|
+
|
|
91
|
+
### Step 1:确定审计范围
|
|
92
|
+
|
|
93
|
+
读取 `02-sprint-contract.md` 的 `changed_files`,筛选需要审计的文件:
|
|
94
|
+
- Service / Manager 类(Rule 1/4)
|
|
95
|
+
- Mapper 接口 + XML(Rule 2/3/5/6)
|
|
96
|
+
- Controller(Rule 2 的分页参数)
|
|
97
|
+
|
|
98
|
+
### Step 2:逐规则扫描
|
|
99
|
+
|
|
100
|
+
对每个目标文件,逐一应用上述 6 条规则,记录发现的风险。
|
|
101
|
+
|
|
102
|
+
### Step 3:风险分级与量化
|
|
103
|
+
|
|
104
|
+
| 风险等级 | 定义 | 处理要求 |
|
|
105
|
+
|---------|------|---------|
|
|
106
|
+
| 高(需 P2 重入)| 生产环境下数据量正常情况即会触发的性能问题 | modus-reviewer 将标记为 P2,触发 Loop 2 |
|
|
107
|
+
| 中(建议修复)| 数据量增长后可能触发,当前影响有限 | cr-report 中作为 P3 建议 |
|
|
108
|
+
| 低(记录观察)| 仅在极端场景下触发 | 记录但不阻塞 |
|
|
82
109
|
|
|
83
110
|
---
|
|
84
111
|
|
|
85
112
|
## 产出物格式(04-perf-report.md)
|
|
86
113
|
|
|
87
114
|
```markdown
|
|
88
|
-
|
|
115
|
+
<!--HANDOFF
|
|
116
|
+
agent: "04-perf-auditor"
|
|
117
|
+
story_id: "{story-id}"
|
|
118
|
+
gate_status: "passed"
|
|
119
|
+
high_risks: {N}
|
|
120
|
+
medium_risks: {N}
|
|
121
|
+
-->
|
|
122
|
+
|
|
123
|
+
# 性能审计报告 — {Story 标题}
|
|
89
124
|
|
|
90
125
|
## 审计摘要
|
|
91
126
|
- 审计文件数: {N}
|
|
92
127
|
- 高风险: {N} 个 | 中风险: {N} 个 | 低风险: {N} 个
|
|
93
128
|
|
|
94
|
-
##
|
|
129
|
+
## 高风险(需修复)
|
|
95
130
|
|
|
96
|
-
### [HIGH-01] N+1 查询
|
|
131
|
+
### [PERF-HIGH-01] N+1 查询 — {ClassName}.{method}()
|
|
97
132
|
- **位置:** `{文件名}.java:{行号}`
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
List<Long> ids = orders.stream().map(Order::getId).collect(toList());
|
|
104
|
-
Map<Long, Order> orderMap = orderMapper.selectBatchIds(ids)
|
|
105
|
-
.stream().collect(toMap(Order::getId, o -> o));
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## 中风险问题
|
|
133
|
+
- **风险描述:** 循环内调用 `{MapperClass}.{queryMethod}()`
|
|
134
|
+
- **量化影响:** N 个{实体} → N+1 次 SQL(1000 条 ≈ 1001 次查询)
|
|
135
|
+
- **修复建议:** 改为 `{MapperClass}.selectByIds(ids)` 批量查询
|
|
136
|
+
|
|
137
|
+
## 中风险(建议修复)
|
|
109
138
|
...
|
|
110
139
|
|
|
111
|
-
##
|
|
140
|
+
## 低风险(观察记录)
|
|
112
141
|
...
|
|
113
142
|
|
|
114
|
-
##
|
|
115
|
-
{
|
|
143
|
+
## 无风险确认
|
|
144
|
+
{若某类规则未发现风险,明确写出「Rule N:未发现 XXX 问题」}
|
|
116
145
|
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 质量标准
|
|
150
|
+
|
|
151
|
+
- 每个风险必须有文件路径 + 行号定位
|
|
152
|
+
- 高风险必须量化影响(N 条数据 → N 次查询)
|
|
153
|
+
- **HANDOFF 块必须位于文件最顶部**,`high_risks` 字段供 modus-reviewer 决定是否报 P2
|
|
@@ -8,8 +8,8 @@ disable: false
|
|
|
8
8
|
# modus-reviewer(代码评审 SubAgent)
|
|
9
9
|
|
|
10
10
|
**调用方:** Harness Orchestrator(Gate B 通过后触发)
|
|
11
|
-
**输入:** 全部产出物(01-analysis.md 至
|
|
12
|
-
**产出物:** `modus/
|
|
11
|
+
**输入:** 全部产出物(01-analysis.md 至 06-security-report.md)+ 代码变更
|
|
12
|
+
**产出物:** `modus/stories/{story-id}/harness/cr-report.md`
|
|
13
13
|
|
|
14
14
|
## 职责
|
|
15
15
|
|
|
@@ -53,18 +53,29 @@ disable: false
|
|
|
53
53
|
- 日志是否完整(入参、出参、异常信息)
|
|
54
54
|
|
|
55
55
|
**金额处理:**
|
|
56
|
-
-
|
|
57
|
-
-
|
|
56
|
+
- 金额字段是否符合项目宪法的规范(以 `constitution.hard_rules` 为准,如规则为「金额字段使用 Long(单位:分)」则检查 Long 类型,如规则为「使用 BigDecimal」则检查 BigDecimal;**不得硬编码检查某一具体类型**)
|
|
57
|
+
- 若 `constitution.hard_rules` 未明确金额规范,则默认检查是否使用 BigDecimal,并在报告中标注「未找到金额规范配置,使用默认规则」
|
|
58
58
|
|
|
59
|
-
### 维度 3:测试覆盖(参考
|
|
59
|
+
### 维度 3:测试覆盖(参考 04-test-report.md)
|
|
60
60
|
|
|
61
61
|
- 核心业务逻辑是否有测试
|
|
62
62
|
- 测试是否覆盖了重要异常路径
|
|
63
63
|
|
|
64
|
-
### 维度 4:性能与安全(参考
|
|
64
|
+
### 维度 4:性能与安全(参考 05/06 报告)
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
**分级映射规则(将 05/06 报告分级转换为 CR 分级):**
|
|
67
|
+
|
|
68
|
+
| 来源报告 | 原始级别 | CR 级别 | 处理 |
|
|
69
|
+
|---------|---------|--------|------|
|
|
70
|
+
| 06-security-report | 严重 | P1 | 必须修复,触发 Loop 2 重入 |
|
|
71
|
+
| 06-security-report | 高风险 | P2 | 必须修复,触发 Loop 2 重入 |
|
|
72
|
+
| 06-security-report | 低风险 | P3 | 建议修复,不阻塞 |
|
|
73
|
+
| 05-perf-report | 高风险 | P2(若影响 SLA 则升为 P1)| 必须修复 |
|
|
74
|
+
| 05-perf-report | 中风险 | P3 | 建议修复,不阻塞 |
|
|
75
|
+
| 05-perf-report | 低风险 | P3 | 建议修复,不阻塞 |
|
|
76
|
+
|
|
77
|
+
- 06(安全)报告中「严重」和「高风险」问题是否已在代码中修复
|
|
78
|
+
- 05(性能)报告中「高风险」问题是否已修复
|
|
68
79
|
|
|
69
80
|
---
|
|
70
81
|
|
|
@@ -81,6 +92,34 @@ disable: false
|
|
|
81
92
|
## 产出物格式(cr-report.md)
|
|
82
93
|
|
|
83
94
|
```markdown
|
|
95
|
+
---
|
|
96
|
+
schema_version: "1.1"
|
|
97
|
+
agent: "07-review"
|
|
98
|
+
run_id: "{YYYYMMDD}-{story_id_prefix}"
|
|
99
|
+
story_id: "{story-id}"
|
|
100
|
+
task_id: ""
|
|
101
|
+
domains: ["{domain1}", "{domain2}"]
|
|
102
|
+
gate_status: "{passed|failed}"
|
|
103
|
+
artifact_status: "complete"
|
|
104
|
+
issues:
|
|
105
|
+
- level: "P1"
|
|
106
|
+
code: "P1-01"
|
|
107
|
+
agent: "07-review"
|
|
108
|
+
location: "{文件名}.java:{行号}"
|
|
109
|
+
summary: "{一句话问题摘要,供 Orchestrator 定位重入范围}"
|
|
110
|
+
suggestion: "{修复建议}"
|
|
111
|
+
affected_sprint: "{受影响的 Sprint 编号,如 Sprint 2}"
|
|
112
|
+
- level: "P2"
|
|
113
|
+
code: "P2-01"
|
|
114
|
+
agent: "07-review"
|
|
115
|
+
location: "{文件名}.java:{行号}"
|
|
116
|
+
summary: "{一句话问题摘要}"
|
|
117
|
+
suggestion: "{修复建议}"
|
|
118
|
+
affected_sprint: "{N}"
|
|
119
|
+
skill_refs:
|
|
120
|
+
- "modus-biz-{domain}@{version}"
|
|
121
|
+
---
|
|
122
|
+
|
|
84
123
|
# 代码评审报告
|
|
85
124
|
|
|
86
125
|
## 评审摘要
|
|
@@ -116,15 +155,26 @@ disable: false
|
|
|
116
155
|
{如无 P1/P2 → "通过评审,可进入 Final Review"}
|
|
117
156
|
```
|
|
118
157
|
|
|
158
|
+
**HANDOFF 块填写规则(YAML frontmatter 格式,v1.1):**
|
|
159
|
+
- `gate_status`:无 P1/P2 → `passed`;有 P1/P2 → `failed`
|
|
160
|
+
- `issues`:仅列 P1/P2 问题(P3 不阻塞,Orchestrator 不读取);无 P1/P2 时写空列表 `issues: []`
|
|
161
|
+
- 每条 issue 的 `affected_sprint` 字段:填写受影响代码所属的 Sprint 编号(如「Sprint 2」),供 Orchestrator 精准定位重入范围
|
|
162
|
+
- 每条 issue 的 `code` 字段:填写问题编码(如 `P1-01`、`P2-03`),用于精准重入定位
|
|
163
|
+
- HANDOFF 块**必须位于文件最顶部(`---...---` YAML frontmatter)**,Orchestrator 仅读此块(≤ 25 行)以决策是否触发 Loop 2
|
|
164
|
+
|
|
119
165
|
---
|
|
120
166
|
|
|
121
167
|
## 创建 Bug 单(可选)
|
|
122
168
|
|
|
123
|
-
|
|
169
|
+
> **前置条件:** 需在 `{project}/modus/config.yaml` 中配置 `tapdProjectId`(非空)才能触发 Bug 创建。当前 `tapdProjectId: ""` 时跳过此步骤。
|
|
170
|
+
|
|
171
|
+
> **协调说明:** 如果 workspace 中已安装独立的 `tapd-bug-creator` Skill,**优先使用外部 Skill** 创建 Bug 单(职责更单一),本节逻辑作为降级兜底(外部 Skill 不可用时才启用)。两者不应同时执行。
|
|
172
|
+
|
|
173
|
+
如果满足前置条件,对于 P1/P2 问题自动创建 TAPD Bug 单:
|
|
124
174
|
|
|
125
175
|
- Bug 标题:`[Modus CR] {问题标题}`
|
|
126
176
|
- 关联 Story ID:`{当前 story-id}`
|
|
127
|
-
-
|
|
177
|
+
- 描述:包含代码位置(`location` 字段)、问题代码片段、修复方案(`suggestion` 字段)
|
|
128
178
|
- 严重程度:P1 → 严重,P2 → 一般
|
|
129
179
|
|
|
130
|
-
创建完成后将 Bug ID 写入 cr-report.md
|
|
180
|
+
创建完成后将 Bug ID 写入 cr-report.md 末尾的 `tapd_bugs` 列表。
|
|
@@ -1,123 +1,167 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: modus-security-auditor
|
|
3
|
-
description: Use this skill when the Harness orchestrator needs to perform security audit on code
|
|
4
|
-
allowed-tools: Read,
|
|
3
|
+
description: Use this skill when the Harness orchestrator needs to perform static security audit on changed code. Detects multi-tenant data isolation leaks (tenantId from request vs UserContext), missing permission annotations, SQL injection risks, sensitive data logging, and improper bypass interfaces. Grades as critical/high/low and generates 05-security-report.md with HANDOFF block. Triggered by modus-harness in parallel with tester and perf-auditor after Gate A passes.
|
|
4
|
+
allowed-tools: Read, Glob
|
|
5
5
|
disable: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# modus-security-auditor(安全审计 SubAgent)
|
|
9
9
|
|
|
10
|
-
**调用方:** Harness Orchestrator
|
|
11
|
-
**输入:** `02-sprint-contract.md
|
|
10
|
+
**调用方:** Harness Orchestrator(Gate A 通过后,与 03/04 并行触发)
|
|
11
|
+
**输入:** `02-sprint-contract.md`(变更文件列表)+ 代码变更 + 业务 Skill(≤ 2 个)
|
|
12
12
|
**产出物:** `modus/plans/active/{story-id}/05-security-report.md`
|
|
13
13
|
|
|
14
14
|
## 职责
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
对本次代码变更进行静态安全审计,重点检测多租户隔离漏洞、权限校验缺失、SQL 注入、敏感信息泄露等高频安全问题。不执行代码,不修改文件。
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## 检测规则
|
|
21
21
|
|
|
22
|
-
### 1
|
|
22
|
+
### Rule 1:多租户数据隔离漏洞(严重)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
- DB 查询/更新缺少 `tenantId` 条件
|
|
26
|
-
- `tenantId` 来自 request 参数(可被篡改),而不是从用户会话/上下文中获取
|
|
27
|
-
- 数据归属校验:操作前是否验证当前用户有权操作该条记录
|
|
24
|
+
**触发条件:** Service / Mapper 中的 WHERE 条件使用了来自 request 参数而非 UserContext 的 `tenantId`
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
```java
|
|
27
|
+
// ❌ 严重漏洞:tenantId 来自用户输入,可查看任意租户数据
|
|
28
|
+
public List<Order> listOrders(OrderQueryRequest request) {
|
|
29
|
+
return orderMapper.selectByTenantId(request.getTenantId()); // 危险
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ✅ 正确:tenantId 必须来自 UserContext(登录上下文)
|
|
33
|
+
public List<Order> listOrders(OrderQueryRequest request) {
|
|
34
|
+
Long tenantId = UserContext.getCurrentTenantId(); // 安全
|
|
35
|
+
return orderMapper.selectByTenantId(tenantId);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**危害:** 横向越权,A 租户可读取 B 租户数据
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### Rule 2:Facade/Controller 权限校验缺失(高风险)
|
|
44
|
+
|
|
45
|
+
**触发条件:** 新增的 Facade / Controller 方法缺少权限注解(如 `@UserAuthorization`、`@PreAuthorize`、`@RolesAllowed`)
|
|
46
|
+
|
|
47
|
+
**危害:** 未授权用户可直接调用接口
|
|
48
|
+
**修复建议:** 所有对外接口必须有权限注解,最小权限原则
|
|
33
49
|
|
|
34
50
|
---
|
|
35
51
|
|
|
36
|
-
###
|
|
52
|
+
### Rule 3:敏感信息日志泄露(高风险)
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
54
|
+
**触发条件:** `log.info` / `log.debug` / `log.error` 中直接打印以下敏感字段:
|
|
55
|
+
- 身份证号(idCard / idNo)
|
|
56
|
+
- 银行卡号(bankCard / cardNo)
|
|
57
|
+
- 手机号(phone / mobile)
|
|
58
|
+
- 密码(password / pwd)
|
|
59
|
+
- 完整 Token / sessionId
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- 结合项目的权限框架(RBAC/自定义注解)进行检查
|
|
61
|
+
**危害:** 日志系统通常访问范围较广,敏感信息泄露风险高
|
|
62
|
+
**修复建议:** 使用脱敏工具类处理后再打印,如 `MaskUtils.maskPhone(phone)`
|
|
46
63
|
|
|
47
64
|
---
|
|
48
65
|
|
|
49
|
-
###
|
|
66
|
+
### Rule 4:SQL 注入风险(严重)
|
|
67
|
+
|
|
68
|
+
**触发条件:** MyBatis XML / 注解 SQL 中使用 `${}` 拼接用户输入(应使用 `#{}`)
|
|
50
69
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- 异常信息中暴露内部实现细节(SQL 语句、堆栈等)
|
|
70
|
+
```xml
|
|
71
|
+
<!-- ❌ SQL 注入 -->
|
|
72
|
+
SELECT * FROM orders WHERE status = ${status}
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
<!-- ✅ 安全 -->
|
|
75
|
+
SELECT * FROM orders WHERE status = #{status}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**危害:** 用户可构造恶意 SQL 执行任意查询或修改数据
|
|
60
79
|
|
|
61
80
|
---
|
|
62
81
|
|
|
63
|
-
###
|
|
82
|
+
### Rule 5:Bypass 接口缺少多租户保护(高风险)
|
|
64
83
|
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
84
|
+
**触发条件:** 以下类型的"内部接口"没有 tenantId 过滤:
|
|
85
|
+
- 定时任务(`@Scheduled` / `@XxlJob`)中的全量查询
|
|
86
|
+
- 管理后台接口中可跨租户的查询
|
|
87
|
+
- MQ 消费者处理消息时未验证消息的 tenantId
|
|
69
88
|
|
|
70
|
-
|
|
71
|
-
- 用户输入一律使用 `#{}` 参数化
|
|
72
|
-
- 动态排序字段做枚举白名单校验
|
|
89
|
+
**危害:** 批量操作可能意外处理其他租户的数据
|
|
73
90
|
|
|
74
91
|
---
|
|
75
92
|
|
|
76
|
-
###
|
|
93
|
+
### Rule 6:不安全的反序列化(中风险)
|
|
94
|
+
|
|
95
|
+
**触发条件:** 使用 `ObjectInputStream` 直接反序列化用户可控的数据,或使用不安全的 JSON 反序列化(如 `JSONObject.parseObject(str, Object.class)`)
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
**危害:** 远程代码执行(RCE)风险
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 执行流程
|
|
102
|
+
|
|
103
|
+
### Step 1:确定审计范围
|
|
104
|
+
|
|
105
|
+
读取 `02-sprint-contract.md` 的 `changed_files`,筛选需要审计的文件:
|
|
106
|
+
- Controller / Facade(Rule 1/2/3)
|
|
107
|
+
- Service / Manager(Rule 1/3/5)
|
|
108
|
+
- XML Mapper(Rule 4)
|
|
109
|
+
- MQ Consumer(Rule 5)
|
|
110
|
+
- 定时任务类(Rule 5)
|
|
111
|
+
|
|
112
|
+
### Step 2:逐规则扫描
|
|
113
|
+
|
|
114
|
+
对每个目标文件,逐一应用上述 6 条规则,记录发现的安全漏洞。
|
|
115
|
+
|
|
116
|
+
### Step 3:风险分级
|
|
117
|
+
|
|
118
|
+
| 风险等级 | 定义 | 处理要求 |
|
|
119
|
+
|---------|------|---------|
|
|
120
|
+
| 严重(需 P1 重入)| 可直接导致数据泄露或越权的漏洞 | modus-reviewer 标记为 P1,触发 Loop 2 |
|
|
121
|
+
| 高(需 P2 重入)| 安全隐患,在特定条件下可被利用 | modus-reviewer 标记为 P2,触发 Loop 2 |
|
|
122
|
+
| 中(建议修复)| 潜在风险,当前影响有限 | cr-report 中作为 P3 建议 |
|
|
81
123
|
|
|
82
124
|
---
|
|
83
125
|
|
|
84
126
|
## 产出物格式(05-security-report.md)
|
|
85
127
|
|
|
86
128
|
```markdown
|
|
87
|
-
|
|
129
|
+
<!--HANDOFF
|
|
130
|
+
agent: "05-security-auditor"
|
|
131
|
+
story_id: "{story-id}"
|
|
132
|
+
gate_status: "passed"
|
|
133
|
+
critical_risks: {N}
|
|
134
|
+
high_risks: {N}
|
|
135
|
+
-->
|
|
136
|
+
|
|
137
|
+
# 安全审计报告 — {Story 标题}
|
|
88
138
|
|
|
89
139
|
## 审计摘要
|
|
90
|
-
-
|
|
140
|
+
- 审计文件数: {N}
|
|
141
|
+
- 严重: {N} 个 | 高风险: {N} 个 | 中风险: {N} 个
|
|
91
142
|
|
|
92
|
-
##
|
|
143
|
+
## 严重漏洞(必须修复)
|
|
93
144
|
|
|
94
|
-
### [SEC-CRITICAL-01]
|
|
145
|
+
### [SEC-CRITICAL-01] 多租户隔离漏洞 — {ClassName}.{method}()
|
|
95
146
|
- **位置:** `{文件名}.java:{行号}`
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// 正确
|
|
102
|
-
Long tenantId = UserContext.getCurrentTenantId();
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## 高风险问题
|
|
147
|
+
- **漏洞描述:** tenantId 来自 request.getTenantId(),而非 UserContext
|
|
148
|
+
- **危害:** 横向越权,A 租户可读取 B 租户数据
|
|
149
|
+
- **修复方案:** 将 `request.getTenantId()` 替换为 `UserContext.getCurrentTenantId()`
|
|
150
|
+
|
|
151
|
+
## 高风险(必须修复)
|
|
106
152
|
...
|
|
107
153
|
|
|
108
|
-
##
|
|
154
|
+
## 中风险(建议修复)
|
|
109
155
|
...
|
|
110
156
|
|
|
111
|
-
##
|
|
112
|
-
{
|
|
157
|
+
## 无风险确认
|
|
158
|
+
{若某类规则未发现风险,明确写出「Rule N:未发现 XXX 风险」}
|
|
113
159
|
```
|
|
114
160
|
|
|
115
161
|
---
|
|
116
162
|
|
|
117
|
-
##
|
|
163
|
+
## 质量标准
|
|
118
164
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
| 高风险 | 有潜在安全风险,影响范围较大 | 必须在合入前修复,触发 Loop 2 重入 |
|
|
123
|
-
| 低风险 | 安全最佳实践问题,影响范围有限 | 建议修复,不阻塞合入 |
|
|
165
|
+
- 每个漏洞必须有文件路径 + 行号定位
|
|
166
|
+
- 严重/高风险必须提供具体修复代码示例
|
|
167
|
+
- **HANDOFF 块必须位于文件最顶部**,`critical_risks` + `high_risks` 供 modus-reviewer 决定 P1/P2 级别
|