mcpField
T
threat-modeling

threat-modeling

github.com/bitwarden安全163119 次安装今天更新
代码仓库

关于 threat-modeling

面向 Bitwarden 工程团队的安全威胁建模技能,覆盖初步评估并辅助后续审查与验证。结合 STRIDE、数据流图和 Bitwarden 安全定义,强调威胁范围与目标的一致性。

主要功能

  1. 01生成 Mermaid 数据流图
  2. 02按 STRIDE 识别威胁
  3. 03撰写安全定义与目标
  4. 04检查架构决策记录对齐
  5. 05评估目标状态与风险

适用场景

  1. 01为新服务开展初步安全评估
  2. 02梳理跨服务数据流和信任边界
  3. 03准备 AppSec 审查材料

安装

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

$npx skills add https://github.com/bitwarden/ai-plugins --skill threat-modeling

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
data-flow-diagram.md
security-definition-document.md
threat-catalog.md
references/
bitwarden-vocabulary.md
security-principles.md
stride-framework.md
writing-quality-sds.md

详细介绍

Bitwarden 的参与模型

Bitwarden 的安全工作采用 4 阶段参与模型。此技能主要支持第 1 阶段(工程团队负责),并协助准备第 2 至第 4 阶段的材料。

第 1 阶段:初始安全评估(工程团队)
  1. 检查 Bitwarden 的架构决策记录,了解其中是否已有涵盖待审查系统或组件的决策(参见 ${CLAUDE_PLUGIN_ROOT}/references/adr-alignment.md)——威胁模型应与已接受的架构保持一致,而不是默默重新推导或与之矛盾
  2. 创建数据流图(Mermaid)
  3. 将安全要求与产品要求分开定义
  4. 提出安全定义(威胁模型 + 安全目标)
  5. 使用 STRIDE 识别初始威胁(参见 references/stride-framework.md)
第 2 阶段:AppSec 团队审查(AppSec + 工程团队)
  • 提前分享数据流图和安全定义
  • 协作梳理系统架构
  • 验证或完善拟定的安全定义
  • 识别其他威胁并评估风险
  • 不要假设外部缓解措施已经存在
第 3 阶段:实施(工程团队)
  • 实施必要的安全缓解措施
  • 针对尚无现有保护措施的威胁创建 Jira 后续任务
  • 将安全考量纳入冲刺规划
第 4 阶段:测试与验证(工程团队 + AppSec)
  • 验证缓解措施是否按预期生效
  • 在代码审查中采用对抗性思维
  • 通过逆向推演来检验假设(例如:“我能绕过 SSO 吗?”)
  • 随着系统演进更新安全定义

安全定义

安全定义(SD)是 Bitwarden 用于传达系统安全态势的正式结构。每项定义都包含三个部分:威胁模型(攻击者能力)、安全目标(系统作出的保证)以及已接受的目标状态(诚实评估当前是否已达成目标)。

编写定义时,请使用 Bitwarden 的标准术语——完整词汇表参见 references/bitwarden-vocabulary.md。安全目标应与 Bitwarden 的安全原则(P01-P06)保持一致——参见 references/security-principles.md。

威胁模型组件

描述攻击者的能力和限制——他们能做什么、不能做什么。务必同时说明两方面,以准确界定范围:

  • “攻击者可以在用户的客户端注销后运行用户空间进程” + “攻击者无法访问安全存储机制”
  • “攻击者可以访问数据库,并读取和写入 Send 表” + “攻击者无法访问 ASP.NET Core Data Protection 加密密钥”

必要时提供具体示例(例如,“一个例子是设备失窃”)。不要假设已有外部缓解措施——即使获取身份验证令牌很困难,也要探讨攻击者持有令牌时会发生什么。

界定威胁模型范围时,遵循以下规则:

  • 删去被支配的威胁。 如果你描述的攻击者能力严格弱于已接受为范围外的某项能力,请删除该 SD——其剩余风险说明会沦为“相当于完全入侵用户账户”之类的同义反复。有关被支配威胁反模式以及 references/writing-quality-sds.md 中的 Dominated Threat 一词,请参阅该文档,以及 references/bitwarden-vocabulary.md。
  • 纳入被动观察者,而不只是对手。 对于任何传输至外部服务的秘密或受保护数据(LLM 提供商、日志聚合器、分析管道、训练数据收集器),至少编写一个 SD,将攻击者设定为诚实但好奇。机密性损害往往源自_可见性_,而非恶意——仅以对抗性为背景会遗漏基本风险。请参阅词汇表中的 Passive Observer 条目。
  • 依据目标平台验证“攻击者无法访问 X”这一限制。 每项限制在范围涵盖的每个 OS/运行时上都必须属实。一个常见陷阱是,误以为某项能力需要内核级权限,但实际上在 Linux 和 Windows 上无需特权即可实现(例如,读取其他进程的环境变量)。如果限制不成立,该 SD 的范围界定就有误。
安全目标组件

针对威胁模型,陈述简洁、可测试且不可发生的情况。具体指出相关资产(令牌、密钥、保险库数据):

  • “用户的客户端注销后,攻击者无法访问有效令牌”
  • “攻击者无法获取任何不属于自己的已解密 MasterKeys”
  • “攻击者只能读取加密的电子邮件地址列表”

每项目标都必须附带理由——分为三个部分,每部分一行:

  • 原则——该目标落实了哪项 Bitwarden 原则(P01–P06)。请参阅 references/security-principles.md。
  • 资产——要保护的具体数据、密钥或令牌。
  • 危害——目标若未实现,用户可感知的后果(例如,“主密码暴露给第三方 LLM 提供商,并可能进入其训练管道”)。

没有理由的目标只是主张,而非要求。理由能让审查者判断该目标是否不可或缺,或是否可以删去。

关于目标表述的另外两条规则:

  • 根据运行时检验目标是否切实可行。 对于垃圾回收、字符串驻留的运行时(JavaScript、.NET、JVM、Python),声称秘密会“从内存中清除”“归零”或“不被保留”的目标无法落实。如果运行时无法保障该目标,应改述为运行时_能够_保障的内容(缩小作用域、使用短生命周期引用、进程隔离),或明确标记 Accepted Goal Status 为未达成,并链接至系统性限制。不要编写语言本身无法保障的目标。
  • 传递秘密时,优先使用 stdin 或文件描述符,而非环境变量/命令行参数。 如果目标禁止将秘密暴露于 process.env 或 argv,实现就必须使用 stdin 或继承的文件描述符。若 SD 的目标禁止暴露于环境变量,但实现却通过环境变量传递秘密,则前后矛盾——请修改设计或目标,但不要两者兼而有之。
已接受的目标状态组件

如实评估当前状态:

  • 目标已达成 — 说明如何达成(例如:“清除用户状态时会从磁盘中删除已存储的令牌”)
  • 目标部分达成 — 分别说明哪些方面有效、哪些无效,并为每个方面使用单独的指标
  • 目标未达成 — 说明差距以及接受该差距的原因
  • 尽力而为 — 对于取决于平台能力的目标(例如:“对于无法访问安全存储的客户端,例如 Web 和浏览器客户端,此目标无法实现”)

如果已知某个目标存在问题,请链接到相关的跟踪问题。注明范围方面的注意事项(例如:“这些定义不适用于将 Vault Timeout 设为 Never 的情况”)。

另外两条规则:

  • 量化“短暂”或“短期存在”的理由。 如果接受残余风险的依据是“暴露时间很短”,请说明具体时限。例如:“机密信息会在子进程的环境变量中保留,直至 bw unlock 执行完毕;时长随 KDF 迭代次数和保管库大小而变化——在具有代表性的硬件上观察到的时长为 1 到 8 秒。”_不带数字的“短暂”不算可接受的状态,而只是一种希望。_请参阅“暴露窗口”词汇条目。
  • 确保内部一致。 威胁模型、安全目标和已接受的目标状态必须相互一致。如果威胁模型将能力 X 纳入范围,目标就必须防御 X,状态也必须说明该防御是否有效。如果目标禁止通过环境变量暴露信息,而实现却使用了环境变量,那么安全定义就是错误的——请选择这三者之一进行修改,并据此更改。不一致并非风格问题,而是安全定义未能描述系统。
编写安全定义
  • 出错没关系——目的是开启讨论,看看这些定义能否被攻破
  • 从系统 SHOULD 保证的内容入手,然后通过威胁分析进行验证
  • 将宏观层面的定义(例如端到端加密)与特定于功能的微观定义分开
  • 按顺序为定义编号(SD1、SD2、SD3)——每条定义都是一个独立单元
  • 如果功能引入了特定领域的词汇,请附上功能专用术语表
  • 按影响而非编号优先排序。 一份列出实际影响设计的 3–5 个威胁的简短文档,比一份包含 15 条安全定义、却将重要威胁埋没在冗余信息中的文档更有用。添加安全定义前,请先问:“如果这个威胁不存在,设计会改变吗?”如果答案是否定的,它很可能只是代码质量方面的说明,而非安全定义。
  • 为每条安全定义标注关键性级别(Critical / High / Medium / Low),并按关键性从高到低排列文档,让审阅者先看到支撑设计的关键安全定义。优先级判断方法请参阅 references/writing-quality-sds.md。
  • 冗长也是一种失误模式。 早期大模型代码审查中常见的反模式——冗长而信息量低的清单——同样困扰着生成的安全定义。删去仅描述实现细节的安全定义(例如,未来维护者将常量修改为包含 shell 元字符的内容),除非它们对设计至关重要。

工件生成

生成工件时,使用 examples/ 中的模板:

  • examples/security-definition-document.md — 完整的 SD 文档模板,包含术语表、编号定义、关键性标记、目标依据和已接受的目标状态
  • examples/data-flow-diagram.md — 带信任边界的 Mermaid DFD 模板
  • examples/threat-catalog.md — 威胁目录表和缓解措施跟踪模板

编写或审查 SD 时,请参考以下资料:

  • references/writing-quality-sds.md — 反模式(占主导地位的威胁、仅考虑对抗者的攻击者、无法强制执行的目标、理想化的限制、shell 引号 SD、“短暂暴露”陷阱)和自洽性检查清单
  • references/bitwarden-vocabulary.md — 标准术语,包括 被动观察者、占主导地位的威胁 和 暴露窗口
  • references/security-principles.md — P01–P06,每个目标的依据行都会引用这些原则
  • references/stride-framework.md — 用于结构化威胁识别的 STRIDE 类别
  • ${CLAUDE_PLUGIN_ROOT}/references/adr-alignment.md — 安全工程师技能之间通用的架构决策记录(ADR)对齐检查

何时联系 AppSec

遇到以下情况时,团队应启动与 AppSec 团队(#team-eng-appsec)的完整协作:

  • 新建项目或新服务
  • 数据共享变更(组织成员资格、Send、共享功能)
  • 组件之间新增 IPC 通道
  • 跨域或跨源功能
  • 不确定安全影响 — 首先进行初步安全评估,并将发现发布到 #team-eng-appsec,同时注明是否需要完整协作尚不确定

快速提问(例如,对第三方库或编码实践的疑虑)不需要完整协作 — 直接发布到 #team-eng-appsec 即可。

关键规则

  • 在技术拆解中,将产品需求与安全需求分开。两者目的不同,相关利益方也不同。
  • 安全定义是持续演进的文档。 功能变更、出现新威胁或发现安全问题时,应重新审视这些定义。
  • 复杂性会增加漏洞风险。 将过于复杂的安全关键代码标记为技术债务。依赖项众多、逻辑错综复杂的代码极难保障安全。
  • 威胁建模无法识别所有漏洞。 它只是众多工具之一。应结合代码分析、安全测试和对抗性审查。
  • 不要假设外部缓解措施一定有效。 定义威胁模型时,应考虑攻击者绕过外部控制措施后会发生什么。
  • 占主导地位或实现上不言自明的威胁都是噪声。 删除那些残余风险描述可归结为“等同于完全攻陷用户账户”,或唯一缓解措施是“审查者注意到某个常量被修改”的 SD。它们会降低信噪比,并掩盖真正重要的威胁。
  • 每个安全目标都必须说明依据。 将每个目标与 Bitwarden 原则(P01–P06)、受保护的资产和用户可见的危害关联起来。没有依据的目标无法确定优先级,也无法评估其必要性,而且往往只是因惯性而非价值通过审查并保留下来。

最终确定一组 SD 之前,请应用 references/writing-quality-sds.md 中的自洽性检查清单。

评论

支持 Markdown