协作办公
在已有审查计划时对生产源码做静态安全审计并输出独立发现文件
当 workspace/plan.json 已存在审查计划、需要对目标源码文件做内存安全、逻辑正确性与健壮性深度审计时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在已有审查计划时对生产源码做静态安全审计特定
解决思路
- 先做定位解析(Locator Resolution):确定唯一的 CODE_ROOT,所有 target_files/code_paths 都相对它解析。优先级:本次调用传入的 --target_root 为权威覆盖;否则用 --snapshot_root/SNAPSHOT_ROOT;否则读 state_root/workspace/.mantis_state.json 的 active_snapshot.root;都没有则 CODE_ROOT=当前目录并视 snapshot_pinned=false(MODE-OFF),不要停止。
- 若 snapshot_pinned 为 true 且未走 --target_root 路径,做哨兵检查:确认 CODE_ROOT/.mantis_snapshot_id 存在且等于 SNAPSHOT_ID,否则以 'snapshot sentinel mismatch' 停止(--target_root 树被有意修改,免检)。
- 区分路径类型:SNAPSHOT-RELATIVE(在 CODE_ROOT 下读取)包括 code_paths 条目、plan 中作为文件路径的 target_files,仅剥离末尾的 ':<digits>';含 '://' 的条目是 URL/端点而非文件;非 <existing-path>:<integer> 形式的是非源码 LOCATOR(符号/偏移/端点),只校验其存在,跳过所有行号逻辑。STATE-RELATIVE(在 state_root/workspace 下读写,绝不加 CODE_ROOT 前缀)包括 kb_references、repro_file_path、reattack_file_path、helper 脚本、报告文件及所有 state/findings JSON。
- snapshot_pinned 为 true 时绝不在 CODE_ROOT 下写入;任何编译、生成或写产物的命令必须在私有影子副本(从 CODE_ROOT 用 mktemp -d 创建)中运行,绝不 cwd=CODE_ROOT;只读检查可以 cd 进 CODE_ROOT。
- VCS 元数据例外:历史日志提取与任何 VCS diff/blame 命令在仍含 .git/.hg/.repo 的实时仓库根运行,而非 CODE_ROOT(快照副本剥离了 VCS 元数据);不要仅因 CODE_ROOT 缺少 .git/.hg/.repo 就停止。
- 每条 shell 命令使用绝对路径并在该次调用中自行设置工作目录,不要假设工作目录在调用间保持。
- 加载审查计划与上下文:从 workspace/.mantis_state.json 读取当前 pass 号并解析当前 ISO 8601 时间戳;读 workspace/plan.json 获取目标调查项;若 plan.json 缺失或为空,则对目录做通用列表并审查主要源文件;若调查含 kb_references 数组,先显式读取这些 Markdown 文件(如 workspace/kb/entities/auth.md)获取历史上下文;同时读取 active_snapshot 的 root、snapshot_id、snapshot_pinned,将 snapshot_id 记入内存用于写入每个 finding 的 discovery_commit;若 active_snapshot 缺失或 snapshot_pinned 为 false,进入 DEGRADED/legacy 模式,不要停止,只是省略 discovery_commit。
- 子代理委派(基于波次的并行蜂群):若平台支持子代理,不要顺序执行。将 plan.json 中的调查拆成并行波次。Wave 1 轻量快速分诊:并发启动轻量子代理(如 10-20 个并行)扫描 plan.json 中所有文件,每个只输出快速分类 {"potentially_flawed": true/false, "reason": "..."}。Wave 2 深度安全缺陷热点审计与并行轨迹搜索:收集 Wave 1 标记的文件,启动并发深度审计子代理(如 4-8 个并行)专注这些热点;对特别复杂的文件,用不同提示约束或一组更便宜的不同 LLM 对同一文件启动多个子代理探索并行攻击向量,依赖后续去重阶段合并重叠发现。
- Token 优化(分布式写入):指示 Wave 2 子代理生成唯一 UUID 并直接写入各自的 workspace/findings/<id>.json 文件;不要让它们把完整 JSON 载荷回传给你,只让它们返回所创建的 UUID 列表。
- 快照隔离(波次固定)——强制:向每个 Wave-1 和 Wave-2 子代理传入相同的 --snapshot_root(Step 0 解析的 CODE_ROOT)和相同的 --snapshot_id,并指示每个子代理遵守 Block A(在该 CODE_ROOT 下解析 target_files/code_paths、遵守哨兵)。任何写入 finding 的 Wave-2 子代理必须按 Findings Schema Format 用该 snapshot_id 填写 discovery_commit。子代理不得运行 git pull/fetch/checkout/reset、hg pull/update、repo sync 或任何改变工作树或切换版本的命令——快照在整个 pass 内不可变。看不到快照的子代理必须报告该情况,而不是重新同步。
- 若环境不支持子代理或并发,则回退为顺序执行扫描与深挖。
- 结构化索引(仅作提示增强):当 workspace/kb/structural_index/manifest.json 存在时,用它补充上述波次蜂群。结构化索引只决定顺序,绝不决定成员集合,绝不能替代 Step 3 的穷尽调用点扫描。
- 结构化查询前必须先做解析优先协议:先运行 python3 workspace/helpers/query_structural_index.py resolve_symbol --name "<function_name>" [--language "<lang>"] [--file "<path>"] --state_root <state_root>;若响应 ambiguous: true,调查所有匹配符号,绝不静默选一个,可用 --file/--language 收窄或为每个匹配符号安排调查;再用解析出的 symbol_id 做有界查询:python3 workspace/helpers/query_structural_index.py find_callers --symbol_id "<id>" --limit 100 --offset 0 --state_root <state_root>。
- 覆盖感知解读:检查每个结构化索引响应中的 coverage.partition_status。complete + precision == semantic + 空结果 = '无索引调用者'(对已索引代码权威,但仍按 HINT-only 规则跑 grep);complete + precision != semantic + 空结果 = '无索引调用者'但非权威,必须跑穷尽 grep;partial/empty/failed + 空结果 = '未完全索引',必须跑穷尽 grep;用每个结果的 precision 和 backend 字段加权信任(semantic > typecheck > ast > symbol-only > heuristic > deferred > coverage-only)。
- Wave 1(快速分诊):用 find_callers() 作为排序提示补充 grep——只决定顺序,绝不决定成员集合;结构化索引结果用于优先标记哪些文件 potentially_flawed,绝不能替代 Step 3 的穷尽调用点扫描;审计 grep 结果与结构化索引结果的并集。
- Wave 2(深度审计):用 get_function_boundary(file, line) 从所在函数开始,再按需扩展到调用者/被调用者/文件以获取深挖上下文。
- 优雅降级:若结构化索引缺失(无 manifest.json)、为空或查询 helper 缺失,回退到基于 grep 的发现(当前行为)。结构化索引只是覆盖提示。
- 穷尽接口与调用点审查:若目标源文件定义了公开或 API 函数(如数值解析器、解码器、编码器、转换器)并记录了显式大小约束或安全要求(如期望调用方分配特定大小缓冲区):先对函数名做全仓库 grep 建立候选调用点集合——这是强制底线;再用结构化索引查询 helper(先 resolve_symbol 再 find_callers)对调用点排序并优先审计(索引能区分真实调用与注释/字符串/变量名);审计两者结果集的并集——结构化索引可能漏掉宏调用、函数指针和动态分派,故 grep 仍是底线。搜索代码库找出并审查这些函数在整个仓库的所有调用点,确保安全契约全局被遵守。读取调用方文件,验证每个调用点是否严格遵守输入约束、正确管理边界并检查大小。将任何不一致标记为契约对齐缺陷或缺失检查。
- 无约束/探索性调查:若 plan.json 中的调查包含明确要求无约束扫描、对抗性审计或随机探索的指令或问题:忽略 workspace/kb/THREAT_MODEL.md 中已有的安全假设与文档化信任边界;将所有输入和边界视为不可信且可能畸形;从头以完全自由和自主性分析实现;若是指令极少的随机探索/挖掘任务,专注于映射目标文件行为、识别关键入口点、寻找意外副作用或边界情况,不受特定威胁模型约束。
- 编译并写入发现:不要写单一巨型文件;若 workspace/findings/ 目录不存在则创建。对每个潜在发现生成唯一 UUID,并将合法 JSON 对象写入单独文件 workspace/findings/<id>.json,使发现彼此隔离并避免后续分析的 token 限制问题。文件中 JSON 前后不得有任何文本。
- 签名与谱系计算(Step 5a):写 JSON 文件前为每个发现计算 signature、lineage_id,可选 cwe。cwe(可选):若漏洞映射到已知 CWE,将 cwe 字段设为标识符(如 "CWE-787"、"CWE-416");无适用 CWE 则省略该字段;它是签名的输入。
- 计算 signature(确定性内容身份哈希):normalized_title = finding 的 title 转小写并剥离所有非字母数字字符(仅保留 ASCII [a-zA-Z0-9],其余包括 Unicode 字母、标点、空格全部移除);若剥离后 normalized_title 为空(如标题全为非 ASCII/Unicode 字符),设 normalized_title = sha256(<原始 title 的 UTF-8 字节>) 的前 16 个十六进制字符,以免两个不同的非 ASCII 标题在空字符串上碰撞。cwe_part = finding 的 cwe 字段(若存在且非 null),否则为空字符串。primary_target = code_paths 中第一个条目剥离末尾 ':line'(如 src/auth.c:145 → src/auth.c);若 code_paths 为空,或第一条目是非源码 LOCATOR(含 '://' 的 URL,或按 Block A step 3 的非文件符号/偏移),用空字符串。确定性地排列 code_paths(主 sink 在前,跨 pass 保持稳定),使 primary_target 及 signature 不在 pass 间漂移(若顺序不稳定,唯一代价是漏掉谱系继承 → 发现被过度报告为新,绝不会被隐藏,但稳定顺序可保留跨 pass 折叠)。若 primary_target 非空:signature = sha256(normalized_title + '|' + cwe_part + '|' + primary_target) 的前 16 个十六进制字符。若 primary_target 为空:signature = sha256(normalized_title + '|' + cwe_part + '|' + sorted(code_paths).join(',')) 的前 16 个十六进制字符。签名在发现创建时计算一次,绝不重算、编辑或臆造(与 discovery_commit 同规则)。
- 计算 lineage_id(跨 pass 谱系链):扫描 workspace/archive/findings_pass_*/ 和 workspace/archive/loop*_findings/,找任何已归档 finding JSON 的 signature 字段等于本发现计算出的 signature。若找到匹配:lineage_id = 该归档祖先的 lineage_id(继承谱系链以便消费者跨 pass 折叠);若多个归档发现共享同一 signature,从最近(pass 号最高)的祖先继承;所有同 signature 的祖先应共享同一 lineage_id,若不一致则从最近者继承并记录警告。若按精确签名无匹配:仅对真正的重命名尝试 basename 重命名回退,不要重算签名(它在创建时计算一次且绝不重算——不变式 #4)。具体:1) 计算当前发现的 basename:取 primary_target(code_paths 第一条剥离末尾 ':line',已在签名步骤 2 算出)的 basename(如 src/auth.c → auth.c);若 primary_target 为空(非源码 LOCATOR 或空 code_paths),跳过此回退,走下面的全新 UUIDv4。2) 对步骤 3 归档扫描中的每个归档发现:从其存储的 code_paths[0] 重建归档发现的 basename(剥离末尾 ':line',取 basename,如 lib/old_auth.c:88 → old_auth.c);不要重算归档发现的签名,也不要比较签名;将两个 basename 作为字符串比较。3) 仅当 (i) basename 匹配且 (ii) 祖先的完整 primary_target(其 code_paths[0] 剥离 ':line')在当前快照上不再存在(在 CODE_ROOT 下检查旧完整路径缺失——以此区分真正重命名与仅共享 basename 的第二个独立文件)时,才通过此回退继承祖先的 lineage_id;若多个归档祖先满足 (i) 和 (ii),从最近(pass 号最高)者继承;通过 basename 继承时,还要添加 finding 历史注记 lineage-via-basename-rename,以便下游消费者将该链接视为 basename 派生(报告仅当两个发现的完整 signature 也匹配同一 SAME-BUG 谓词时才折叠,故 basename 派生的谱系链接绝不会合并不同缺陷)。4) 若旧完整路径在当前快照上仍存在,不要继承——视为无匹配(走下面的全新 UUIDv4)。若精确签名和 basename 重命名都无匹配:lineage_id = 全新 UUIDv4。这些是 STATE-RELATIVE 路径(Block A step 3)——在 --state_root/workspace/archive/ 下读取,绝不在 CODE_ROOT 下。
- 将 cwe、signature、lineage_id 三个字段与 discovery_commit 一起写入 finding JSON。模式无关性:与 discovery_commit(在 DEGRADED/legacy 模式省略)不同,signature 和 lineage_id 总是计算——它们是内容身份字段而非快照身份,无论快照是 pinned、unpinned 还是缺失(MODE-OFF)都有效。这是有意的 Phase-3 改进:MODE-OFF 下 finding JSON 现在携带 2-3 个 Phase 1 没有的可选键(cwe、signature、lineage_id),这不改变快照模型(无 active_snapshot、无同步、无 pin——三态规则不受影响)。去重 MODE-OFF 回退现在优先用 signature 而非 stable_key(若存在),这严格更具区分度(signature 在 title+path 组合中加入 cwe),故只会拆分 stable_key 本会合并的条目(新预算、更保守=安全),绝不会产生错误合并或压制合法发现。signature 缺失 → 与今天的 stable_key 行为完全一致。
- 缺失或不可读目标文件:若 target_files 中某路径在 CODE_ROOT 下不存在或不可读(如计划写好后被删除或重命名),不要臆造 finding、行号或文件内容;跳过该目标并在相关 finding 的 description 中如实记录跳过(或完全省略);绝不臆造未读过的代码。
- 非源码目标:对非源码 LOCATOR(二进制、固件或 URL 端点——见 Block A step 3),code_paths 条目必须是稳定 LOCATOR(符号名、偏移或裸路径)且不带 ':line' 后缀;不要给无法作为文本打开的目标附上臆造的行号。
- 按 Findings Schema Format 写入每个 finding 文件,字段包括:id(唯一标识符,须与文件名匹配)、title、description(根因分析)、impact、severity(CRITICAL/HIGH/MEDIUM/LOW)、privileges_required(NONE/LOW/HIGH)、attacker_position(EXTERNAL/INTERNAL_NETWORK/IN_CLUSTER/LOCAL/HOST_SYSTEM/SUPPLY_CHAIN/PHYSICAL_TEMPORARY/PHYSICAL_LONG_TERM)、user_interaction(NONE/REQUIRED)、status(PROVISIONALLY_VALID)、code_paths(CODE_ROOT 下的 SNAPSHOT-RELATIVE 路径如 'relative/file/path.c:145';非源码目标用稳定 LOCATOR 不带 ':line',绝不臆造行号)、discovery_commit(快照 pinned 时必填非空,逐字复制 active_snapshot.snapshot_id,创建时设置一次,绝不重算/编辑/臆造;active_snapshot 缺失或 snapshot_pinned 为 false 时完全省略该键,不写 "" 或 null)、cwe(可选,无适用则省略)、signature、lineage_id、mitigation、history 数组(含 stage: researcher、action: created、details、pass_number、timestamp)。
- discovery_commit 规则(创建时设置一次):本阶段是 discovery_commit 的创建点。快照 pinned 时,你(或 Wave-2 子代理)写的每个 finding 必须携带非空 discovery_commit 等于 active_snapshot.snapshot_id。下游阶段将缺失的 discovery_commit 视为 NOT_MATCHED(保守分支),故写空字符串或错误值会静默破坏匹配——绝不要做。DEGRADED/legacy 模式(无 active_snapshot 或 snapshot_pinned 为 false)省略该键,使行为与今天的流水线一致。
- signature/lineage_id 规则(创建时设置一次):这些字段总是计算(不同于 degraded 模式省略的 discovery_commit)。signature 是 finding 内容身份的确定性哈希;lineage_id 将 finding 链接到其归档祖先。下游消费者(dedupe、chain、report、reproduce)以 signature/lineage 为键并回退到 UUID:signature 缺失 → 与今天的 UUID 行为完全一致(无静默错误结果)。
- 确保所有单独 finding 文件写入 workspace/findings/ 目录,完成后通知用户。
适用边界 · 注意事项
- 不要用于制定审查计划、去重或编写补丁(本技能只做审计与发现写入)。
- 不要在 snapshot_pinned 为 true 时在 CODE_ROOT 下写入、编译或生成任何产物。
- 不要臆造未读过的代码、行号或文件内容;缺失/不可读目标应跳过并如实记录。