TRAE-security-review
TraeWork 内置 skill —— 执行代码安全扫描。审查合并请求和代码差异,提供结构化的安全漏洞风险反馈。核心原则:Right-side line numbers only + Confidence floor = 0.8——不能明确证明可利用就别报告。
一、定位
| 字段 | 值 |
|---|---|
| 所属 | TraeWork 内置 skill(安全审查) |
| 触发条件 | 审查 MR / PR / 代码 diff,提供安全反馈 |
| 核心方法 | 3 遍审计(项目基线 / 偏差地图 / 源到汇追踪) |
| 核心理念 | Reportable ⇔ Demonstrably exploitable(可报告 ⇔ 可证明可利用) |
二、7 条不可违反的运行原则
- Right-side line numbers only — 位置都是变更后的行号。变更前的行号无效。
- Range form
[L_start, L_end]— 单行问题 start 和 end 相同。 - Diff-introduced surface only — 变更前就有且没改的弱点不在范围内。
- Reportable ⇔ Demonstrably exploitable — 不能说出 (a) 攻击者控制的输入从哪进 (b) 到哪个危险 sink/边界,就别报告。
- 默认排除:可用性 / DoS、限流、代码风格、测试/fixture 代码
- Confidence floor = 0.8 — 低于 0.8 → 丢弃,或交给下游过滤 / 人工审查
- No patches — 识别 + 解释。报告里别写替换代码。
三、9 步流程
3.1 范围决议(§1)
3.1.1 用户已经指定了范围
完全用用户的原话——不扩大不缩小。
3.1.2 范围缺失或模糊
用 AskUserQuestion 工具,给 4 个选项:
- 当前工作区的 uncommitted / staged changes
- 相对命名 branch 的 diff(问 branch 名)
- 特定的 MR / PR(问标识符)
- 给定文件列表(问路径)
如果 AskUserQuestion 不可用,把这 4 个选项用纯文本问。
3.1.3 默认回退
如果用户拒绝指定并要你继续,审计 branch-vs-origin/HEAD delta——用 §2 的数据采集链。
3.2 Diff 数据采集(§2)
跑 4 个 probe——它们是审计的权威输入:
| Probe | 命令 | 用途 |
|---|---|---|
| Working tree state | git status | 检测 untracked / staged 异常 |
| Touched files | git diff --name-only origin/HEAD... | 枚举文件 surface |
| Commit timeline | git log --no-decorate origin/HEAD... | 跨 commit 重建意图 |
| Authoritative diff | git diff --merge-base origin/HEAD | 变更内容的唯一权威源 |
最后一个 probe 产生的 diff 是唯一权威变更内容。聊天里的内联片段是建议;diff 覆盖。
3.2.1 Probe 失败级联
如果 merge-base diff 失败,按这个顺序试:
git diff origin/HEAD...git diff HEAD~1git diff(工作区)- 用
AskUserQuestion让用户明确范围
如果单个辅助工具(如 SearchCodebase)间歇性不可用,继续剩下的部分,显式标记结论受证据范围限制。
3.3 上下文采集(强制,§3)
禁止只基于片段推理。每个候选发现必须按这个顺序收集仓库级证据:
- 确认范围(§1)
- 采集 diff + commits(§2)
- 用
SearchCodebase定位 (a) 输入入口 / 信任边界 (b) 项目已有的 sanitizer / validator / authZ helper - 用
Read检视触碰文件的完整 body + 相关的调用链邻居 - 上面都完成后才开始起草发现
每个候选发现必须收集:
- Source-side evidence — 执行路径上具体的攻击者控制入口
- Sink-side evidence — 输入到达的危险操作、安全边界跨越、敏感数据暴露
- Bypass-context evidence — 附近代码是否已经 sanitize / encode / validate / authorize;项目已有的 helper 是否中和了问题
如果 source-side 或 sink-side 无法用仓库代码证实,丢弃这个发现。
3.4 作者意图重建(§4)
在把任何东西归类为漏洞之前,推断作者写这个 diff 的原因。编辑模式常常能消除意图的歧义:
- 新的错误处理 / null-guards → 防御性重构,提高 “missing-validation” 发现的门槛
- 算法或数据结构替换 → 行为变化;检查调用者的不变量
- 依赖升级 + adapter 粘合 → API 形状迁移;检查旧的安全假设是否还成立
- 变量 / 模块重命名 → 低语义变化;通常没有安全 delta
把推断的意图当作一句话总结,用作候选发现模糊时的决胜点:和明显防御性意图矛盾的发现需要更多证据,不是更少。
3.5 漏洞面(§5)
只审计下面的类别。每个类别列出算数的模式;不在列表里的除非组合了这些,否则不在范围内。
5.1 不受信输入处理
- 通过未净化值的 SQL 注入
- 子进程 / shell-out 路径中的 OS 命令注入
- XML 解析器中的 XXE
- 服务端模板注入
- NoSQL 查询注入
- 文件系统操作中的路径遍历
5.2 认证 / 授权缺陷
- 通过有缺陷的谓词逻辑绕过认证
- 垂直 / 水平权限提升
- 失效的 session 生命周期:fixation、logout 后复用、缺少 rotation
- JWT 误用:弱密钥、
alg=none、缺少aud/iss/exp检查 - 对象级访问缺口(IDOR 类)
5.3 加密和密钥处理
- 源码中的硬编码密钥 / 密码 / token
- 使用损坏或减弱的算法(MD5、SHA1、ECB、RC4、…)
- 不安全的密钥持久化或传输
- 安全上下文中的可预测随机性(
Math.random、非 CSPRNG) - 禁用或存根的证书验证
5.4 代码执行和注入
- 通过不安全的反序列化(
pickle、ObjectInputStream、…)实现远程代码执行 - 实例化任意类型的 YAML loader(不带
SafeLoader的yaml.load) - 不受信字符串上的
eval/Function/exec - Web 表面中的 XSS — 反射 / 存储 / DOM
5.5 敏感数据暴露
- 秘密、凭据或 PII 写入日志或持久存储
- 端点响应返回的内容超出消费者应看到的
- 生产路径上的调试 / 栈 / 构建信息泄露
Local-network-only 可利用性不降低严重性。local-only RCE 仍然是 HIGH。
3.6 审计程序(§6)
3 遍,按顺序。不要交叉。
-
Pass A — 项目安全基线:识别项目已有的安全原语:哪些 validators、escapers、ORM、auth middleware、crypto wrappers 在用。项目自己的模式是比较基线。
-
Pass B — 偏差地图:对每个触碰的文件问:新代码用了项目已有的原语,还是引入了绕开它们的新 ad-hoc 处理?偏差是最高产的发现来源。
-
Pass C — 源到汇追踪:对每个可疑点追踪控制 / 数据流:
- 值从哪进
- 跨过哪些边界
- 路径上是否有 encoding / validation / authZ 检查
- 落在哪
没通过 Pass C 的就丢。
3.7 严重性 & 置信度(§7)
3.7.1 严重性等级
| 严重性 | 触发 |
|---|---|
| HIGH | 直接可利用:RCE、authN 绕过、大范围数据泄露、垂直权限提升 |
| MEDIUM | 在特定但现实的条件下可利用,有实质影响 |
| LOW | 纵深防御缺口,直接影响边际。仅在链条具体时报告 |
3.7.2 置信度
| 范围 | 含义 | 行动 |
|---|---|---|
| 0.90 - 1.00 | 具体攻击路径,仓库内可端到端追踪 | 报告 |
| 0.80 - 0.89 | 识别的易损模式,前置条件看起来可满足 | 报告 |
| 0.70 - 0.79 | 怀疑形状,前置条件投机 | 丢弃 |
| < 0.70 | 投机 | 丢弃 |
偏向假阴性。漏掉边缘发现比洪水报告好;噪音报告比漏掉纵深防御问题更快摧毁审查者信任。
3.8 硬性排除(§8)
这些不能逐个发现豁免。
3.8.1 范围外(按类别)
- 可用性:DoS、资源耗尽、限流缺口、内存 / CPU 压力
- 过时的第三方依赖(由单独工具处理)
- 文档文件里的发现(
*.md、设计文档、RFC) - 「缺少审计日志」/ 「缺少加固」 — 单独不构成漏洞
- 单元测试或 fixture 代码里的发现
- 没有具体可达路径的 race / TOCTOU 模式
- 任何形式的 Regex 注入和 ReDoS
- 包含未净化用户输入的日志条目(「日志欺骗」);只有日志中的 secrets / credentials / PII 算数
- 在 AI 系统 prompt 里包含用户控制的内容
- 只控制 URL path 的 SSRF;SSRF 只在 host 或 protocol 可影响时算
3.8.2 框架和语言豁免
- React / Angular / Vue 默认 XSS-safe。发现需要明确的 escape hatch —
dangerouslySetInnerHTML、bypassSecurityTrust*、v-html或等价的 - 客户端 JS / TS 里缺少 authN / authZ 不是漏洞;那些检查在服务器上
- 内存安全语言(Rust、Go、managed JVM/CLR/JS)中的内存安全问题(buffer overflow、UAF、double free)不报告
- Shell 脚本中的命令注入默认不可达;需要可证明的不受信输入入口
*.ipynb默认不可达;证据门槛和 shell 脚本相同- 环境变量和 CLI flag 是受信输入 — 任何依赖攻击者控制 env / flag 的链条无效
- UUID 不可猜;不要标记缺少 UUID 验证
- GitHub Actions workflow 问题在报告前需要明确的不受信 trigger 路径
3.8.3 微妙的 Web bug
Tabnabbing、XS-Leaks、原型污染、open redirect — 只在利用链高置信度且端到端可见时。默认丢弃。
3.8.4 日志先例
- 记录 URL 是安全的
- 记录非 PII 业务值是安全的,即使值「感觉」敏感
- 只有暴露 secrets / credentials / PII 的日志条目可报告
3.9 输出(§9)
3.9.1 干净的 diff
如果 §3-§8 后没有东西,输出一行总结:
✅ No exploitable issues found in the reviewed change set.
3.9.2 发现表
否则,精确输出一张表:
| # | Category | Title | Severity | Confidence | Evidence (Source → Sink) | Recommendation | Location |
|---|---|---|---|---|---|---|---|
| 1 | sql_injection | Concatenated query in lookup_user | HIGH | 0.92 | req.query.q (router L17) → string concat → db.query (svc L88) | Switch to parameterized query via the project’s existing db.safe_query helper | services/user.py:[80, 95] |
列规则:
- Category 用 §5 的 snake_case 分类法(如
xxe、idor、unsafe_deserialization、weak_crypto) - Severity ∈ {HIGH、MEDIUM、LOW} 按 §7.1
- Confidence 是数字值,保留两位小数
- Evidence 必须编码 source 和 sink;
→分隔 - Location 用右侧行范围 +
file:///…#Lstart-Lend链接形式 - Recommendation 是散文,不写代码。不写 patch。
发现按严重性降序排,然后置信度降序。
3.10 发出前最终自检(§10)
跑这个清单;任何项不通过就删除该行。
- 行的 location 用了变更后的行号?
- 问题是这次 diff 引入或恶化的,不是预先存在且没碰的?
- Evidence 单元格里有 source 和 sink?
- Confidence ≥ 0.80?
- 行通过了 §8 的所有硬性排除?
- Recommendation 只有散文,没有代码 patch?
任何「否」→ 删行再发出。
四、与其他 skill 的关系
| Skill | 关系 |
|---|---|
triage | 安全审查是 issue 分流的一部分 |
diagnosing-bugs | 修发现的 bug |
tdd | 写回归测试防漏洞复发 |
五、引用来源
- TraeWork 实际 skill 路径 —— 本文内容完全来自此文件
六、一句话总结
TRAE-security-review 是「代码安全审查」技能——核心是「能证明可利用才能报告」+ Confidence ≥ 0.8 + 报告里不写 patch。报告是发现 + 证据 + 建议(散文),不是修复方案——避免假阴比避免噪音更重要。