LifeOS CompromiseScenario 工作流:用资产图爆炸半径与风险登记册回答"资产被攻破后会怎样"
【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS
导读
本文讲解 LifeOS 中 ThreatModel 技能的核心工作流 CompromiseScenario:当你说出"如果 X 被黑客攻破会发生什么"时,它如何借助 Atlas 资产图(asset graph)计算真实的爆炸半径(blast radius)、推演攻击者的一跳信任(one hop of trust)、按数据暴露而非资产体量给影响打分,并把落地风险写入可持久化、可复审的风险登记册。读完本文,你将掌握资产图三条取证命令(blast/owns/exposed)的语义与底层 SQL 遍历、影响/可能性评分的锚定规则、Scenarios/<asset-slug>.md场景文档的七要素写法,以及RiskRegister.ts确定性 CLI 的完整用法。
该工作流定义于 CompromiseScenario.md,技能总体约定见 SKILL.md,配套的登记册 CLI 见 RiskRegister.ts。
工作流定位:什么时候触发 CompromiseScenario
ThreatModel 技能共有四条工作流,由 SKILL.md 中的路由表统一分派:
| 工作流 | 触发语 | 文件 |
|---|---|---|
| SensitiveDataMap | "我们的敏感数据在哪"、"数据分类"、"哪些资产持有敏感数据" | SensitiveDataMap.md |
| CompromiseScenario | "如果 X 被攻破"、"入侵场景"、"X 的爆炸半径" | 本文主题 |
| ThreatModelTarget | "对 X 做威胁建模"、"对整个资产做风险评估" | ThreatModelTarget.md |
| RiskRegister | "风险登记册"、"添加风险"、"风险复审"、"接受风险" | RiskRegister.md |
CompromiseScenario 的核心定位是防御性建模:只推演"若某资产被攻破会暴露什么、能触达什么、如何检测与响应",绝不执行任何利用、扫描或破坏性动作。主动渗透测试属于单独的 offensive-security 技能。
执行入口与语音通知
按 SKILL.md 约定,每次执行工作流时需同时完成语音通知与文本通知:
curl -s -X POST http://localhost:31337/notify -H "Content-Type: application/json" \ -d '{"message": "Running CompromiseScenario in ThreatModel"}' > /dev/null 2>&1 &同时在终端输出一行Running CompromiseScenario in ThreatModel...,便于用户感知 Agent 正在执行哪条工作流。
Step 0 — 充分性检查(Sufficiency Check)
工作流要求先锚定一个具体的资产:可以是 Atlas 中的 key、一个应用、一个域名或一个 worker。若用户没有给出资产且无法从上下文推断,则必须反问用户选哪个资产;否则直接进入正题。这一步防止对"整个资产"这种过宽范围做漫无目的的推演——宽范围建模应交给 ThreatModelTarget.md 的组合式流程。
理想产出物:可执行的场景文档Scenarios/<asset-slug>.md
CompromiseScenario 的最终交付物是一份写入私有数据目录的 Markdown 场景文档Scenarios/<asset-slug>.md,让应急响应人员拿到即可行动。文档必须包含以下七要素:
- 资产与信任(Asset & trust)— 资产是什么、持有哪些数据(依据 SensitiveDataMap / 数据分类)、能触达什么(凭证、服务绑定、部署密钥,至少一跳信任)。
- 爆炸半径(Blast radius)— 谁依赖它、它拥有什么,来自资产图,且作为派生证据对待。
- 入侵推演(Compromise walk)— 合理的入口、攻击者读取/写入/横向移动的路径、最坏的现实结局。
- 暴露面(Exposure)— 具体暴露的数据类别,以及大致多少条记录/多少个系统。
- 检测(Detection)— 什么信号能捕获这次入侵(日志、扫描器、异常),以及该信号今天是否已存在。
- 响应(Response)— 遏制步骤、凭证轮换指引(指向事件响应 runbook 而非重复其内容)、恢复方案。
- 残余风险(Residual risk)— 即便按计划响应后,仍暴露在外的部分。
要素 1 中提到的"数据分类"对应 DataClassification.md 定义的 RESTRICTED / CONFIDENTIAL / INTERNAL / PUBLIC 四类;SensitiveDataMap 工作流则用credentials · pii · financial · health · customer-data · source-private · internal-only · public这组类别为每个持有数据的资产打标。场景文档中的暴露面描述应复用这两套分类词汇,保证与登记册、数据地图口径一致。
爆炸半径:资产图三条取证命令
Atlas 是 LifeOS 的资产图 CLI(入口见 Atlas.ts),SQLite 作为系统记录(schema 见 Store.ts)。CompromiseScenario 用它把"爆炸半径多大"从拍脑袋变成可重复的查询:
bun ~/.claude/LIFEOS/ATLAS/Atlas.ts blast <key> # inbound: 谁依赖 X bun ~/.claude/LIFEOS/ATLAS/Atlas.ts owns <key> # outbound: X 拥有什么 / 删除 X 会孤儿化什么 bun ~/.claude/LIFEOS/ATLAS/Atlas.ts exposed <key> # X 会泄露哪些凭证, compromise-tier 优先三条命令的语义差异在 Store.ts 的查询实现中一目了然:
blast(入站):沿OPERATIONAL_EDGE_KINDS(SERVES、ROUTE、CALLS、DEPENDS_ON、RUNS_ON、OWNS、DEPLOYED_FROM、HOLDS)反向递归,回答"哪些资产在运行上依赖 X"。注意HOLDS也在其中——凭证被轮换时,持有它的资产会"坏掉",所以blast credential:X能返回所有需要新值的系统。owns(出站):沿OWNS边正向递归,回答"删除/丢失 X 会孤儿化(orphan)什么"。exposed(泄露方向):沿OWNS+HOLDS双向递归,只返回kind = 'credential'的资产,并按凭证优先级排序。它回答的是事件响应的方向问题——"这个资产被攻破了,它泄露了什么"——与blast("我轮换 X 会弄坏什么")正好互补。
exposed的输出还会额外打印两条关键信息:暴露的凭证总数、其中 compromise-tier(CRITICAL)的数量,以及一句重要的处置提示——先遏制资产再轮换凭证,否则轮换只是把新值交到还活着的立足点上(见 Atlas.ts 中exposed命令实现)。
另一半信任继承:DEPENDS_ON 数据存储查询
凭证之外,资产还能通过数据存储触达数据。工作流给出了配套的只读 SQL 查询,找出 X 依赖的活动数据存储:
bun ~/.claude/LIFEOS/ATLAS/Atlas.ts sql "SELECT a.kind, a.canonical_key FROM edge e JOIN asset a ON a.id=e.dst WHERE e.kind='DEPENDS_ON' AND e.status='active' AND e.src=(SELECT id FROM asset WHERE canonical_key='<key>')"atlas sql在实现上是结构性只读的——Atlas.ts 以readonly: true打开数据库连接,"结构上无法写入"。exposed加上这条 DEPENDS_ON 查询,就让要素 1 的"一跳信任"从主观判断变成确定性的枚举。
为什么这条查询重要:一个自身没有任何数据的 worker,通常正是通过它的绑定(bindings)把影响继承到了 5 分。所以工作流明确要求:在打分影响之前,两条查询都跑完,不要用眼睛估。这正是 SKILL.md 中 gotchas 所强调的"场景影响包含资产能触达的,而不仅是它存储的"。
Atlas 不可用时的回退
如果当前安装没有 Atlas,工作流退回到"用户枚举 + 仓库/配置检查"来构建爆炸半径,并且必须在输出中明确声明这一点——绝不允许凭空编造资产清单(Never invent an inventory)。同理,SensitiveDataMap 在没有资产图时也必须声明覆盖率是"用户枚举的"而非"图完备的"。
凭证集中:它本身就是一个独立发现
工作流给出了一条容易被忽略的高价值规则:
当
exposed在单个资产上返回了多于一个compromise-tier 凭证类别时,这种"集中"本身就是一条独立的发现。
举个例子:一个资产上同时持有两类凭证,且分别触达两个不同的信任域,那它把本来应该存在的信任边界击穿了。此时应该把它写成一条独立风险,而不是并进该资产主场景的分数里——因为缓解方式不同:前者需要拆分凭证(split),而不是轮换(rotate)。
从源码看,exposed的排序逻辑把CRITICAL, HIGH, MEDIUM, LOW, DEFER, ORPHAN, UNKNOWN作为固定优先级序(见 Atlas.ts),所以"多个 compromise-tier 类别落在同一资产"这种集中信号可以直接从输出中机械化识别,不需要人工翻找。
图是派生证据,不是权威
工作流反复强调一个认知边界:
- 高风险的场景:在把爆炸半径当作完整结论之前,必须用供应商的权威 API(provider's authority API)复核关键边——因为图可能滞后或欠建模(graph can lag or under-model edges)。
- 图看不到的东西必须点名:vendor-only 的 OAuth 授权、SSH 密钥、浏览器会话、密码管理器里的内容——这些要作为场景的一部分写出来,而不是当作遗漏跳过。
这个边界在数据收集层面同样成立:凭证收集器(Secrets.ts)只读取凭证注册表(名字 + 分类,绝不读值),它明确记录了一个"故意不伪造"的已知盲区:只存在于供应商侧、从未落到本地任何文件的凭证(如 OAuth 授权、控制台签发的 token)对任何收集器都不可见,必须走供应商自己的审计面。
这与 SecurityModel.md 的贯穿性问题一脉相承:"到这份数据的真实路径是什么?"——图给出的是当前状态快照,而权威永远在平台侧。
影响与可能性评分(喂给登记册)
影响(Impact 1-5):锚定"暴露了什么 + 触达了什么"
影响打分不取决于资产的体量,而取决于资产被攻破后暴露与触达的后果:
| 分数 | 判定标准 |
|---|---|
| 5 | 触及多个系统的凭证、规模化客户数据,或金融/健康类 PII |
| 4 | 触及一个持有数据的系统的凭证,或一个私有数据存储 |
| 3 | 仅内部数据,或对公共面有写权限 |
| 2 | 有限的内部暴露 |
| 1 | 仅公开数据,无横向移动可能 |
对照 DataClassification.md 的四级分类可发现其一致性:RESTRICTED(凭证、第三方 PII、客户数据、财务/健康源文档)和 CONFIDENTIAL(个人健康、财务、安全态势)直接对应影响 4–5;INTERNAL 对应影响 2–3;PUBLIC 对应影响 1。
可能性(Likelihood 1-5):锚定暴露面
可能性由以下因素决定:是否公开 URL、认证边界的强度、补丁/凭证卫生状况、是否已有检测手段。
分数换算(确定性,无模型判断)
SKILL.md 与 RiskRegister.ts 中scoreRisk()/levelFor()共同定义了换算规则:
score = likelihood(1-5) × impact(1-5) Low 1-4 · Medium 5-9 · High 10-14 · Critical 15-25scoreRisk()会先校验两个维度必须是 1–5 的整数,否则直接抛错;levelFor()按 15 / 10 / 5 三个阈值切分等级。这意味着分数计算在数据路径上完全确定——模型不参与算术,只提供两个锚定后的输入。
落地风险:RiskRegister 确定性 CLI
场景推演出的每一条真实风险都要落进登记册。工作流给出了add命令的完整形态:
bun ~/.claude/skills/ThreatModel/Tools/RiskRegister.ts add \ --title "<short risk>" --threat "<threat>" \ --assets "<atlas-key>" --data-classes "<classes>" \ --likelihood <1-5> --impact <1-5> \ --response "Scenarios/<asset-slug>.md" --review-by <YYYY-MM-DD> \ --mitigation "<control>"其中--response指向本工作流生成的场景文档——这是"场景文档 ↔ 登记册"的双向引用:场景文档说明风险为何成立,登记册条目负责跟踪处置与复审。
登记册的完整命令面
RiskRegister.md 给出了意图到命令的完整映射,这里按场景流程常用顺序整理:
T="bun ~/.claude/skills/ThreatModel/Tools/RiskRegister.ts" $T init # 初始化数据目录 + 空登记册(同时创建 Scenarios/ 子目录) $T stats # 态势快照:总数、开放数、按等级/状态分布、逾期复审数 $T list # 列出开放风险, 按分数从高到低 $T list --all # 含已关闭 $T list --level Critical # 按等级过滤 $T show R-001 # 查看单条详情 $T update R-001 --status accepted --notes "accepted by <owner>: <rationale>" # 接受风险(是决策,不是删除) $T update R-001 --likelihood N --impact N --add-mitigation M --review-by DATE # 重新打分/追加缓解/顺延复审 $T close R-001 --reason "…" # 关闭(必须给理由) $T review # 列出逾期或缺失复审日期的风险 $T export # 重新生成 RiskRegister.md 视图数据结构与安全门(源码级)
从 RiskRegister.ts 的实现可以看到几个关键设计:
- JSON 存储是系统记录:
risk-register.json是唯一事实来源;RiskRegister.md是由exportMarkdown()生成的视图,文件头明确写着"GENERATED,请通过 CLI 编辑,不要在此编辑"——下次导出会覆盖手改内容。 - 代码/数据强制隔离:
resolveDataDir()默认数据目录为~/.claude/LIFEOS/USER/SECURITY/THREATMODEL/(可用THREATMODEL_DATA_DIR覆盖),且结构上拒绝任何解析到skills/路径内的数据目录(检测到即exit 2)。这保证了"公开代码树永不包含数据"。 - 无密钥值:凭证一律按环境变量名引用,
Risk类型里根本没有存放值的字段;注册表条目的历史事件(history: [{ts, event}])只记录变更语义,不记录值。 - 每条风险必有
review_by:review命令会列出review_by为空或已到期的未关闭风险。正如 SKILL.md 的告诫——"没人复审的登记册比没有更糟,它制造虚假的安全感"。
复审节奏
建议的处置循环是:review拉取到期清单 → 逐条判定(仍成立?已缓解?接受?)→update状态并把review_by顺延 → 对无负责人或无缓解的 Critical/High 单独上抛。关闭风险必须使用close并给出--reason,保持审计轨迹。
约束与安全门(Constraints)
工作流明确列出三条红线,与整个 ThreatModel 技能的安全模型一致:
- 只读建模:只推演入侵场景,绝不执行利用、扫描或破坏性动作;主动进攻性测试属于独立的 offensive-security 技能。
- 文档与登记册中无密钥值:任何 token、key、cookie 都不允许出现在威胁模型输出中,凭证仅以环境变量名引用。
- 只写数据目录:场景文档与登记册条目只能写入数据目录(
THREATMODEL_DATA_DIR,默认~/.claude/LIFEOS/USER/SECURITY/THREATMODEL/),永不写入技能树。
这三点在 SecurityModel.md 的"代理与安全机制"一节有系统化支撑:外部内容一律视为数据而非指令,egress 扫描拦截 secret 形状的字符串,发布管线是私有安装通向公共面的唯一通道且 fail-closed。
收尾(Close):一次场景推演的交付清单
工作流结束时的总结必须覆盖:
- 最坏的现实结局(worst realistic outcome)是什么;
- 暴露度最高的数据类别有哪些;
- 检测今天是否已存在(对应场景文档要素 5,且要区分"应有信号"与"现有信号");
- 落地的风险清单(ID + 分数);
- 任何 Critical 风险都要标记为需要立即关注。
至此,一次"如果 X 被攻破会怎样"的提问,闭环为:资产图爆炸半径(blast/owns/exposed+ DEPENDS_ON 查询)→ 七要素场景文档 → 锚定数据暴露的影响评分 → 登记册条目(add+review_by)→ 复审循环。整条链路在数据路径上是确定性的、可审计的,这正是 ThreatModel 技能区别于"让模型自由发挥"的核心——推演允许模型判断,但事实、分数与记录由代码与证据决定。
进一步阅读:技能总览见 SKILL.md;资产图 CLI 实现见 Atlas.ts;图数据模型与遍历查询见 Store.ts;凭证收集器的边界见 Secrets.ts;数据分类口径见 DataClassification.md;安全模型总纲见 SecurityModel.md。
【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考