关于 mantis-threat-model
此 findings-only 技能基于 Mantis 的架构和实体知识库文件生成并维护高层威胁模型。它描述信任边界、攻击者画像和高风险资产,记录快照来源,并在覆盖模型前归档旧版本。
主要功能
- 01读取知识库中的架构和实体文件
- 02识别信任边界与攻击路径
- 03记录高风险资产和可用性等级
- 04跟踪快照来源与新鲜度
- 05归档旧版威胁模型
适用场景
- 01根据现有架构知识库生成威胁模型
- 02知识库快照变更后重新推导模型
- 03按轮次保存旧模型以供审查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ google/ mantis --skill mantis-threat-model安装后在 Claude Code 中输入/mantis-threat-model确认已加载。
详细介绍
威胁建模器(/mantis-threat-model)
系统目标
安全架构师。仅基于知识库(KB)中定义的实体和架构,综合信任边界、攻击面和攻击者画像,生成 THREAT_MODEL.md。
命令定义
- 命令:
/mantis-threat-model - 描述: 评估架构边界、入口点和信任边界,以构建威胁模型。
- 参数(均为可选;未提供 → 沿用今日行为):
--state_root <dir>:workspace/的父目录。若未提供,则使用相对于当前目录的./workspace/...。用于定位.mantis_state.json、KB 和归档目录。--snapshot_id <id>:本轮固定使用的SNAPSHOT_ID。仅用作写入THREAT_MODEL.md的来源标记值(KB_SNAPSHOT:行)。若未提供,则回退使用状态中的active_snapshot.snapshot_id;若该值也不存在,或snapshot_pinned为 false,则标记为字面值UNPINNED。--snapshot_root <dir>:为保持接口统一而接受,但不会使用 —— 此阶段不会读取目标源代码(Block A 步骤 0,仅处理发现项)。
输入/输出约定
- 读取:
workspace/.mantis_state.json——pass_number(用于按轮次归档),以及仅用于来源追踪的active_snapshot({root, snapshot_id, snapshot_pinned})。两者均可选;未提供 → 降级运行(参见向后兼容)。workspace/kb/architecture.md。workspace/kb/entities/*.md。- 上一轮留下的
workspace/kb/THREAT_MODEL.md(若存在)——仅读取其第一条KB_SNAPSHOT:行,用于步骤 0 的新鲜度检查。
- 写入:
workspace/kb/THREAT_MODEL.md(第一行为KB_SNAPSHOT:来源标头)。- 覆盖前,将上一轮的
workspace/kb/THREAT_MODEL.md(若存在)归档至workspace/archive/kb/THREAT_MODEL_pass_${N}.md。
- 前置条件:
- 知识库文件必须存在且已有内容。
- 幂等性保证:
- 将上一轮的
THREAT_MODEL.md(若存在)复制到本轮归档,然后以确定性方式原位覆盖workspace/kb/THREAT_MODEL.md。在快照未变化的情况下重新运行本轮,会生成等效模型并附带STALE标记(参见步骤 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.
此阶段的角色(仅处理发现项 / 仅使用 KB)。 /mantis-threat-model 绝不读取目标源代码。它使用的每项输入 —— architecture.md、entities/*.md、上一轮的 THREAT_MODEL.md 和 .mantis_state.json —— 都是相对于状态目录的(在 state_root/workspace 下读取,绝不在 CODE_ROOT 下读取)。因此,此阶段采用 Block A 步骤 0 的“仅处理发现项”路径:跳过 Block A 步骤 2–6,但仍从状态中读取 active_snapshot 以追踪来源;绝不能仅仅因为代码根目录未设置或未固定就停止。
维护一份高层威胁模型,明确说明攻击者是谁以及他们可以在哪里与系统交互,并以 KB 中已预处理的实体为依据。
按以下步骤执行威胁建模:
-
解析快照来源、新鲜度,并归档上一轮模型:
a. 计算
CUR(此威胁模型标记所依据的快照):- 若传入了
--snapshot_id→CUR= 该值。 - 否则,若状态中的
active_snapshot.snapshot_pinned为 true →CUR=active_snapshot.snapshot_id。 - 否则 →
CUR= 字面值UNPINNED(降级运行 / 沿用今日行为)。
b. **计算
PREV_TM(上一轮模型所依据的快照):**读取现有workspace/kb/THREAT_MODEL.md中符合^KB_SNAPSHOT:的第一行;其值(去除首尾空白后)为PREV_TM。若文件不存在、没有此类行,或值为空 →PREV_TM= 空字符串""。c. 同步差异判定(机械执行;严格字符串相等,不进行模糊比较):
CUR == "UNPINNED"→SYNC_OCCURRED = true(降级:始终重新推导)。- 否则,若
PREV_TM == ""→SYNC_OCCURRED = true(首次运行/旧版知识库)。 - 否则,若
PREV_TM != CUR→SYNC_OCCURRED = true(同步或脏编辑推进了快照)。 - 否则(
PREV_TM == CUR)→SYNC_OCCURRED = false(自上次建模以来快照未变)。
d. 归档先前的模型(每次处理),以确保覆盖不会造成数据丢失:
- 确定
N:从workspace/.mantis_state.json读取"pass_number"。如果缺失或无效,则扫描workspace/archive/,查找匹配findings_pass_N或loopN_findings的文件夹,并设N = max_found + 1;如果不存在归档,则默认为1。(与架构阶段使用相同规则。) - 如果
workspace/kb/THREAT_MODEL.md存在:确保workspace/archive/kb/存在(mkdir -p workspace/archive/kb/),并将文件复制(不要移动)到workspace/archive/kb/THREAT_MODEL_pass_${N}.md。你将在步骤 3 中覆盖现有文件。如果文件不存在,则跳过复制。 - 此步骤中的所有路径均相对于状态目录(位于
state_root/workspace下);绝不要添加CODE_ROOT前缀。
在步骤 1–3 和最终保存时,继续沿用
CUR、SYNC_OCCURRED和N。 - 若传入了
-
读取综合知识库:
- 读取
workspace/kb/architecture.md,了解系统的数据流和高层设计。 - 读取
workspace/kb/entities/中的文件,了解各个组件,以及/mantis-architecture阶段映射到这些组件的历史约束或漏洞模式。
- 读取
-
分析信任边界:
- 评估各实体,确定信任边界所在的位置。不可信数据会在哪些地方进入可信上下文?哪些组件会接收外部输入?
-
综合威胁模型:
- 编写一份全面、结构清晰的 Markdown 文件,并直接保存到
workspace/kb/THREAT_MODEL.md(覆盖旧文件)。 - **Token 优化:**使用文件写入工具将文件直接写入磁盘;不要在聊天回复中输出威胁模型文本。
请包含以下部分,确保下游规划 Agent 获得充足的上下文:
-
**系统概览摘要:**根据
architecture.md编写简明摘要。 -
**部署意图:**准确写出
Intent: PRODUCTION或Intent: SAMPLE_OR_TEST_ONLY中的一个。此判定的影响范围很大:/mantis-critic一旦读取到Intent: SAMPLE_OR_TEST_ONLY,就会将所有发现标记为SAMPLE_OR_TEST(驳回本次处理的全部结果)。因此,SAMPLE_OR_TEST_ONLY采用故障关闭机制,必须通过机械化检查清单:生产环境信号检查清单——只有在以下五项检查全部为 TRUE 时,才可以写入
Intent: SAMPLE_OR_TEST_ONLY。如果任何一项为 FALSE,知识库未提及任何一项,或你对任何一项不确定,则必须写入Intent: PRODUCTION。workspace/kb/entities/*.md中没有任何实体被分类为CRITICAL或STANDARD可用性(这两种分类都意味着有运行中的生产服务)。architecture.md未提及任何可从外部访问的服务、守护进程、服务器、 API 或网络端点,也未提及任何部署/打包描述文件 (systemd、Dockerfile/docker、kubernetes/k8s/helm、负载均衡器、 云/VPC/IaC、CI/CD 发布或发行)。- 知识库未描述任何可安装/发布的包或运行时入口点(例如
console_scripts/entry_points、main()/服务二进制文件、已发布的库或包清单)。 - 知识库中引用的每个组件/路径都仅位于测试/示例目录下——其路径包含
test、tests、example、examples、sample、samples、tutorial、demo、docs、fixtures中的一个——且没有任何组件/路径位于src、lib、pkg、internal、cmd、app、server或core等生产源代码根目录下。 - 没有任何实体文档描述真实(非模拟、非测试)的不可信外部输入 越过信任边界进入特权/生产逻辑。
同步后(步骤 0 中的
SYNC_OCCURRED == true),你必须根据当前知识库从头 重新运行此清单,且不得沿用先前的Intent:判定——同步可能会向此前仅含示例的树中添加生产代码, 否则可能会因此悄然忽略所有新发现。 -
信任边界: 明确、严谨地定义不可信输入与内部可信状态相交的位置。引用具体实体 (例如
[Auth Module](entities/auth_module.md))。 -
威胁行为者与攻击向量: 定义潜在攻击者的特征 (例如,未认证的网络攻击者、恶意本地用户)以及他们能够触及的具体边界。
-
高风险资产: 攻击者试图破坏的数据、执行权限或可用性目标。对于可用性目标, 根据知识库将其归入以下某个可用性等级:
CRITICAL:中断会立即对 24/7 全天候运营造成影响。STANDARD:重要运营;可容忍短暂停机。LOW_CRITICALITY:非阻塞型实用工具;中断只会造成轻微不便。
- 编写一份全面、结构清晰的 Markdown 文件,并直接保存到
为模型添加标记并保存:
workspace/kb/THREAT_MODEL.md的第一行必须是来源标记KB_SNAPSHOT:,后接CUR(来自步骤 0)——例如KB_SNAPSHOT: <CUR>, 或在降级模式下使用KB_SNAPSHOT: UNPINNED。下一轮会将其读回为PREV_TM,而mantis-critic会将其用作知识库新鲜度检查。- 如果
SYNC_OCCURRED == false(自上次模型以来快照未变化):可以 复用先前模型的实质内容,但必须在KB_SNAPSHOT:行之后紧接着插入以下 STALE 横幅:> STALE: Threat model NOT re-evaluated this pass; carried unchanged from snapshot <CUR>.如果SYNC_OCCURRED == true:不要输出 STALE 横幅——本轮已重新推导 所有章节,包括部署意图清单。 - 直接保存到
workspace/kb/THREAT_MODEL.md(相对于状态目录;先前文件已在步骤 0d 中复制到本轮存档)。使用文件写入工具;不要在聊天中输出模型。完成后通知用户。