关于 mantis-report
mantis-report 是面向开发者和相关方的安全报告技能,可将已验证的发现整理为 Markdown 审查报告,并纳入此前轮次仍未解决的问题及快照来源信息。
主要功能
- 01汇总整个安全检查周期的发现
- 02按发现身份去重
- 03按严重程度划分报告章节
- 04生成带快照标记的 Markdown 报告
适用场景
- 01根据已验证发现编制审查报告
- 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 报告,详细说明已验证/复现的漏洞和攻击链。
按以下步骤执行报告阶段:
-
加载发现——完整纳入本轮发现及沿用至今的未解决发现(从最新到最旧折叠;不使用脚本)。 按发现身份构建工作集,每项发现仅保留一次,且采用其最新状态: 相同缺陷判定条件(用于本阶段所有当前↔归档去重、折叠和抑制;在此处多报始终是安全的,绝不能隐藏真实发现):只有满足以下条件之一时,两个发现才属于相同缺陷:(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,且确认祖先所在行已不存在于当前快照时,仅按路径匹配;但目前采用保守的行号匹配,以防任何静默丢弃风险。- 读取所有处于活跃状态的
workspace/findings/*.json,并将每个活跃发现项都加入工作集,以其id(UUID)为键——涵盖所有修复状态,这样本轮的VERIFIED_SECURE/MITIGATION_PROPOSED修复仍会连同其补丁显示在类别 1/2 中。切勿合并两个活跃发现项,即使它们的lineage_id或signature相同,也要将每个活跃的id保留为单独条目。 - 按轮次降序扫描
workspace/archive/findings_pass_<N>/(以及旧版loop<N>_findings/)。仅当归档发现项仍处于开放状态(见第 4 条)、工作集中尚无与其属于同一漏洞的发现项(按上述判定条件),且尚未添加更早(轮次更高)的同一漏洞归档副本时,才添加该发现项。遇到的第一个副本即为最新状态;忽略较低目录中同一漏洞的后续副本。(只有真正被同一漏洞的新发现项取代时,才会抑制归档发现项;仅lineage_id或signature偶然相同不足以抑制。) - 取代折叠(阶段 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发现项。 - 开放状态判定条件(仅适用于第 2 条中的归档结转):归档发现项只有在满足第 4 条,且
patch_status不为VERIFIED_SECURE/MITIGATION_PROPOSED、status不为FALSE_POSITIVE/DUPLICATE,并且production_viability不为NON_VIABLE时,才视为“仍处于开放状态”。(无论patch_status如何,都会载入活跃发现项,以便本轮修复仍然显示;已修复的归档发现项不会在每轮中重复列出——可使用可选的“本次活动中已解决”汇总,查看累计修复情况。) - 规模控制: 每次处理一个目录,并按最新优先的顺序处理;切勿一次性载入整个归档。
- 严重性筛选: 从报告正文中排除优先级为
"LOW"的发现项。必须在报告最末尾单独设置“附录:低优先级发现项”章节,列出这些较低优先级问题,使报告正文聚焦于高风险问题。
- 读取所有处于活跃状态的
-
提取关键资料: 对于每项复现的发现,提取并整理以下内容:
- 标头元数据: 标题、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)。不要假定它与标头/轮次快照相同。
- PoC 脚本路径(
- 风险依据: 独立验证理由(
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>等标准占位符,确保报告可安全地广泛分发。
-
生成审查资料包:
-
报告标题与免责声明: 在报告最顶部(执行摘要之前):
快照溯源横幅 — 在下方第 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 作为完整字符串进行比较 — 不进行模糊匹配或前缀匹配。-
显示从
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). 这仅用于显示溯源信息; 不会用于筛选或丢弃任何发现。
- 如果
-
加入一条醒目的免责声明,说明:“本报告由 Mantis AI 自动生成。所有发现和补丁均由 AI 生成,必须由安全或相关领域专家在部署或披露之前进行人工核验。”
-
-
按补丁状态分组(互斥): 按发现的问题分组,整理执行摘要表和报告正文。必须从这些主要分组中排除利用链,并且只能在专门的“利用链(未进行端到端复现)”部分报告。 对于标准(非链)发现,按修复状态分为以下三个互不重叠的类别:
- 类别 1:补丁已独立验证:
patch_status为"VERIFIED_SECURE"的发现。 - 类别 2:已提出补丁/已确定缓解措施:
patch_status属于["MITIGATION_PROPOSED", "VERIFICATION_INCOMPLETE"],或(存在patch_diff且patch_status未设置/为空)。 - 类别 3:未修补/验证失败:
patch_status属于["VERIFICATION_FAILED", "ERROR"],或(不存在patch_diff且patch_status未设置/为空)。
- 类别 1:补丁已独立验证:
-
专门的利用链部分: 创建专门针对利用链、标题为
"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文件保持原样,供历史参考。
-