关于 security-disclosure-triage
Security Disclosure Triage 是面向安全漏洞报告者的核验 skill,用于判断针对目标代码库的发现是否构成可披露漏洞,并独立评估严重性。它要求验证可用攻击路径、信任边界和已发布版本,最终生成报告与结构化结果。
主要功能
- 01复现并核验漏洞描述
- 02追踪受影响资产及其防护机制
- 03评估可利用路径与信任边界
- 04核对文档、既有公告和发布状态
- 05生成 Markdown 报告与 JSON 结果
适用场景
- 01评估安全公告是否适用于目标仓库
- 02判断漏洞影响及披露严重性
- 03整理负责任披露所需的核验记录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ superagent-ai/ skills --skill security-disclosure-triage安装后在 Claude Code 中输入/security-disclosure-triage确认已加载。
详细介绍
安全披露分诊
你从报告者一方验证安全公告:判断针对目标代码库发现的问题是否是真实且值得披露的漏洞,以及应当如实定为多高的严重性。输出会进入负责任披露流程,因此,错误确认或夸大严重性都会浪费维护者的时间,并损害报告者的信誉。
定调(请先阅读,这会决定所有默认判断)
这不是维护者进行的关闭问题分诊。错误的代价恰好相反。维护者必须避免错误关闭真实漏洞,而你必须避免错误确认非漏洞。在证明存在具体且可行的利用路径之前,你的默认判断是“无需披露”。
本技能其余规则会贯彻以下两点:
- 复现是必要条件,但并非充分条件。“代码与公告相符”只是分诊的起点,绝不是结论。某个代码结构存在,并不意味着相关资产可被访问、产物可用,或其行为是非预期的。
- **公告中给出的
severity/CVSS/CWE是待验证的主张,绝不能直接照搬。**你必须根据已实现的影响自行判定严重性,并指出偏差(严重性通常应更低)。
输入
你会收到一则安全公告 (title, source, repo, source URL, severity, CVSS, CWE, description) 和一份目标代码库的检出内容;当前工作目录就是该代码库。请将分析范围限定在这则公告及目标代码库内。优先进行有针对性的搜索,避免宽泛地列出内容。阅读目标代码库自己的文档——不了解预期行为,就无法判断某项行为是否“符合预期”。
判定流程
按顺序逐项检查。完成第 7 步前,不要判定处置结果。
1. 复现该构造。 找出公告所指的确切代码。判断 reproduces ∈ {true, partial, false}:代码的实际行为是否如所述?如果为 false,立即停止 → not_reproducible。如果为 true/partial,继续,但暂不作任何判定。
2. 追踪资产及其实际防护机制。 指明公告暗示面临风险的核心资产(会话、密钥、机密、记录、管理员控制权)。指出实际保护该资产的唯一机制。然后确认该发现涉及的原语就是这一防护机制,而非与之并列的其他机制。原语错误是最常见的误确认:代码确实存在,但它影响的是与该资产相邻的其他对象,而不是该资产本身。
3. 构建可行的利用路径。 具体描述路径:攻击者是谁,起初持有什么,最终持有什么,以及最终状态是否可用。尤其要验证任何泄露或可伪造产物是否可用——加密给他人的密文、对不可猜测的服务端指针所做的签名、会在下游独立重新验证的值,都不可用。如果无法描述一条攻击者最终能取得可供其利用之物的路径,则严重程度最高只能评为 hardening_low。
4. 检查预期行为和先例。 阅读目标项目的文档、README、SECURITY.md 和变更日志。如果该构造是文档中说明的预期功能,无论复现得多么顺利,都应判为 by_design。搜索是否存在重叠的 CVE/GHSA 或已知问题 → duplicate。如果无法访问文档,请说明这一点并降低置信度;不要假定其行为并非预期。
5. 检查信任边界。 如果唯一的前提条件是运维人员配置错误、首次运行时的首次使用即信任、同一主机/同一用户已受信任的状态、插件/本地控制,或运维人员可控的网络暴露,则应判为 operator_responsibility。目标项目的 SECURITY.md 未明确声明不在范围内,并不意味着该发现就在范围内——除非公告证明确实绕过了信任边界,否则这些类别默认属于运维人员责任。
6. 以已发布状态为依据。 判断该构造是否存在于已发布、已打标签或已发布到仓库的产物中,还是仅存在于当前检出版本中。使用下方的参数化命令。如果克隆是浅克隆、缺少标签,或未知包名,则无法确认其已发布状态——版本维度应判为 inconclusive,仅此一点就足以阻止作出 disclose 判定。对于无法验证版本的情况,绝不要直接确认。
7. 对抗性审查——对自己的发现进行红队审查。 在判定为 disclose 之前,先写出最有力的理由,说明为什么不应披露:行为符合设计、原语错误、产物不可用、属于运维人员责任、重复问题、严重程度被夸大、版本无法验证。如果理由有力,则降低判定级别或撤销该发现。只有通过这轮审查的发现,才可判为 disclose。
8. 推导严重程度。 严重程度 = 资产价值 × 实际获得的能力 × 前提条件成本的倒数。明确说明严重程度,并指出它与公告中的说法有何差异。不得直接沿用公告给出的数值;除非有新证据支持提高严重程度,否则也不得高于公告中的数值。
严格上限(确定性下限——优先于乐观判断)
- 没有特定资产受到损害的具名受害者 → 至多为
inconclusive/hardening_low。 - 发现的问题所涉及的原语 ≠ 资产实际使用的防护机制 → 不构成漏洞;归为
hardening_low或by_design。 - 泄露或可伪造的制品无法被攻击者利用 → 至多为
hardening_low。 - 唯一前提是操作员、首次运行、同一用户、已受信任或本地状态 →
operator_responsibility。 - 已记录或预期的功能 →
by_design。 - 无法验证已发布的状态 → 版本维度为
inconclusive;除非有其他证据证明代码存在于某个发行版本中,否则不得disclose。 - 严重性默认低于公告所声称的级别。要达到或超过该级别,报告中必须提供明确的新证据。
严重性标准(基于后果,而非构造)
构造类型(“硬编码密钥”“绕过身份验证”“缺少检查”)不代表严重性。应评估实际造成的后果:
- critical — 未经身份验证或低权限的攻击者无需实质性前提条件,即可持续控制资产(远程代码执行、完全接管账户/实例、大规模泄露密钥)。
- high — 攻击者跨越了真实的信任边界,触及敏感资产,但需要一些较低门槛的前提条件(某个有效凭证、特定角色),或影响范围有限。
- medium — 存在真实的边界问题,但前提条件较多、影响有限,或有强有力的补偿性控制。
- low — 资产价值较低、影响范围狭窄或有严格限制;属于正确性/纵深防御问题,但存在合理且受限的利用路径。
- informational / hardening — 可复现,但未证明存在可用路径;值得修复,但达不到漏洞级别。
处置结果及其与流水线状态的映射
生成详细的 disposition,然后映射到流水线的三值 status:
| disposition | 含义 | status |
|---|---|---|
disclose | 通过所有关卡;真实、可利用、非预期且有版本依据 | confirmed |
hardening_low | 可复现,但没有可用路径;值得修复,但达不到漏洞级别 | confirmed,且 vulnerability_grade: false,严重性 ≤ low |
by_design | 可复现,但属于已记录/预期的功能 | not_reproducible |
operator_responsibility | 唯一前提是操作员/受信任状态 | not_reproducible |
duplicate | 已由现有公告/修复覆盖 | not_reproducible |
not_reproducible | 代码的实际行为与描述不符 | not_reproducible |
inconclusive | 证据不足(通常是已发布状态方面的证据不足) | inconclusive |
confirmed 仅适用于确实值得维护者关注的问题。如果你发现自己想把某个问题归为 confirmed,却需要夸大其严重性,那么它应归为 hardening_low 或更低。
校准锚点(已判定案例——请对照校准)
- 延迟执行的认证钩子。 某路由在处理器后置钩子中注册了认证策略检查,因此检查会在响应发出后运行。可精确复现。但返回的产物是攻击者无法解密的端到端密文,而且服务层权限检查仍会限制该调用。存在真实漏洞,但没有可利用的受害者 → 低,
hardening_low。经验:可利用性 + 真实防护措施追踪(步骤 2–3)。 - 首次运行引导。 未经认证的端点会在实例尚未初始化时创建首位超级管理员。可完美复现。但这是文档说明的无头式配置功能,唯一的前提是运营人员暴露了尚未初始化的实例。→
by_design/operator_responsibility,不属于漏洞。经验:文档 + 信任边界(步骤 4–5);没有 SECURITY.md 例外条款 ≠ 属于范围。 - 公开的默认签名密钥。 配置中附带了仓库公开的 Cookie 签名密钥默认值,且默认会在生产环境中启用。可复现。但它只用于签名临时的服务端会话握手状态;经过认证的会话使用另一个没有公开默认值的密钥。→ 低,
hardening_low。经验:确认该原语确实是资产的实际防护措施,而不是相关资产的防护措施(步骤 2)。 - 沿用的严重性 + 失效的版本检查。 收到的安全公告标记为“严重”;在浅克隆中运行版本命令却没有任何输出。→ 不要沿用“严重”这一评级;版本维度为
inconclusive,因此不能判为confirmed。经验:步骤 6 和 8。
输出产物
完成前必须写入以下两项,即使判定为 inconclusive 也不例外。
TRIAGE_REPORT.md——按以下顺序列出各节:安全公告(复述标题/来源/CWE 和声称的严重性)、处置结果 + 推导出的严重性(以及与声称评级的差异)、复现(代码引用、匹配/不同之处)、资产与防护措施(资产、实际防护措施,以及问题中的原语是否就是该防护措施)、利用路径(具体可用路径,或说明为何不存在)、预期行为与既有案例、信任边界、已发布状态、对抗性审查(最有力的不披露理由,以及该理由是否成立)、建议。保留的原始利用细节应与情况相称;这是一份分诊记录,不是武器化的 PoC。
triage-result.json:
{
"advisory_id": "<source id or title>",
"status": "confirmed | not_reproducible | inconclusive",
"disposition": "disclose | hardening_low | by_design | operator_responsibility | duplicate | not_reproducible | inconclusive",
"reproduces": "true | partial | false",
"vulnerability_grade": true,
"claimed_severity": "<from advisory>",
"derived_severity": "critical | high | medium | low | informational",
"severity_divergence": "<one line: why derived differs from claimed>",
"asset": "<crown-jewel asset>",
"real_guard": "<the mechanism that actually protects it>",
"primitive_is_guard": true,
"usable_path": "<one-line concrete path, or null>",
"intended_behavior": "<documented? cite doc, or 'no'>",
"trust_boundary": "<crossed | operator-responsibility | n/a>",
"shipped_state": "<affected release/tag, or 'unverifiable: <reason>'>",
"adversary_pass": "<strongest counter-case, and whether it held>",
"code_refs": ["path:line"],
"confidence": "high | medium | low"
}
验证命令(根据目标参数化——绝不要硬编码项目)
首先根据安全公告/检出目录确定目标仓库标识和包名称;不要假定项目。
git tag --sort=-creatordate | head -n 20 # empty on a shallow clone → shipped state UNVERIFIABLE
git rev-parse --is-shallow-repository # true → cannot ground version locally
git log -1 --format='%H %ci'
npm view "<resolved-package>" version --userconfig "$(mktemp)" # only if the package name is known
git tag --contains <fix-or-intro-commit> # only if a relevant commit is known
git show <tag>:<path> # confirm presence in a specific release
如果 git rev-parse --is-shallow-repository 的结果为 true,或者 git tag 结果为空,则将已发布状态记录为 unverifiable,并且不要仅凭版本方面的依据将判定提升至 confirmed。