mcpField
M
mantis-report

mantis-report

github.com/google安全2.7k1.6k 次安装3 天前更新
代码仓库

关于 mantis-report

mantis-report 是面向开发者和相关方的安全报告技能,可将已验证的发现整理为 Markdown 审查报告,并纳入此前轮次仍未解决的问题及快照来源信息。

主要功能

  1. 01汇总整个安全检查周期的发现
  2. 02按发现身份去重
  3. 03按严重程度划分报告章节
  4. 04生成带快照标记的 Markdown 报告

适用场景

  1. 01根据已验证发现编制审查报告
  2. 02跨安全检查轮次跟踪未解决问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/google/mantis --skill mantis-report

安装后在 Claude Code 中输入/mantis-report确认已加载。

详细介绍

报告器(/mantis-report)

系统目标

安全报告专家。将复杂的技术发现日志综合整理为高质量、易读的审查报告,供开发者和利益相关者使用。

命令定义

  • 命令: /mantis-report
  • 描述: 生成易读的安全审查报告,其中包含已确认的发现和攻击链。

输入/输出约定

  • 读取:
    • workspace/findings/*.json(本轮的所有活动发现文件)。
    • workspace/archive/findings_pass_*/*.json(先前轮次归档的发现)和旧版 workspace/archive/loop*_findings/*.json。报告提供整个活动的全局视图:包含本轮的全部发现,以及先前轮次停止重试后沿用至今的发现(例如达到重试上限的发现),确保它们不会从报告中消失。
    • workspace/.mantis_state.json(用于跟踪当前循环轮次,并读取 vcs_info 和 active_snapshot {root、snapshot_id、snapshot_pinned} 以追溯来源)。
    • 每项发现的快照来源字段,全部为可选字段:discovery_commit、repro_snapshot_id、patch_base_snapshot。任何字段缺失或为空时,均显示为“(未记录)”——绝不能因此舍弃发现。
  • 写入:
    • workspace/report/review_packet_pass_<N>_<snapshot_tag>.md(带轮次和快照标签的 Markdown 报告)。对于未记录快照的旧版轮次,回退到不带后缀的 review_packet_pass_<N>.md。
    • 更新 workspace/report/review_packet-latest.md 的副本/符号链接。
  • 前提条件:
    • workspace/findings/ 或 workspace/archive/ 中存在经过校准和复现的发现。报告提供整个活动的全局视图:报告本轮或任何先前轮次发现的每项未解决发现的当前状态,每项发现仅保留其最新状态,并去重。已确认但未修复、且计划停止继续跟进的发现(例如达到 2 次尝试的重试上限)不会消失——此处会显示其最新的归档状态。
  • 幂等性保证:
    • 写入带轮次和快照标签的文件。原地覆盖 review_packet-latest.md。在同一快照上重新运行同一轮次时,会更新同一个带标签的文件。在不同快照上重新运行相同轮次编号时,会写入一个独立文件(<snapshot_tag> 后缀可防止不同快照间相互覆盖)。未记录快照的旧版轮次仍使用不带后缀的 review_packet_pass_<N>.md 文件名,并按原样原地覆盖。

说明

步骤 0 — 定位器解析。

LOCATOR RESOLUTION (before reading ANY target code or artifact):
0. ROLE: If this skill NEVER reads target source (report, calibrate, reflect),
   you are a FINDINGS-ONLY stage: skip steps 2-6; still read active_snapshot from
   state for provenance/annotation; NEVER stop merely because a code root is unset.
1. Determine CODE_ROOT, in this priority order:
   a. If --target_root is passed on THIS invocation, CODE_ROOT = --target_root.
      It is AUTHORITATIVE and OVERRIDES SNAPSHOT_ROOT and the state fallback
      (used when a caller hands you a prepared tree, e.g. a patched shadow).
   b. Else if --snapshot_root (or SNAPSHOT_ROOT) is passed, use it.
   c. Else read state_root/workspace/.mantis_state.json (state_root from
      --state_root if passed, else ./workspace/... relative to the current dir)
      -> active_snapshot.root / .snapshot_id / .snapshot_pinned.
   d. Else (no arg AND no readable active_snapshot): CODE_ROOT = current directory,
      treat snapshot_pinned = false (MODE-OFF). Do NOT stop.
2. SENTINEL CHECK (only if snapshot_pinned is true AND you did NOT take path 1a):
   verify CODE_ROOT/.mantis_snapshot_id exists and equals SNAPSHOT_ID. If missing
   or different -> STOP "snapshot sentinel mismatch". (A --target_root tree (1a) is
   deliberately mutated and is sentinel-EXEMPT.)
3. PATH FIELDS:
   - SNAPSHOT-RELATIVE (read under CODE_ROOT): code_paths entries; plan target_files
     that are file paths. Strip ONLY a trailing ":<digits>". A code_paths entry
     containing "://" is a URL/endpoint, NOT a file read. A code_paths entry that is
     NOT of the form <existing-path>:<integer> is a non-source LOCATOR
     (symbol/offset/endpoint): only check that the artifact/symbol exists; skip ALL
     line-range and line-existence logic.
   - STATE-RELATIVE (read/write under state_root/workspace, NEVER prefix CODE_ROOT):
     kb_references, repro_file_path, reattack_file_path, helper scripts, report
     files, and all state/findings JSON.
4. Never WRITE under CODE_ROOT when snapshot_pinned is true. Any command that
   compiles, generates, or writes artifacts MUST run in a PRIVATE SHADOW copy
   (mktemp -d from CODE_ROOT), never with cwd=CODE_ROOT. Read-only inspection may
   cd into CODE_ROOT.
5. VCS-METADATA CARVE-OUT: history-log extraction and any VCS diff/blame command
   run in the LIVE repository root (which still has .git/.hg/.repo), NOT CODE_ROOT
   (the snapshot copy strips VCS metadata). Do NOT stop merely because CODE_ROOT
   lacks .git/.hg/.repo.
6. Every shell command uses ABSOLUTE paths and sets its own working directory on
   that call. Do NOT assume the working directory persists between calls.

随后,以下仅针对发现的说明适用于报告器:

  • 报告器是一个仅处理发现的阶段(Block A,ROLE 步骤 0):跳过定位器步骤 2–6,不需要也不会解析 CODE_ROOT,并且绝不会因为代码根目录或哨兵未设置而停止。
  • 报告器仍会读取 workspace/.mantis_state.json 中的 active_snapshot(root、snapshot_id、snapshot_pinned)和 vcs_info 以追溯来源——用于构建页眉、顶部横幅和输出文件名。
  • 报告器接触的所有路径(workspace/findings/*.json、workspace/.mantis_state.json、workspace/report/*、workspace/archive/*)均相对于状态目录,绝不会加上 CODE_ROOT 前缀。

编写一份专业的 Markdown 报告,详细说明已验证/复现的漏洞和攻击链。

按以下步骤执行报告阶段:

  1. 加载发现——完整纳入本轮发现及沿用至今的未解决发现(从最新到最旧折叠;不使用脚本)。 按发现身份构建工作集,每项发现仅保留一次,且采用其最新状态: 相同缺陷判定条件(用于本阶段所有当前↔归档去重、折叠和抑制;在此处多报始终是安全的,绝不能隐藏真实发现):只有满足以下条件之一时,两个发现才属于相同缺陷:(i)它们的 id(UUID)完全相同;或(ii)以下三项全部成立——它们具有相同的非空 lineage_id,具有相同的非空 signature,并且它们的 code_paths 中至少有一项在包含末尾 :line 的比较下完全相同。否则,它们就是不同缺陷——两者都要呈现。绝不可仅凭 lineage_id 或 signature 就将两个发现视为相同缺陷:这两者的粒度都比缺陷的真实身份更粗(基于文件名生成的 lineage 可能会关联两个不同但同名的文件;signature 会去掉行号,因此同一文件中的不同缺陷可能发生冲突),仅凭其中任一项进行合并都可能悄无声息地丢弃真实发现。

    设计说明(重新锚定与折叠): mantis-plan 的重新锚定(阶段 2\)只提供用于引导重新发现的行号提示——它不会改写所携带发现的 code_paths。重新发现的发现会在当前快照的新行号处出现。由于折叠判定条件要求 code_paths 中包含行号且匹配,因此重新发现的发现不会与其祖先折叠(行号不同)。这种安全的多报会同时呈现两条记录,当前记录会显示新位置。未来阶段可以放宽判定条件:当两个发现具有相同的 signature 和 lineage_id,且确认祖先所在行已不存在于当前快照时,仅按路径匹配;但目前采用保守的行号匹配,以防任何静默丢弃风险。

    1. 读取所有处于活跃状态的 workspace/findings/*.json,并将每个活跃发现项都加入工作集,以其 id(UUID)为键——涵盖所有修复状态,这样本轮的 VERIFIED_SECURE/MITIGATION_PROPOSED 修复仍会连同其补丁显示在类别 1/2 中。切勿合并两个活跃发现项,即使它们的 lineage_id 或 signature 相同,也要将每个活跃的 id 保留为单独条目。
    2. 按轮次降序扫描 workspace/archive/findings_pass_<N>/(以及旧版 loop<N>_findings/)。仅当归档发现项仍处于开放状态(见第 4 条)、工作集中尚无与其属于同一漏洞的发现项(按上述判定条件),且尚未添加更早(轮次更高)的同一漏洞归档副本时,才添加该发现项。遇到的第一个副本即为最新状态;忽略较低目录中同一漏洞的后续副本。(只有真正被同一漏洞的新发现项取代时,才会抑制归档发现项;仅 lineage_id 或 signature 偶然相同不足以抑制。)
    3. 取代折叠(阶段 3): 如果某个归档发现项与当前发现项属于同一漏洞(判定条件 ii),则由当前发现项取代它——仅显示当前(最新)状态的单个条目;不要同时显示归档副本。如果不满足判定条件(例如文件重命名导致 signature 不同,或缺少 lineage_id),则将两者作为单独条目显示(宁可安全地多报告,也绝不隐瞒)。
      • 防止漏报: 如果当前(取代旧项的)发现项未通过可执行判定条件(下方第 4 条),但其归档祖先项原本可以通过(例如,祖先项已 reproduced 且处于开放状态,但当前轮次在新快照上的复现因临时构建/环境故障而变为 not_attempted),不要让这种临时降级抑制已确认开放的漏洞。应在报告中保留祖先项最后一次确认的状态,并附注“开放 — 新快照上的复现待处理”,以免此前已确认的漏洞悄然从报告中消失。当前发现项的较新元数据(例如更新后的 code_paths 行号)仍可作为注释附上,但显示的判定结果/状态必须是祖先项最后一次确认的状态,绝不能是临时降级后的状态。
    4. 可执行性/质量判定条件(适用于活跃和归档发现项):仅当发现项属于漏洞利用链(存在 constituent_findings,或标题/历史记录中包含“Exploit Chain”)、或 repro_status 为 reproduced、或 repro_status 为 statically_confirmed 且包含实证执行证据(外部堆栈跟踪、sanitizer 跟踪(ASan/UBSan/MSan/TSan)或崩溃日志)时,才纳入报告。不要纳入误报、NON_VIABLE、DUPLICATE、failed_to_reproduce,或缺少实证跟踪记录的普通 statically_confirmed 发现项。
    5. 开放状态判定条件(仅适用于第 2 条中的归档结转):归档发现项只有在满足第 4 条,且 patch_status 不为 VERIFIED_SECURE/MITIGATION_PROPOSED、status 不为 FALSE_POSITIVE/DUPLICATE,并且 production_viability 不为 NON_VIABLE 时,才视为“仍处于开放状态”。(无论 patch_status 如何,都会载入活跃发现项,以便本轮修复仍然显示;已修复的归档发现项不会在每轮中重复列出——可使用可选的“本次活动中已解决”汇总,查看累计修复情况。)
    6. 规模控制: 每次处理一个目录,并按最新优先的顺序处理;切勿一次性载入整个归档。
    • 严重性筛选: 从报告正文中排除优先级为 "LOW" 的发现项。必须在报告最末尾单独设置“附录:低优先级发现项”章节,列出这些较低优先级问题,使报告正文聚焦于高风险问题。
  2. 提取关键资料: 对于每项复现的发现,提取并整理以下内容:

    • 标头元数据: 标题、ID(UUID)、推断的暴露程度、最终风险评分和定性优先级。
    • 活动溯源: 为每项未关闭的发现标注首次发现时所属的轮次和当前轮次(例如 discovered pass 2 · still open as of pass 7),以便清楚显示延续至今的发现。首次发现 = 该发现 history 条目中最小的 pass_number(或包含该发现的编号最小的归档目录所对应的 pass_number);当前状态 = 上述合并操作中保留的副本。
    • 重复项提示: 如果发现包含 possible_duplicate_of 字段(该字段由 mantis-dedupe 在跨轮次候选未匹配时设置),则发出提示说明: Possibly related to finding <UUID> (cross-pass candidate; snapshots differ — not confirmed duplicate). 这样利益相关方就能看到这条回归指针提示。
    • 发现快照: 为该发现输出 Discovery Snapshot: <discovery_commit>。如果 discovery_commit 缺失或为空,则输出 Discovery Snapshot: (legacy — not recorded)。不得因缺少此字段而省略或删除该发现。
    • 漏洞描述与影响: 清楚说明漏洞及其对系统造成的具体影响。
    • 复现证据:
      • PoC 脚本路径(repro_file_path)和执行命令(run_command)。
      • 清晰展示成功触发利用的 stdout/stderr 片段(repro_output)。
      • 证据基准: 使用该证据所采集的快照标注复现证据:Evidence base: <repro_snapshot_id>。如果 repro_snapshot_id 缺失或为空,则写入 Evidence base: (not recorded)。不要假定它与标头/轮次快照相同。
    • 风险依据: 独立验证理由(reasoning)、生产环境可行性理由(critic_reasoning)以及轰动性因素分析(outrage_commentary)。
    • 修复措施与补丁:
      • 建议的缓解策略。
      • 已验证的补丁差异(patch_diff)以及重新攻击状态,以证明修复具有韧性。
      • 应用于: 使用补丁所针对的快照标注补丁差异:Apply against: <patch_base_snapshot>。如果 patch_base_snapshot 缺失或为空,则写入 Apply against: (not recorded)。如果 patch_base_snapshot 存在且与该发现的 discovery_commit 不同,则添加一行警告,说明该差异是针对不同快照生成的,可能无法干净地应用于发现快照。
    • PII 与机密信息脱敏: 在将任何发现数据(包括描述、PoC 脚本/命令和复现日志)写入报告前,必须扫描并脱敏任何硬编码的 API 密钥、令牌、凭据、PII(姓名、电子邮件地址、电话号码)、内部主机名/域名,以及具有过强攻击性的载荷参数,并将其替换为 <REDACTED_SECRET>、<REDACTED_PII>、<REDACTED_INTERNAL_HOST> 或 <REDACTED_PAYLOAD> 等标准占位符,确保报告可安全地广泛分发。
  3. 生成审查资料包:

    • 报告标题与免责声明: 在报告最顶部(执行摘要之前):

      快照溯源横幅 — 在下方第 1 项之前、报告最顶部按以下顺序输出这些横幅,每个横幅单独放在一个引用块中: a. 非权威 / HALT 横幅(3 状态规则)。 从 workspace/.mantis_state.json 读取 active_snapshot。 - 如果 active_snapshot 不存在(MODE-OFF — 未请求 --sync, 即今天的默认行为):不要输出此横幅。本次运行与今天的行为逐字节一致; 报告中的 VERIFIED_SECURE 发现和其他判定与今天一样有效。在此处输出 NON-AUTHORITATIVE 横幅会与本次运行生成的判定相矛盾。 - 如果 active_snapshot 存在,但 snapshot_pinned 为 false(HALT 模式):将以下内容作为报告的第一行输出: > **WARNING — NON-AUTHORITATIVE RESULTS:** The target could not be pinned to an immutable snapshot for this pass (HALT mode: the tree raced or was too big / live / copy-failed). Findings may not correspond to a stable, reproducible tree, and the ABSENCE of findings in this report does NOT indicate the target is secure. Treat all results as provisional. 当 active_snapshot 不存在(MODE-OFF)或 active_snapshot.snapshot_pinned 为 true(PINNED)时,省略此横幅。

      b. 工作树脏状态警告。 如果 vcs_info.dirty 为 true,输出: > **WARNING — DIRTY WORKING TREE:** The target had uncommitted local modifications when it was scanned. Results reflect that exact working tree (captured by content hash), NOT a clean committed revision. The recorded commit alone will not reproduce this state.

      c. 混合快照横幅。 令 HEADER_SID = active_snapshot.snapshot_id。如果 HEADER_SID 存在且非空,并且任一已纳入的发现所含 discovery_commit 缺失、为空或与 HEADER_SID 不完全相同,则输出: > **WARNING — MIXED SNAPSHOTS:** This report combines findings discovered on different code snapshots (e.g. findings retried from earlier passes). The pass snapshot is <HEADER_SID>. Consult each finding's "Discovery Snapshot" before acting; line numbers and code context may differ between snapshots. 仅将快照 ID 作为完整字符串进行比较 — 不进行模糊匹配或前缀匹配。

      1. 显示从 workspace/.mantis_state.json 中的 "vcs_info" 读取的目标代码库版本信息:

        • 如果 "vcs_type" 为 "git",显示: Target Version: Git branch [branch] at commit [commit_hash] [(dirty) if dirty is true].
        • 如果 "vcs_type" 为 "hg",显示: Target Version: Mercurial branch [branch] at revision [commit_hash] [(dirty) if dirty is true].
        • 如果 "vcs_type" 为 "multi-vcs",显示: Target Version: Multi-VCS (repo) manifest [revision] [(dirty) if dirty is true].
        • 如果 "vcs_type" 为 "none",显示: Target Version: None (No version control detected).
        • 如果 "vcs_type" 为 "unknown",或者 vcs_info 缺失,显示: Target Version: Unknown (VCS detection failed/error)。

        在 Target Version: 行之后的第二行附上本次通行的快照标识:

        • 如果 active_snapshot.snapshot_id 存在且非空,写入: Snapshot ID: [snapshot_id] (pinned: [snapshot_pinned]).
        • 如果 active_snapshot 不存在或 snapshot_id 为空,写入: Snapshot ID: (legacy — snapshot not recorded). 这仅用于显示溯源信息; 不会用于筛选或丢弃任何发现。
      2. 加入一条醒目的免责声明,说明:“本报告由 Mantis AI 自动生成。所有发现和补丁均由 AI 生成,必须由安全或相关领域专家在部署或披露之前进行人工核验。”

    • 按补丁状态分组(互斥): 按发现的问题分组,整理执行摘要表和报告正文。必须从这些主要分组中排除利用链,并且只能在专门的“利用链(未进行端到端复现)”部分报告。 对于标准(非链)发现,按修复状态分为以下三个互不重叠的类别:

      1. 类别 1:补丁已独立验证:patch_status 为 "VERIFIED_SECURE" 的发现。
      2. 类别 2:已提出补丁/已确定缓解措施:patch_status 属于 ["MITIGATION_PROPOSED", "VERIFICATION_INCOMPLETE"],或(存在 patch_diff 且 patch_status 未设置/为空)。
      3. 类别 3:未修补/验证失败:patch_status 属于 ["VERIFICATION_FAILED", "ERROR"],或(不存在 patch_diff 且 patch_status 未设置/为空)。
    • 专门的利用链部分: 创建专门针对利用链、标题为 "Exploit Chains (Not End-to-End Reproduced)" 的部分。在此记录每个链式发现,列出其标题、定性优先级、风险评分,并详细说明其组成发现(包括 ID 和各自状态)。不要将利用链与类别 1、2 或 3 中的标准发现混在一起。

    • 按轮次编号输出: 每次执行时,不要覆盖同一个 review_packet.md 文件。请改为确定流水线当前运行/轮次编号 N(从 workspace/.mantis_state.json 中的 "pass_number" 解析。如果缺失或无效,则扫描 workspace/archive/,查找与 findings_pass_N 或 loopN_findings 匹配的文件夹,并将 N 设为 max_found + 1;如果没有归档,则默认为 1)。然后根据 active_snapshot.snapshot_id 得出 <snapshot_tag>:保留快照 ID 的原始内容,并将所有不属于 [A-Za-z0-9.-] 的字符替换为单个下划线 _(不要截断——结果远低于任何文件名长度限制)。将报告写入:

      • 当 active_snapshot.snapshot_id 存在且非空时,写入 workspace/report/review_packet_pass_<N>_<snapshot_tag>.md(例如 review_packet_pass_1_content_9f86d081884c...md)。<snapshot_tag> 后缀可确保在不同快照上重复使用同一轮次编号时,会写入不同文件,不会覆盖之前的报告。
      • 当 active_snapshot 不存在或 snapshot_id 为空时,写入 workspace/report/review_packet_pass_<N>.md(不带后缀,完全沿用旧名称),以保持当前的向后兼容行为。
    • 最新副本/符号链接: 写入上述按轮次编号的报告后,将该确切文件(无论是否带有 <snapshot_tag> 后缀)更新为符号链接或副本,路径为 workspace/report/review_packet-latest.md,以确保始终可以访问最新版本。review_packet-latest.md 名称保持不变,仍作为下游使用方的稳定入口。

    • 使用简洁、专业的 Markdown 格式,设置清晰的标题、用于展示元数据的表格,以及为日志和差异内容提供语法高亮的代码块。

    • 在顶部包含高层级的执行摘要表格,列出所有纳入报告的发现及其优先级和风险评分。

    • 可选部分(建议添加):

      • 本次活动中已解决: 使用相同的折叠方式进行的简短汇总,但筛选出 patch_status 为 VERIFIED_SECURE 或 MITIGATION_PROPOSED 的发现项。这让相关方能与未解决的发现项并列看到一份直观的“修复了什么”视图。
      • 未解决 — 已达重试上限: 一个标注块,列出复现尝试次数已达上限的未解决发现项。该次数不是发现项 JSON 上的字段;它存放在缓存文件 state_root/workspace/archive/.repro_attempts.json 中,以每个发现项的 signature 为键(若 signature 缺失,则以其计算出的 stable_key = normalized_title + "@" + primary_file_path 为键——与 mantis-reproduce 相同的键选择方式)。对于工作集中的每个未解决发现项,在该缓存中查找其 signature(或 stable_key 回退值);若缓存值已达重试上限,则将该发现项纳入此标注块。按照 schema 的值形态规则读取缓存值:裸整数 V 表示 {count: V, last_snapshot: UNKNOWN};对象表示 {count: V.count, last_snapshot: V.last_snapshot or UNKNOWN}。若缓存文件缺失或发现项的键不存在,则将其次数视为 0(不要在此列出)。这些是规划器已停止携带的条目

    说明

    去重注意事项: 去重依据发现项身份,按照本阶段顶部的 SAME-BUG PREDICATE:两个发现项仅当满足以下任一条件时才折叠——(i) 它们共享完全相同的 id(UUID),或 (ii) 以下三者全部成立——共享非空的 lineage_id、共享非空的 signature,且至少有一个包含行的 code_paths 匹配。切勿仅凭 lineage_id 或仅凭 signature 折叠(基于文件名派生的 lineage 可能把两个不同的同名文件关联起来;signature 会去掉行号,因此会在同一文件中不同的 bug 之间发生碰撞)——仅凭其中任一项进行折叠可能会悄无声息地丢掉一个真实的发现项。一个新 UUID 下重新发现的 bug,若不满足条件 (ii)——如回归、导致行号偏移的文件重命名,或非确定性的重复发现——将作为与其归档祖先分开的独立条目列出:宁可多报(安全),绝不隐藏。随着稳定的发现项签名和 lineage 跟踪落地(阶段 3),重新发现的发现项仅当完全满足条件 (ii) 时才会折叠进其祖先的单个条目;仅 UUID 匹配仍是针对遗留/未升级发现项的安全分支。

    • review_packet-latest.md 具有权威性: 请注意,review_packet-latest.md 现在是整个活动当前未解决状态的权威来源(而不仅是最新一趟)。各趟的 review_packet_pass_<N>_<snapshot_tag>.md 文件保持原样,供历史参考。

评论

支持 Markdown