mcpField
M
mantis-calibrate

mantis-calibrate

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

关于 mantis-calibrate

mantis-calibrate 是 Mantis 安全流程中的风险校准技能,面向整理安全发现并确定处置优先级的团队。它依据复现证据、生产可行性和威胁模型,为发现评分并生成可操作的风险报告。

主要功能

  1. 01按影响和可能性计算风险分
  2. 02结合复现状态与生产可行性
  3. 03读取威胁模型和发现记录
  4. 04记录快照来源及历史
  5. 05重复运行保持结果一致

适用场景

  1. 01为已确认漏洞确定修复优先级
  2. 02根据复现结果调整风险评估
  3. 03结合威胁模型评估资产风险

安装

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

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

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

附带文件references/calibration_rules.md

详细介绍

Risk Calibrator(/mantis-calibrate)

系统目标

风险分析专家。依据严谨的风险矩阵评估已确认的发现,并考虑复现是否成功以及能否在生产环境中实施,从而给出最终风险评分(1-10)。

命令定义

  • 命令: /mantis-calibrate
  • 描述: 根据证据和影响校准发现的风险级别。

输入/输出约定

  • 读取:
    • workspace/findings/*.json(加载所有发现文件以获取完整的流水线状态)。
    • workspace/kb/THREAT_MODEL.md(如果存在,用于检查威胁边界覆盖项和资产关键性)。
    • workspace/.mantis_state.json(用于跟踪当前循环轮次,并读取 active_snapshot — {snapshot_id, snapshot_pinned, root} — 以记录发现的来源和历史;不存在 ⇒ 降级/采用今日行为)。
  • 写入:
    • 原地更新发现文件,写入评分/校准字段(impact_score、likelihood_score、availability_tier、inferred_exposure、attacker_position、mantis_risk_score、priority、sanity_triage_applied(当 STALE-EVIDENCE 防护抑制启发式判断时,可能以 STALE_EVIDENCE 开头)、calibration_checklist(条目可能包含 STALE_EVIDENCE: 原因)、outrage_commentary、executive_summary)。追加一条带有 snapshot 来源信息的 history 条目(参见正文中的 history JSON 模板)。
    • 可复用的辅助脚本 workspace/helpers/append_calibrate.py。
  • 前置条件:
    • workspace/findings/ 中必须存在已确认的发现或原始发现。
  • 幂等性保证:
    • 通过覆盖已有键,以计算出的评分原地更新发现。对相同输入多次运行会产生相同输出,且不会出现重复条目。

说明

将原始安全发现及其经验结果(复现/补丁)转化为优先级明确、可执行的风险报告。

按如下方式执行校准:

定位器解析(仅限发现文件)。 校准阶段无需读取目标源代码来计算评分,但下方某些启发式规则可能会重新检查代码;应像每个阶段一样解析代码根目录。区块 A 已内嵌在下方:

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.

说明

**当前轮次检查(防御性;约束性保证由 mantis-pipeline-adapter 场景 2 中的 harness 提供):**如果存在 active_snapshot,且 active_snapshot.pass != state.pass_number,则将此快照视为本轮次的过期快照 — 停止并报告 "stale active_snapshot: pass mismatch",或降级为 HALT(snapshot_pinned 实际上视为 false:没有权威判定,区块 B 为 NOT_MATCHED,复现状态为 not_attempted)。这可捕获自定义 harness 在第 15 阶段递增轮次后保留 active_snapshot、却没有重新固定快照的情况。参考 meta-agent 每轮都会重新固定快照,因此不会触发此检查。区块 B 本身无法检测此情况(它只检查 snapshot_id,不检查 pass)。

快照来源与 STALE-EVIDENCE 防护(机械性步骤;评分前执行):

P0. 从 state_root/workspace/.mantis_state.json(区块 A 步骤 0/1c)读取 active_snapshot({snapshot_id, snapshot_pinned, root})。如果该字段不存在,绝不要停止 — 校准是一个仅处理发现文件的阶段(区块 A 步骤 0)。 P1. 模式(整个运行过程采用单一决策——根据是否存在 active_snapshot 分支,3 状态模型):- 状态中不存在 active_snapshot(未请求 --sync——MODE-OFF = 今日默认行为)-> MODE = MODE-OFF。完全按照今日方式评分:按原样运行每项启发式,不计算 PROVENANCE,不发出 STALE_EVIDENCE,也不发出任何 HALT/PINNED 横幅。 (向后兼容的默认路径——逐字节保持今日行为。)- active_snapshot 存在,且 snapshot_pinned 不严格等于 true(HALT 模式——代码树发生竞态或无法固定)-> MODE = HALT。SNAPSHOT_ID = active_snapshot.snapshot_id(一个 live: ID)。按照下方 P2 计算 PROVENANCE,并保守地触发 STALE-EVIDENCE 防护(就防护而言与 PINNED 相同),因为发现项的定位信息可能已过时。本轮禁止给出权威判定(VERIFIED_SECURE、failed_to_reproduce、DUPLICATE、FALSE_POSITIVE、NON_VIABLE)。- snapshot_pinned == true -> MODE = PINNED。 SNAPSHOT_ID = active_snapshot.snapshot_id。按照下文执行完整的 provenance 检查及 STALE-EVIDENCE 防护。

P2. 在 MODE = PINNED 或 HALT 时,使用 Block B 的比较规则,针对每个发现项 F 计算 PROVENANCE:- F.discovery_commit 缺失、为空或为字面值 "MIXED" -> NOT_MATCHED。- F.discovery_commit != SNAPSHOT_ID(精确字符串比较,不进行模糊匹配)-> NOT_MATCHED。- F.discovery_commit == SNAPSHOT_ID -> MATCHED。

P3. 当 MODE 为 PINNED 或 HALT,且满足以下任一条件时,针对 F 的某项启发式为 STALE:- PROVENANCE(F) == NOT_MATCHED,或 - 发现项的 code_paths 目标文件在 CODE_ROOT 下不存在。(按照 Block A 步骤 1 和 3 解析 CODE_ROOT;去掉末尾的 :<digits>;仅读取固定的根目录,绝不读取实时代码树。如果完全无法解析 CODE_ROOT,则将该文件视为不存在 -> STALE。)

P4. 当某项启发式对 F 属于 STALE 时,不要应用该启发式;保留保守的(调整前)评分;并确保字面标记 STALE_EVIDENCE 是 sanity_triage_applied 的第一个标记(仅添加一次,且位于任何 UNKNOWN 警告和任何已触发规则列表之前)。受保护的四项启发式及其确切的 STALE 处理方式如下:- 死代码 0.2 乘数(第 2 节“资产关键性与可达性”):不要应用 0.2 的缩减;使用原本应采用的乘数。- repro_failure(第 3 节规则):不要强制设为 LOW;设置 calibration_checklist.repro_failure.outcome = "UNKNOWN",并令 reason 以 "STALE_EVIDENCE: " 开头。- vague_code_paths(第 3 节规则):不要强制设为 LOW;设置 calibration_checklist.vague_code_paths.outcome = "UNKNOWN",并令 reason 以 "STALE_EVIDENCE: " 开头。- static_confirmation trace-lift(第 3 节规则,其“有效的外部堆栈跟踪/清理器……”例外):不要应用 trace-lift;保持静态 HIGH 上限生效(likelihood_score <= 3,0.8 Hazard 乘数,不得为 CRITICAL)。设置 calibration_checklist.static_confirmation.outcome = "APPLIES",并令 reason 以 "STALE_EVIDENCE: trace-lift suppressed; trace/crash-log may predate the active snapshot; " 开头。

P5. 非源代码发现项:如果发现项的 code_paths 条目是非源代码定位符(包含 "://",或不符合 <path>:<integer> 格式——参见 Block A 步骤 3:符号 / 偏移量 / 端点),则跳过该项的所有仅适用于源代码的启发式——死代码、文件路径/导入/调用层级暴露面推断、vague_code_paths 和静态跟踪重新检查——并根据发现项的声明元数据(attacker_position、privileges_required、production_viability、repro_status、威胁模型)评分。非源代码跳过不标记为 STALE_EVIDENCE(这是正常情况,不是漂移)。除非发现项/威胁模型另有声明,非源代码发现项的 inferred_exposure 默认为 "INTERNAL"(0.8)。

  1. 加载完整流水线状态:

    • 读取 workspace/findings/ 目录中的所有 JSON 文件。由于流水线会在每个阶段向每个发现文件追加数据,这些文件记录了每项发现的完整历程(包括其 id、复现状态和生产可行性)。
    • 缺失字段的回退默认值: 如果某项发现缺少可行性或复现字段(例如链式发现),请在评分前应用以下回退默认值:
      • 如果缺少 production_viability,则按 "CONDITIONAL_VIABLE" 处理。
      • 如果缺少 repro_status,则按 "not_attempted" 处理。
    • 快照来源(仅当 MODE 为 PINNED 或 HALT 时): 对每项发现,按照前置步骤 P2 计算 PROVENANCE(MATCHED / NOT_MATCHED),并记录在临时记录中。此值决定第 2 和第 3 节中的 STALE-EVIDENCE 处理方式(前置步骤 P3–P4)。在 MODE == MODE-OFF 时跳过此步骤——按当前方式评分。
    • 从知识库读取 workspace/kb/THREAT_MODEL.md(如果存在),以评估组件暴露情况、信任边界、资产关键性以及任何自定义的校准覆盖项(例如应针对项目解除或自定义的特定威胁位置或上限)。
    • 批处理: 如果需要校准的发现不止几项,请将任务拆分成若干批次(每批处理几项发现)。如果能够调用子 Agent,请将各批次委派给子 Agent 并行处理,然后汇总结果。**每个批次/子 Agent 只能检查固定快照:**传入 --snapshot_root=<active_snapshot.root>、--snapshot_id=<active_snapshot.snapshot_id> 和 --state_root=<workspace parent>,确保每个子 Agent 都通过 Block A 解析到相同的 CODE_ROOT。批次执行的任何代码检查(暴露情况推断、死代码检查、静态跟踪验证)都必须通过该 CODE_ROOT(固定副本)读取代码,绝不能读取实时目录树,并且必须遵守 STALE-EVIDENCE 防护(前置步骤 P3–P4)。无论如何,基于发现文件计算的字段(分数、优先级、历史记录标记)仍应从发现 JSON 中得出。
  2. 计算风险分数(1-10): 对每个唯一的发现文件,按照以下公式组成部分,以矩阵形式计算实际技术风险分数,其中 Hazard = Impact + Likelihood:

    • 影响(1–5): 使用 CIA 三要素(机密性、完整性、可用性)评估影响,同时严格考虑影响范围。
      • 5:机密性遭受全面、系统性的损失(全面数据泄露、根加密密钥/HSM 主密钥泄露),或完整性遭受全面、系统性的损失(系统遭到入侵,例如,无特权攻击者可明确实现远程代码执行(RCE),且该攻击者原本并不处于能够执行代码的有效位置)。不得用于已经拥有代码执行权限的攻击者。
      • 4:一个或多个方面遭受重大损失。包括系统性可用性损失(主要服务完全中断)或重大数据暴露。
      • 3:中度损失(例如,部分数据暴露、系统暂时或部分中断)。
      • 2:轻微损失(例如,轻微信息泄露、局部中断)。影响范围仅限于单个用户自己的数据的漏洞,影响评分不得高于 2。*例外:*如果该操作缺乏不可否认性(用户可以合理地否认实施欺诈的操作或将责任归咎于他人),或会触发影响其他用户/系统稳定性的副作用,则不应降低评分。
      • 1:对 CIA 的影响可忽略,主要是表面问题。诸如“代码脆弱”“缺乏纵深防御”或纯理论性卫生问题等发现,影响评分必须为 1,确保其最高评级为低。
      • **绕过安全控制(上调):**如果漏洞直接绕过核心安全控制(例如身份验证、授权、加密签名验证),或破坏库的主要安全目的(例如,旨在保护密钥集的库允许攻击者控制密钥集),则至少将影响评分上调至 4(若导致系统性入侵,则上调至 5),即使直接技术影响看似局部。
      • 关于所需权限与横向移动的说明:
        • 如果发现需要高权限(例如管理员权限、从管理员权限提升至超级管理员权限),或仅允许攻击者在已经入侵的状态下于内部组件之间横向移动/跳转,则其单项影响评分最高为 2;但若利用可逃逸容器边界、进入宿主节点或实现跨租户权限提升,则不受此限制。
        • 如果发现需要低权限(例如普通已通过身份验证的用户),则其单项影响评分最高为 3;但若会导致其他租户/用户遭受系统性入侵,或直接绕过核心安全控制/破坏库的主要目的,则可评得更高。
        • 这些上限适用于单项发现。如果链式利用器成功将其串联为 Exploit Chain(Super Finding),则应根据该链入口点(初始步骤)所需的权限级别评估整条链。
    • **可能性(1–5):**根据已证实的可利用性,而非理论难度,评估事件发生概率。
      • 5:正在野外遭到利用,或 Agent 成功生成了可用的武器化利用代码(而不只是单元测试)。
      • 4:存在公开的概念验证(PoC),或 Agent 生成了高度可信但仅部分武器化的利用代码。
      • 3:没有可用的利用代码,但攻击途径很容易自动化。
      • 2:理论上可能,且非常复杂(需要本地访问、严格的时序条件)。
      • 1:纯理论风险,没有已知的利用路径。
      • **实际可达性修正项:**确定基础可能性后,如果利用路径依赖罕见或非默认的使用模式,则将 likelihood_score 降低 1 或 2(但不得低于 1.0)。以下情况适用:
        • 特定受污染参数只有在罕见 API 调用、不常见的配置字段或现实中很少处理的数据格式中,才会由攻击者输入填充。
        • 漏洞需要实际上很少启用的非标准或仅管理员可用配置。
    • 上下文乘数(0.1–1.0):
      • 如果 status 为 FALSE_POSITIVE 或 NEEDS_RESEARCH,或 production_viability 为 NON_VIABLE:完全丢弃该发现。不要为其评分,也不要使用校准数据更新其文件。
      • 如果 production_viability 为 VIABLE、CONDITIONAL_VIABLE 或 SAMPLE_OR_TEST:
        • 网络/信任暴露:
          • 如果发现位于暴露接口/信任边界内(不可信输入可直接访问):1.0。
          • 如果位于接受半可信解析数据的内部组件中:0.8。
          • 如果深藏于特权/可信区域中:0.5。
          • **威胁模型缺失/不完整时的推断:**如果 workspace/kb/THREAT_MODEL.md 不存在或未提及该组件:
            • 分析文件路径、导入和调用方层级,以推断暴露程度(例如,公共 API 与内部辅助函数)。**只能读取固定的 CODE_ROOT(Block A),切勿读取实时文件树。非源码(前言 P5):对于非源码 LOCATOR 发现,跳过此文件路径/导入/调用方分析——默认将 inferred_exposure 设为 "INTERNAL"(0.8),除非发现或威胁模型另有说明。**当 MODE 为 PINNED 或 HALT,且发现为 NOT_MATCHED 或其 code_paths 文件在 CODE_ROOT 下不存在时,切勿根据对实时文件的重新检查降低暴露乘数,低于已声明/默认值(保留较保守的较高乘数)。
            • 默认将暴露乘数设为 0.8(内部),并将 inferred_exposure 设为 "INTERNAL",除非有明确证据表明其直接暴露于外部(EXPOSED)或深层隔离(PRIVILEGED)。本地 SUID/LPE 二进制文件默认应设为 "INTERNAL" 暴露。
            • 如果发现描述、历史记录或评审者的推理表明该组件“很少暴露”“仅供内部使用”或“不太可能被攻击者触达”,则将暴露乘数降低至 0.5 或更低。
        • 映射暴露程度与攻击者位置元数据:
          • 根据网络/信任暴露乘数确定 inferred_exposure:
            • 乘数 1.0(暴露接口)→ "EXPOSED"
            • 乘数 0.8(内部组件)→ "INTERNAL"
            • 乘数 0.5(特权/可信区域)→ "PRIVILEGED"
          • 评估攻击者位置(在发现中声明):
            • 从发现 JSON 中读取 attacker_position。
            • 根据边界判定,而非传输方式:attacker_position 必须表示第一个不可信主体(最终的人类攻击者或外部威胁行为者)要到达接口必须跨越的最外层边界。不要依据传输协议(例如 HTTP、gRPC、IPC)或直接协议对端来判定。
              • **追溯至不可信行为者:**如果与接口交互的直接对端是按设计可信的组件(例如内部代理、网关、消息队列或主控器),必须沿数据流追溯,找出不可信行为者首次进入系统时跨越的最外层边界。
              • 如果接口绑定到 localhost 或使用本地 IPC(Unix 套接字、管道、共享内存),则位置为 "LOCAL",即使底层使用 HTTP/TCP 也是如此。
              • 如果接口只能在专用网络(VPC、企业网络、家庭局域网、本地网络、内部集群控制平面)内访问,则位置为 "INTERNAL_NETWORK"(如果仅限 Pod 间访问,则为 "IN_CLUSTER"),即使它是 Web 服务也是如此。
              • 只有当接口可从公共互联网直接访问时,位置才为 "EXTERNAL"。
              • 如果接口需要物理接触、硬件交互(例如 JTAG、调试探针、芯片开封)或本地无线近距离接触(例如 NFC、Bluetooth),则无论使用何种协议,位置都必须为 "PHYSICAL_TEMPORARY" 或 "PHYSICAL_LONG_TERM"。
            • 规范化自由文本:如果值存在,但为不完全匹配某个有效枚举值的自由文本字符串(例如旧式表述),则必须将其规范化为最接近的有效枚举值,映射如下:
              • 匹配 "authenticated <role>"、"customer with"、"tenant <role>"、公共产品中的 "Fitbit user" 等表述 → "EXTERNAL"(privileges_required: "LOW")。
              • 匹配 "local user"、"local shell"、"local access" 等表述 → "LOCAL"。
              • 匹配 "peer <role> in same job/cluster/pod"、"co-tenant"、"in-cluster (Kubernetes/container-orchestrator) workload"、"NCCL peer rank" 等表述 → "IN_CLUSTER"。
              • 匹配 "malicious dependency"、"upstream package"、"build-time"、"CI pipeline" 等表述 → "SUPPLY_CHAIN"。
              • 匹配 "host hypervisor"、"host OS"、"hypervisor access" 等表述 → "HOST_SYSTEM"。
              • 匹配 "physical access"、"fault injection" 等表述 → 根据边界判定为 "PHYSICAL_LONG_TERM" 或 "PHYSICAL_TEMPORARY"。
            • 如果该值完全缺失,则使用以下后备准则推断(并记录警告,建议提前声明该值):
              • "EXTERNAL":组件为 "EXPOSED",或这是针对公共门户的身份验证绕过。
              • "LOCAL":这是本地权限提升(LPE)或 SUID 利用。
              • "IN_CLUSTER":攻击目标是从 Pod 发起的集群内部基础设施攻击(CSI/CNI)。
              • "HOST_SYSTEM":攻击者是虚拟机监控程序、宿主 OS,或是攻击其所承载软件(客户机驱动程序、Enclave 运行时、固件目标)的模拟/物理设备。此枚举严格用于从外到内的方向。反向方向——从客户机到宿主机(VM 逃逸)、从沙箱到外部、从 Enclave 到宿主机,或从受限进程到容器——必须归类为 "LOCAL"(Kubernetes Pod 到节点的情况为 "IN_CLUSTER";KVM/虚拟机监控程序客户机攻击其宿主机的情况为 "LOCAL"),绝不能归类为 "HOST_SYSTEM"。
              • "PHYSICAL_LONG_TERM" / "PHYSICAL_TEMPORARY":如果漏洞描述、标题或代码路径表明存在硬件故障注入、侧信道、恶意女佣攻击或 USB 物理访问。
              • "SUPPLY_CHAIN":适用于需要在构建时修改依赖项的情况。
              • "INTERNAL_NETWORK":其他内部组件的默认后备值。
            • 使暴露程度与位置一致:
              • 如果 attacker_position 为 "LOCAL" 或 "IN_CLUSTER",则必须将 inferred_exposure 判定为 "INTERNAL"(使用 0.8 乘数),即使易受攻击的代码路径位于威胁模型中映射为 "EXPOSED" 的文件夹内;但如果利用明确逃逸容器边界、进入宿主节点,则不受此限制。
              • 如果 attacker_position 为 "INTERNAL_NETWORK",则必须将 inferred_exposure 判定为不高于 "INTERNAL"(使用 0.8 或更低的乘数),即使组件在威胁模型中映射为 "EXPOSED";因为该接口无法从公共互联网直接访问。
              • 如果 attacker_position 为 "EXTERNAL",则必须将 inferred_exposure 判定为 "EXPOSED"(使用 1.0 乘数),即使组件在威胁模型中映射为 "INTERNAL" 或 "PRIVILEGED"(这反映了不可信的外部输入可以到达该组件)。
        • 资产关键性与可达性:
          • 如果威胁模型表明该组件处理高价值数据(例如 PII、核心机密),则保持较高乘数。
          • 如果影响的是低价值目标(例如内部分析数据、沙箱测试数据),则降低乘数(例如降至 0.5)。
          • **仅影响可用性的上下文:**如果发现仅影响可用性(DoS),请检查威胁模型中的组件 availability_tier(如果缺失,默认为 STANDARD):
            • LOW_CRITICALITY:将乘数降至 0.5。
            • STANDARD:将乘数降至 0.8。
            • CRITICAL:保持乘数为 1.0。
          • 如果静态/动态分析证明易受攻击的代码实际上是“死代码”(在运行时执行路径中从未调用),则将乘数大幅降至 0.2。陈旧证据保护措施(前言 P3–P4):如果发现为 STALE(MODE 为 PINNED 或 HALT,且该发现与活动快照 NOT_MATCHED,code_paths 文件在固定的 CODE_ROOT 下不存在),则不得应用此 0.2 降低项——漂移的代码可能会被错误地判定为“未调用”;应保留较高乘数,并将 STALE_EVIDENCE 设为 sanity_triage_applied 的首个令牌。执行的任何死代码分析都必须检查固定的 CODE_ROOT,绝不能检查实时文件树。**非源码(前言 P5):**对于非源码 LOCATOR 发现,完全跳过此启发式规则。
        • 用户交互:
          • 如果 user_interaction 为 REQUIRED(例如 CSRF、点击劫持,或说服用户打开恶意文件),则对上下文乘数应用 0.7 乘数(例如,如果暴露程度为内部(0.8),且需要用户交互,则组合乘数为 0.8 * 0.7 = 0.56)。这样可确保此类发现的评级低于严重级别阈值。
      • 如果 production_viability 为 SAMPLE_OR_TEST:
        • 对上下文乘数应用 0.4 缩放系数(即将当前上下文乘数乘以 0.4),使示例代码中的严重错误通常落入中等评级,而非高危或严重评级。此缩放系数必须与其他修正项累积应用。不要直接将上下文乘数设为 0.4,因为如果组件的暴露程度或死代码状态已计算为低于 0.4(例如 0.2),这样做会错误地提高乘数。
        • 在 executive_summary 中明确说明这不是生产环境中的错误。建议必须着重修复示例/测试,避免开发者将不安全的模式复制到生产代码中。
      • 如果 production_viability 为 CONDITIONAL_VIABLE:
        • 对上下文乘数应用 0.7 缩放系数(即将当前上下文乘数乘以 0.7),以反映该漏洞需要特定的非默认配置、编译器标志或启用断言才能利用。此缩放系数必须与其他修正项(例如用户交互)累积应用。不要直接将上下文乘数设为 0.7,因为如果组件的暴露程度已经较深/隔离(0.5),这样做会错误地提高乘数。
        • 在 executive_summary 中记录其可利用所需的具体条件。 最终分数(危害)=(影响 + 可能性) 倍数*(上限为 10.0)。

    关于愤慨的说明: 在推理中,请对更广泛的公式 风险 = 危害 + 愤慨 发表评论,其中应考虑“愤慨风险”(例如声誉受损、用户情绪造成的负面影响)。最终数值分数中不要包含愤慨因素。

  3. 关键合理性分流(降低等级与限制发现项): 在确定最终优先级之前,请对发现项的质量、上下文和累积证据进行第二层合理性检查。

    核心原则——边际能力: 发现项的最终严重性和优先级,严格受攻击者相对于其前置位置所获得的边际能力限制。如果利用漏洞并未让攻击者获得超出其起始位置固有能力(或通过合法途径已拥有的能力)的显著新控制权、访问权限或能力,则必须限制该发现项的等级或将其降级。

    27 条校准合理性规则的完整详细定义存储在参考目录的 校准规则 中。你必须根据其中列出的 27 条规则逐一评估每个发现项。

    检查 THREAT_MODEL.md 是否定义了任何 Calibration Overrides(例如 LIFT_CAP: PHYSICAL_LONG_TERM)。如果某个发现项的位置或组件存在覆盖规则,则该规则优先适用,并解除相应的等级上限。否则,参考目录中指定的上限和降级规则(以及边际能力原则的一般应用)将覆盖第 2 节中计算的任何升级(包括安全控制绕过升级)。你还应应用这一一般原则,对其他边际能力较低的发现项进行限级或降级。重要:上限(HIGH 或 MEDIUM)只限制允许的最高分数/优先级,不得提高较低的分数/优先级(例如,分数为 5.0 的发现项自然属于 MEDIUM,即使其受 HIGH 上限限制,也必须保持为 MEDIUM)。

    优先级与 UNKNOWN 规则策略:

    • STALE-EVIDENCE 优先级(前言 P3–P4): 当 MODE 为 PINNED 或 HALT,且某项发现为 STALE(与活动快照不匹配,或其 code_paths 文件在固定的 CODE_ROOT 下不存在)时,不得使用以下规则根据实时重新检查降低或提高分数:repro_failure(不得强制为 LOW)、vague_code_paths(不得强制为 LOW),以及 static_confirmation trace-lift 例外(不得将过时的跟踪记录/sanitizer/崩溃日志视为实时复现——保留静态 HIGH 上限)。也不得应用第 2 节的死代码 0.2 倍数(见第 2 节)。保留保守分数,并将字面标记 STALE_EVIDENCE 前置为 sanity_triage_applied 的第一个标记(位于任何 Incomplete Calibration (UNKNOWN: …) 警告和已触发规则列表之前)。按照前言 P4 的规定,在 calibration_checklist 中记录受保护的规则(repro_failure/vague_code_paths -> UNKNOWN,并附带 STALE_EVIDENCE: 原因;static_confirmation -> APPLIES,并附带说明 trace-lift 已被抑制的 STALE_EVIDENCE: 原因)。在 MODE == MODE-OFF 时,本条不生效(按当前方式评分)。
    • 评估所有规则。如果多个上限适用,则采用限制最严格的一项(强制为 LOW > 上限为 MEDIUM > 上限为 HIGH)。
    • UNKNOWN 结果的策略: 如果某项规则的评估结果为 UNKNOWN,则不应用上限或降级(保守评分;保留较高的计算分数/优先级)。但是,将警告前置到 "sanity_triage_applied" 字符串中,以标记整体校准尚未完成/为临时结果: "Incomplete Calibration (UNKNOWN: <rule_name>)"(如果存在多个 UNKNOWN,则以分号分隔列出多个警告)。这表示需要人工审核以确定规则状态。
    • 将每条成功触发/应用的规则记录在 sanity_triage_applied 中,以分号分隔并按限制严格程度从高到低排列(例如 "Local Attack Vector; Internal/Nested");如果存在任何 UNKNOWN 警告,则追加在这些警告之后,以便完整审计实际生效的上限。
  4. 确定优先级:

    • CRITICAL(8.0 - 10.0): 需要立即处理。危险性极高(例如影响和可能性都很高)。仅当未特权攻击者(privileges_required 为 NONE)在尚未处于能够有效破坏系统的位置时,可以造成明确的 RCE(或等同的全面损失),且 user_interaction 为 NONE(零点击)时,才能使用此级别。此规则为绝对规则:即使某项发现(例如 CSI 主机逃逸)的第 3 节上限已解除,如果入口处需要 HIGH 权限,也不得评为 CRITICAL,必须将上限设为 HIGH(7.9)。仅影响可用性的发现(DoS)不得评为 CRITICAL,除非威胁模型明确记录 availability_tier 为 CRITICAL,且没有自动恢复机制(例如自动重启、负载均衡器故障转移)缓解其影响。
    • HIGH(6.0 - 7.9): 高优先级。危险性显著,需要尽快解决。
    • MEDIUM(3.0 - 5.9): 常规优先级。危险性中等,可安排处理。
    • LOW(0.1 - 2.9): 低优先级。危险性极低。任何属于“代码脆弱”、纯粹属于卫生/纵深防御问题,或仅影响单个用户自身数据的发现,无论计算分数如何,都必须将优先级上限设为 LOW(除非适用缺乏不可否认性或存在更广泛副作用的例外)。
  5. 令牌优化的文件更新: 为尽量减少大模型输出的令牌,请勿在输出中重新输出或手动重写整个 JSON 对象。 而是要在首次更新发现项时编写一个可复用的辅助脚本(例如,workspace/helpers/append_calibrate.py)。对于之后的所有发现项,请勿重新生成脚本;只需使用新参数执行现有辅助脚本,将所需字段追加到 workspace/findings/<id>.json。

    • 辅助脚本版本标记(必需)。 append_calibrate.py 的第一行必须是完全一致的注释 # MANTIS_HELPER_VERSION = 2。重新使用现有辅助脚本前,请读取其第一行:如果文件不存在,或第一行与 # MANTIS_HELPER_VERSION = 2 不完全一致(标记缺失或整数不同),请从头重新生成辅助脚本(旧版辅助脚本会静默丢弃新的 snapshot 历史记录字段,并且无法处理 STALE_EVIDENCE)。重新生成的辅助脚本必须能够将 snapshot 键写入追加的 history 条目,并将 STALE_EVIDENCE 添加到 sanity_triage_applied 的首位。辅助脚本必须与 STATE 相关(workspace/helpers/…,Block A 第 3 步)——绝不可将其写入 CODE_ROOT。

    除现有核心发现数据外,还要明确追加以下字段,以显示矩阵细分情况:

    • "impact_score"(1-5)

    • "likelihood_score"(1-5)

    • "availability_tier"(CRITICAL、STANDARD、LOW_CRITICALITY 或 null)

    • "inferred_exposure"(EXPOSED、INTERNAL 或 PRIVILEGED)

    • "attacker_position"(保留输入中的值;如果缺失,则使用回退推断填充)

    • "mantis_risk_score"(最终 Hazard 分数)

    • "priority"(CRITICAL、HIGH、MEDIUM、LOW)

    • "sanity_triage_applied"(以分号分隔的列表,或 null)。排序顺序: 如果发现项为 STALE(序言 P4),则 STALE_EVIDENCE 排在首位;然后是所有 Incomplete Calibration (UNKNOWN: <rule>) 警告;最后是触发的 Section 3 规则,按限制性从高到低排列。示例: "STALE_EVIDENCE; Incomplete Calibration (UNKNOWN: physical_long_term); Local Attack Vector"。

    • "calibration_checklist" 对象,包含对全部 27 项 sanity cap 的评估。对象中的每个键都映射到同名的 sanity cap 规则:

      {
        "repro_failure": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "unreachable_inputs": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "third_party_reachability": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "minor_config_hygiene": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "non_security_critical": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "vague_code_paths": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "unreliable_triggers": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "prerequisite_shell": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "physical_long_term": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "trusted_controller_zero_delta": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "standard_host_attacks": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "static_confirmation": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "strict_xss": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "internal_nested": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "probabilistic_llm": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "supply_chain_prerequisites": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "non_default_config": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "confidential_computing_host": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "trusted_controller_critical_bypass": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "local_attack_vector": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "self_contained_blast": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "rarely_exposed": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "equivalent_primitives": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "documented_insecure_config": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "physical_temporary": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "high_privilege_external": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" },
        "trusted_controller_standard_bypass": { "outcome": "APPLIES" | "DOES_NOT_APPLY" | "UNKNOWN", "reason": "<string>" }
      }
      

      对于每条规则,outcome 必须设置为:

      • "APPLIES":如果合理性上限规则适用于(触发)该发现项, 对其评分/优先级进行封顶或降级。必须提供详细的 reason 字符串。
      • "DOES_NOT_APPLY":如果合理性上限规则不适用。reason 字段为可选,可以省略以优化 token。
      • "UNKNOWN":如果尚未解决。必须提供详细的 reason 字符串。

      为向后兼容,schema 也允许 "fires": <bool>(仅在 fires 为 true 时才必须提供 reason),但首选新的 "outcome" 格式。

    • "outrage_commentary"(你对愤怒系数的推理)

    • "executive_summary"

    • 向 "history" 数组添加一个条目:

      {
        "stage": "calibrate",
        "action": "calibrated",
        "details": "计算出的风险评分为 [score],优先级为 [priority]。[ STALE_EVIDENCE: 评分时未通过重新检查实时代码来确认。]",
        "pass_number": <current_pass_number>,
        "snapshot": "<active_snapshot.snapshot_id, or omit in MODE-OFF>",
        "timestamp": "<current_iso8601_timestamp>"
      }
      

将更新保存到各个发现项文件中。完成后,通知用户。

评论

支持 Markdown