安全与风控
已有多个已单独验证的安全发现时,用…
适用于验证阶段之后,检查多个低危/分散漏洞能否串联成更高影响的漏洞;不用于初始代码库审计或编写补丁。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
已有多个已单独验证的安全发现时,用 /m特定
解决思路
- 调用 `/mantis-chain`;系统目标是 Exploit Chain Architect:分析已单独验证的安全发现和历史知识库原语,识别并构造复杂多步利用链。
- 参数处理:所有参数可选,由 orchestrator 按 harness 生命周期契约传入:`--snapshot_root`/`SNAPSHOT_ROOT`(本次 pass 固定的不可变代码快照根,供 Block A 使用);`--snapshot_id`/`SNAPSHOT_ID`(本次 pass 快照身份字符串,供 Block A sentinel 与 Block B match check 使用);`--state_root`(`workspace/` 的父目录,缺省当前目录,见 Block A step 1c/1d);`--target_root`(已准备树,覆盖 snapshot root,本阶段很少用,Block A step 1a 可识别)。均未传时 Block A 回退到 `workspace/.mantis_state.json` 的 `active_snapshot`;若也不存在则 MODE-OFF(`snapshot_pinned = false`),行为同今天。
- 输入:读取 `workspace/findings/` 中通过验证的 finding JSON:`status` 为 `VALID`,`viability` 为 `VIABLE`、`CONDITIONAL_VIABLE` 或 `SAMPLE_OR_TEST`。
- 输入:读取 `workspace/kb/entities/*.md` 与 `workspace/kb/vulnerabilities/*.md` 知识库原语。
- 输入:读取 `workspace/.mantis_state.json` 以跟踪当前 loop pass。
- 输出:将全新的 exploit chain finding JSON 写入 `workspace/findings/<new_uuid>.json`;原始 finding 保持不变。
- 前置条件:`workspace/findings/` 中必须存在已验证或 viable 的 finding。
- 幂等保证:写新 chain 前,比较组成 finding 序列,检查现有 chain finding。扫描当前 `workspace/findings/`、所有 `workspace/archive/findings_pass_*/`、以及遗留 `workspace/archive/loop*_findings/`;这些是 STATE-RELATIVE,绝不在前面加 `CODE_ROOT`。
- 幂等保证:任何 `constituent_findings` 数组存在且非空的 finding 都视为 chain JSON。若任一位置已存在完全相同的有序组成序列,则跳过创建重复项。
- 幂等保证(首选 signature 键,带 code_paths tiebreak):若所有组成 finding 都有 `signature` 字段,则比较有序组成 `signature` 序列(不是 UUID)。仅当有序 `signature` 序列相等,且对每一对应组成对,至少有一个 `code_paths` 条目(包含行号,即连同尾部 `:line` 一起比较)完全相同,才视为同一 chain 并跳过创建。
- 幂等保证:若 signature 序列匹配但任一对应组成 finding 的 `code_paths` 不同,则 chain 不同,创建新 chain。过度报告是安全的;`signature` 冲突绝不能抑制真正新的利用链,因为 `signature` 会去掉行号,可能在同文件不同 bug 间冲突。
- 幂等保证(UUID 回退):若任一组成 finding 缺少 `signature` 字段,则回退为精确比较有序组成 UUID 序列(当前行为)。保留 legacy/un-upgraded finding 的行为。
- 幂等保证:带稳定 finding signatures 时 archive 扫描完全有效:组成 signature 相同的两个 chain 能跨 pass 正确去重。signature 缺失时扫描无害:不会错误抑制合法新 chain(不会静默丢结果),只防止 resumed/rerun pass 内 exact-UUID 重复。若 `workspace/archive/` 不存在,视 archived set 为空并继续。
- Locator Resolution 先运行:对所有 stage,先执行定位器解析。本技能不是 findings-only stage(不是 report/calibrate/reflect),所以 Block A 运行步骤 1–6,并从 `--snapshot_root`/`--snapshot_id`/state `active_snapshot` 解析 `CODE_ROOT`、`SNAPSHOT_ID`、`snapshot_pinned`。
- Locator Resolution step 0:ROLE:若技能从不读取目标源码(report、calibrate、reflect),则为 FINDINGS-ONLY stage:跳过步骤 2-6;仍从 state 读 `active_snapshot` 用于 provenance/annotation;绝不因 code root 未设置就停止。但 mantis-chain 不是 findings-only。
- Locator Resolution step 1:按优先级确定 `CODE_ROOT`:a. 若本次调用传 `--target_root`,`CODE_ROOT = --target_root`,它权威且覆盖 `SNAPSHOT_ROOT` 和 state fallback(用于调用方给准备好的树,如 patched shadow)。b. 否则若传 `--snapshot_root`/`SNAPSHOT_ROOT`,使用它。c. 否则读 `state_root/workspace/.mantis_state.json`(`state_root` 来自 `--state_root`,否则当前目录下 `./workspace/...`),取 `active_snapshot.root`/`.snapshot_id`/`.snapshot_pinned`。d. 否则(无参数且无可读 `active_snapshot`):`CODE_ROOT = 当前目录`,`snapshot_pinned = false`(MODE-OFF)。不要停止。
- Locator Resolution step 2:若 `snapshot_pinned` 为 true 且未走 1a,则做 SENTINEL CHECK:验证 `CODE_ROOT/.mantis_snapshot_id` 存在且等于 `SNAPSHOT_ID`。缺失或不同则停止并报 `snapshot sentinel mismatch`。`--target_root` 树(1a)故意被修改,sentinel-EXEMPT。
- Locator Resolution step 3:PATH FIELDS:SNAPSHOT-RELATIVE(在 `CODE_ROOT` 下读取):`code_paths` 条目;`plan target_files` 中属于文件路径的项。只剥离尾部 `:<digits>`。包含 `://` 的 `code_paths` 条目是 URL/endpoint,不是文件读取。非 `<existing-path>:<integer>` 形式的 `code_paths` 条目是非源码 LOCATOR(symbol/offset/endpoint):只检查 artifact/symbol 存在;跳过所有 line-range 和 line-existence 逻辑。STATE-RELATIVE(在 `state_root/workspace` 下读/写,绝不在前面加 `CODE_ROOT`):`kb_references`、`repro_file_path`、`reattack_file_path`、helper scripts、report files、以及所有 state/findings JSON。
- Locator Resolution step 4:`snapshot_pinned` 为 true 时绝不在 `CODE_ROOT` 下写入。任何编译、生成或写 artifact 的命令 MUST 在私有 shadow copy 中运行(从 `CODE_ROOT` 用 `mktemp -d`),绝不以 `cwd=CODE_ROOT`。只读检查可以 `cd` 到 `CODE_ROOT`。
- Locator Resolution step 5:VCS-METADATA CARVE-OUT:历史日志提取及任何 VCS diff/blame 命令在 LIVE repository root(仍有 `.git/.hg/.repo`)运行,不在 `CODE_ROOT`(快照副本会剥离 VCS metadata)。不要仅因 `CODE_ROOT` 缺少 `.git/.hg/.repo` 而停止。
- Locator Resolution step 6:每个 shell 命令使用 ABSOLUTE paths,并在该次调用中设置自己的工作目录。不要假设工作目录在调用之间保持。
- CURRENT-PASS CHECK(防御性;绑定保证在 harness per `mantis-pipeline-adapter` Scenario 2):若 `active_snapshot` 存在且 `active_snapshot.pass != state.pass_number`,视 snapshot 对本 pass STALE——停止 `stale active_snapshot: pass mismatch`,或降级为 HALT(`snapshot_pinned` 实际 false:无权威 verdict,Block B NOT_MATCHED,reproduce `not_attempted`)。这捕获 custom harness 在 Stage 15 pass increment 后仍保留 `active_snapshot` 而未 re-pin。参考 meta-agent 每 pass re-pin,所以那里不会触发。Block B 自身无法检测(它只认 `snapshot_id`,不感知 `pass`)。
- Stage-specific notes for Block A:`mantis-chain` 不是 findings-only stage,因此 Block A 运行步骤 1–6,并从 `--snapshot_root`/`--snapshot_id`/state `active_snapshot` 解析 `CODE_ROOT`、`SNAPSHOT_ID`、`snapshot_pinned`。
- Stage-specific notes for Block A:本阶段只向 `workspace/findings/` 写新的 finding JSON(STATE-RELATIVE,Block A step 3)。它从不写 `CODE_ROOT`,因此 Block A step 4 自然满足。若可选地重新检查某组成 finding 的 `code_paths` 以 sanity-check chain,则在 `CODE_ROOT` 下按 SNAPSHOT-RELATIVE 读取(Block A step 3),绝不 cd-and-write 到那里。
- Stage-specific notes for Block A:chain finding 的 `code_paths` 从其组成 finding 原样 COPY(它们已是 SNAPSHOT-RELATIVE)。不要重新加前缀、重新解析或重新编号。
- Snapshot Match Check:用于决定 MATCHED vs NOT_MATCHED:1. 若 `snapshot_pinned` 为 false -> NOT_MATCHED,停止。2. 读 `F.discovery_commit`:缺失、空或字面量 `MIXED` -> NOT_MATCHED;不精确等于 `SNAPSHOT_ID` -> NOT_MATCHED;精确等于 `SNAPSHOT_ID` -> MATCHED。没有其他路径到 MATCHED;绝不模糊比较。全局“默认字段并继续”的 backward-compat 规则不适用于 `discovery_commit`:缺失 = NOT_MATCHED。没有单独的 dirty gate:dirty tree 的 `SNAPSHOT_ID` 已嵌入 working-tree content hash,因此 within-pass findings MATCH,cross-pass bare-commit findings 不 MATCH。
- Snapshot Match Check:对 Step 1 中每个候选组成 finding 运行一次 Block B,使用该 finding 的 `discovery_commit` 作为 `F.discovery_commit`。
- 执行 Step 1 Load Primitives & Validated Findings:读取 `workspace/findings/` 中的 JSON 文件。过滤通过验证的 finding:`status` 为 `VALID`,`viability` 为 `VIABLE`、`CONDITIONAL_VIABLE` 或 `SAMPLE_OR_TEST`。
- 执行 Step 1 Snapshot eligibility gate(根据 `active_snapshot` 是否存在分支,3-state):MODE-OFF(state 中没有 `active_snapshot`,未请求 `--sync`,当前默认):完全跳过此 gate;通过上述 validation/viability 过滤的每个 finding 都是 eligible constituent,和今天一样正常构建 chain。
- 执行 Step 1 Snapshot eligibility gate HALT(`active_snapshot` 存在但 `snapshot_pinned == false`):本 pass 不构建任何 chain。HALT 中 finding 的 locators 和 pre/post-conditions 可能过期(树竞态或无法 pin),因此不能产生权威 chain verdict。记录 `no chain: HALT mode (active_snapshot present, snapshot_pinned=false)` 并干净停止 chaining stage(不产生 chain 文件)。这镜像 minimum-eligibility guard:chain 需要 proven-against-snapshot constituents,HALT 无法提供。
- 执行 Step 1 Snapshot eligibility gate PINNED(`active_snapshot` 存在且 `snapshot_pinned == true`):对每个此类 finding 运行 Snapshot Match Check (Block B),使用其 `discovery_commit`。只保留返回 MATCHED 的 finding 作为 eligible constituents。返回 NOT_MATCHED 的(包括 `discovery_commit` 缺失/空/字面量 `MIXED`/与当前 `SNAPSHOT_ID` 不同)是针对不同代码快照发现的;其 `file:line` locators 和 pre/post-conditions 可能不再成立,因此本 pass 绝不能用作 chain link。
- 执行 Step 1 Minimum-eligibility guard:若剩下少于 2 个 eligible constituents,则本 pass 不要构造任何 chain——chain 至少需要两个在同一快照上证明的 link。记录 `no chain: fewer than 2 snapshot-matched constituents` 并干净停止 chaining stage(不是错误;只是不产生 chain 文件)。这镜像今天少于两个可 chain finding 时的行为。
- 执行 Step 1:读取 Markdown Knowledge Base(`workspace/kb/entities/` 和 `workspace/kb/vulnerabilities/`),识别本身不是 bug、但可作为 stepping stones 的架构原语(例如 `User controls file upload path`、`Service runs as root`)。
- 执行 Step 2 Cross-Finding Analysis(The Chaining Matrix):分析每个已验证 finding 的 preconditions 和 postconditions。
- 执行 Step 2:询问:Finding A 的输出或副作用能否满足触发 Finding B 所需的严格 precondition?
- 执行 Step 2 示例链:Path Traversal + Loose Permissions = RCE:低危 path traversal (Finding A) 允许写 `/tmp`,但单独 misconfiguration (Finding B) 允许 cron job 执行 `/tmp` 中脚本。
- 执行 Step 2 示例链:XSS + CSRF = Account Takeover:存储型 XSS (Finding A) 可用于窃取 anti-CSRF token 以执行状态变更动作 (Finding B)。
- 执行 Step 2 示例链:Info Leak (Memory Revelation) + Buffer Overflow = ASLR Bypass:info leak (Finding A) 泄露 base pointers,满足利用 stack buffer overflow (Finding B) 的 precondition。
- 执行 Step 3 Construct Super Findings:若发现可行 exploit chain,不要修改或删除原始孤立 finding。它们仍需单独 patch。
- 执行 Step 3:在 mint UUID 之前运行 idempotency check:应用 Idempotency Guarantee——扫描当前 `workspace/findings/`、`workspace/archive/findings_pass_*/`、遗留 `workspace/archive/loop*_findings/`,查找组成序列等于本 chain 有序组成序列的 chain。若所有组成都有 `signature`,比较有序 `signature` 序列,并要求 Idempotency Guarantee 中每个组成的 line-inclusive `code_paths` tiebreak(仅 signature-sequence 匹配不够,不能跳过);若任一组成缺少 `signature`,回退到有序组成 UUID 序列(今天行为)。只有匹配满足 tiebreak 时才 SKIP 此 chain(不创建文件),继续下一个候选。
- 执行 Step 3:否则生成 net-new UUID 并创建新 finding JSON 文件 `workspace/findings/<new_uuid>.json`。
- 执行 Step 3 Constituent Findings:必须在结构化 `constituent_findings` 属性记录组成 finding UUID 数组(例如 `[UUID_A, UUID_B]`),清晰记录 exploit chain 的 link。
- 执行 Step 3 Determine Discovery Snapshot (`discovery_commit`):从 ELIGIBLE constituents(Step 1 保留的)设置 chain finding 的 `discovery_commit`。
- 执行 Step 3 `discovery_commit` MODE-OFF short-circuit(3-state rule):若 state 中 `active_snapshot` 缺失(MODE-OFF,未请求 `--sync`),在 chain finding 上完全 OMIT `discovery_commit`。MODE-OFF 中 researcher 对每个组成都 OMIT `discovery_commit`(`researcher:317,340-341`: “OMIT this key entirely if active_snapshot is absent or snapshot_pinned is false”),所以每个组成都 missing/empty。若用下面的 SAME/MIXED 逻辑会给每个 chain 写字面量 `MIXED`——这是 snapshot-era artifact,Phase 1 不存在,违反 MODE-OFF 的 byte-for-byte today's behavior 保证(`schema.json:4`)。chain 自己的 schema 注释(`chain:307`)说 “Absent on legacy/unpinned runs”,确认 MODE-OFF 预期是 omit 而非 `MIXED`。功能影响低(`schema.json:232` 把 absent 和 `MIXED` 都视为 NOT_MATCHED),但 mode purity 重要。MODE-OFF 不要写 `MIXED` 或任何值。
- 执行 Step 3 `discovery_commit`:若所有 eligible constituents 有相同的非空 `discovery_commit` 值,把 chain 的 `discovery_commit` 设为该精确字符串。
- 执行 Step 3 `discovery_commit`:若 constituents 的 `discovery_commit` 值彼此不同,或任一 eligible constituent 的 `discovery_commit` 缺失/空(仅在 PINNED/HALT 可达——MODE-OFF 已由上面 short-circuit OMIT 字段),把 chain 的 `discovery_commit` 设为字面量字符串 `MIXED`。不要发明、哈希或模糊归一化此值——复制精确字符串或写字面量 `MIXED`。理由:pinned mode 下每个 eligible constituent 都 MATCHED,所以都共享当前 `SNAPSHOT_ID`,chain 继承它(之后对 chain 的 Block B 本 pass 会 MATCH)。`MIXED` sentinel 使 Block B 对 chain 返回 NOT_MATCHED(Block B step 2 把字面量 `MIXED` 视为 NOT_MATCHED)——这是 chain 的 links 无法对单一快照证明时的安全分支。
- 执行 Step 3 Compute `signature`(chain 的确定性内容身份哈希):从每个 ELIGIBLE constituent finding 收集 `signature` 字段(与 Step 1 中 `discovery_commit` 使用的同一集合)。若每个 eligible constituent 都有非空 `signature`:对 constituent signatures 按字典序升序排序,然后计算 `signature` = `sha256(chain| + |.join(sorted_constituent_signatures))` 的前 16 个 hex 字符。`chain|` 前缀防止与非 chain finding 的 `signature` 冲突(后者由 title+cwe+target 哈希,不同输入域)。排序使 chain signature 在 constituent 重排序下不变。若任一 eligible constituent 缺少 `signature` 字段(legacy / un-upgraded finding):把 chain 的 `signature` 设为 EMPTY STRING 并在 JSON 中 OMIT 它(下游消费者然后按 `schema.json:256` 回退到 UUID-based fold/dedupe)。这是安全分支——绝不会导致错误 fold,只会 over-report。在 chain 创建时计算一次 signature,之后绝不重算、编辑或发明(同 `discovery_commit` 规则,也同 `researcher:241-242` 对常规 finding 的规则)。
- 执行 Step 3 Compute `lineage_id`(跨 pass chain lineage):扫描 `workspace/archive/findings_pass_*/` 和遗留 `workspace/archive/loop*_findings/`,找任何 archived chain finding JSON(`constituent_findings` 非空)且 `signature` 字段精确等于本 chain 计算的 `signature`。若找到匹配:`lineage_id` = archived ancestor 的 `lineage_id`(继承 lineage chain,便于 report 跨 pass fold)。若多个 archived chain 共享同一 `signature`,从 MOST RECENT(最高 pass number)ancestor 继承。所有同 chain `signature` 的 ancestor SHOULD 共享同一 `lineage_id`;若不共享,从 most recent 继承并 log warning。若无匹配(包括本 chain 的 `signature` 为 EMPTY STRING):`lineage_id` = fresh UUIDv4。这些是 STATE-RELATIVE paths(Block A step 3)——在 `--state_root/workspace/archive/` 下读取,绝不在 `CODE_ROOT` 下。(与 `researcher:246-272` 对常规 finding 的扫描目标和算法形状相同——chain 只是跳过 basename-normalized rename fallback,因为 chain 身份是组成集合,不是单文件路径。)
- 执行 Step 3 Determine Entry Point Privileges:chain 的 `privileges_required` 字段必须表示启动 chain 第一步(entry point)所需权限级别。例如,若 chain 从 unauthenticated exploit (NONE) 开始,导致 admin access,再用其触发 RCE,则 chain 的 `privileges_required` 必须设为 `NONE`。
- 执行 Step 3 Determine Attacker Position:chain 的 `attacker_position` 字段必须继承 entry point / 第一个 constituent finding 的 attacker position。
- 执行 Step 3 Determine User Interaction Requirement:chain 的 `user_interaction` 字段:若 entry point 或 chain 中任一步需要用户交互,则设为 `REQUIRED`。仅当整个 chain 是 zero-click 时才设为 `NONE`。
- 执行 Step 3 Determine Status:设 `status` 为 `VALID`。
- 执行 Step 3 Determine Production Viability:从 constituent findings 继承。若任一 constituent 是 `SAMPLE_OR_TEST`,设为 `SAMPLE_OR_TEST`。否则若任一 constituent 是 `CONDITIONAL_VIABLE`,设为 `CONDITIONAL_VIABLE`。否则设为 `VIABLE`。
- 执行 Step 3 Determine Reproduction Status:从 constituent findings 继承:若任一 constituent 的 `repro_status` 为 `failed_to_reproduce` 或 `not_attempted`,设为 `not_attempted`。否则,若所有 constituent 的 `repro_status` 为 `reproduced` 或 `statically_confirmed`,设为 `statically_confirmed`。exploit chain 必须 NEVER 继承 `reproduced`(组成 finding 的复现不能证明端到端 chain 有效)。
- 执行 Step 3 Chain Findings Schema Format(每个文件):按以下 JSON schema 写入:`id`:为此 chain finding 生成的唯一标识符,必须与文件名匹配。`title`:`Exploit Chain: [Impact] via [Finding A] and [Finding B]`。`description`:利用链的逐步文档。从 Step 1(Triggering Finding A)开始,解释其结果如何喂给 Step N(Triggering Finding Z)。`impact`:组合升级后的影响(例如 Remote Code Execution、Full Database Exfiltration),应高于单个 finding。`severity`:`CRITICAL / HIGH`。`privileges_required`:`NONE / LOW / HIGH`。`user_interaction`:`NONE / REQUIRED`。`code_paths`:数组,如 `relative/file/path_A.c:line_number`、`relative/file/path_B.c:line_number`。`attacker_position`:`EXTERNAL / LOCAL / etc.`(从 entry point 继承)。`mitigation`:建议的断链策略,通常至少修一个,甚至所有 underlying links。`status`:`VALID`。`production_viability`:`VIABLE / SAMPLE_OR_TEST / CONDITIONAL_VIABLE`。`repro_status`:`statically_confirmed / not_attempted`。`constituent_findings`:`[UUID_A, UUID_B]`。`signature`:若每个 constituent 都有非空 `signature`,为 `sha256(chain| + |.join(sorted(constituent_signatures)))` 前 16 hex 字符;否则 EMPTY STRING(absent-equivalent -> 下游回退到 UUID-only)。创建时计算一次,绝不重算(同 `discovery_commit`)。`lineage_id`:从最近 archived chain finding 继承,其 `signature` 等于本 chain 的 `signature`(扫描 `workspace/archive/findings_pass_*/` 和 `workspace/archive/loop*_findings/`);否则 fresh UUIDv4。`discovery_commit`:所有 constituents 共享的 `SNAPSHOT_ID`,或若不同/缺失则为字面量 `MIXED`(仅在 PINNED/HALT mode 计算)。在 legacy/unpinned runs(MODE-OFF)中 OMITTED(absent)——见上面的 MODE-OFF short-circuit。`history`:数组,每项含 `stage`: `chainer`,`action`: `created`,`details`: `Constructed by chaining findings [UUID_A] and [UUID_B].`,`pass_number`: `<current_pass_number>`,`timestamp`: `<current_iso8601_timestamp>`。
- 执行 Step 4 Chain Deduplication Tagging:为确保 `/mantis-dedupe` 对这些 chain 与 raw findings 区别对待,确保单词 `Chain` 在 `title` 和 `history` 字段中显著出现(如 schema 所示)。
- 完成写入:确保所有新构造 chain 文件写入 `workspace/findings/` 目录;完成后通知用户。
适用边界 · 注意事项
- 不适用于初始代码库审计。
- 不适用于编写补丁代码。
- 当 `workspace/findings/` 中没有已验证/viable finding,或 eligible constituents 少于 2 个,或处于 HALT/STALE 状态时,不应构造 chain。