公司动态

Coldcard 漏洞揭示:代码注释与变更比例低,开发者忽视编译器警告致风险

📅 2026/8/3 6:53:57
Coldcard 漏洞揭示:代码注释与变更比例低,开发者忽视编译器警告致风险
【一条提交信息揭示的 COLDCARD 近期漏洞】这是一篇来自知名 Core - Lightning 开发者 ddustin 的客座文章。他深入研究了 Coldcard 固件的提交历史揭示了事件的经过以及代码失败的原因。【引言】开始调查 Coldcard 黑客攻击事件时着实令人震惊下面为您解释原因。开发者处理代码时会将代码变更组织成“提交commit”的变更集目的是清晰展示代码变更历史包括内容、原因和方式这也是为应对比特币用户资金大规模被盗情况以便调查确切原因。优秀开发者会编写清晰提交信息伴随代码变更解释目的。编写时通常建议每次提交代表较小代码变更减少注释内容。开发者的好目标是提高提交信息与代码变更比例变更代码行数越多需更多注释解释原因“更多的信息”和“更少的代码变更”是不错做法。这里有个例子从自身工作随机选取提交信息 235 个字符变更 15 行代码比例约为 16。而 Coldcard 中引入低熵漏洞的提交信息仅 5 个字符“runs”变更 1534 行代码比例约为 0.003这是极其糟糕的注释与代码变更比例。虽然极少数情况下低注释比例合理但变更代码“最重要的部分”并非如此。涉及项目安全关键功能的代码需更高注释与变更比例且要严格审查。导致 Coldcard 弱熵问题的第二次提交信息仅 1 个字符“x”变更约 1000 行代码比例约为 0.001。【问题所在】在标题为“runs”的提交中比例约为 0.003他们似乎在导入并配置 C 代码让自定义 MicroPython 代码在所有 Coldcard 运行的 STM32 开发板上运行。STM32 是这类小型设备常用 CPU此类配置常见。在“runs”提交中硬件随机数生成器RNG被代码行禁用#define MICROPY_HW_ENABLE_RNG (0)这导致漏洞。将此值设为零会让默认 MicroPython RNG 代码不使用硬件 RNG 设备而用 Yasmarang RNG 代替。开发者添加内联注释“解释”变更// We have our own version of this code. Coldcard 版本的这段代码似乎参考了 rng.h 和 rng.c 中添加的函数。这些函数似乎是为覆盖 STM32 RNG 库的 pyb_rng_get_obj 函数但遇到问题。STM32 的 rng.c 文件已定义 pyb_rng_get_obj 变量并赋值同一个变量不能有两个定义还能编译通过。提交 37e4af5 添加自定义 rng.c 文件复制粘贴相同宏定义导致代码无法编译编译器报错“duplicate symbol pyb_rng_get_obj”。推测开发者沮丧中把 MICROPY_HW_ENABLE_RNG 设为 0解决了编译器错误。有时开发者无计可施会尝试随机方法设为 0 虽让编译器错误消失但“原因是错的”掩盖了两个冲突定义的编译器错误。将其设为零移除了使用硬件随机数生成器的代码产生副作用移除 pyb_rng_get_obj 第二个定义“修复”了编译器错误。编译器错误本提醒程序员重新考虑逻辑但开发者未这么做忽视并消除了警告。现在清楚了开发者试图覆盖变量遇到冲突定义面对“重复符号”错误随机修改代码让其“运行”。发现设为 0 能编译通过可能不知原因想出理论不需要那个因为有自己版本的代码。其对 pyb_rng_get 的定义完成不想运行的代码也关闭了。【令人困惑的调用链】Coldcard 的固件用 C 语言编写应用层用 Python 编写Python 代码调用 C 代码开发者覆盖了 pyb_rng_get 函数。但不幸的是其覆盖的函数并非 Coldcard v4.0.0 版本 Python 代码实际调用的函数该版本 Python 代码在 make_new_wallet() 函数中调用了 random.bytes()。将 MICROPY_HW_ENABLE_RNG 设为 0 关闭了 STM32 库提供的硬件代码允许开发者设置 pyb_rng_get_obj但 pyb_rng_get_obj 是 Python 可见的 pyb.rng() 可调用对象并非开发者在钱包函数中调用的内容。他们使用 random.bytes(32)跳过 pyb_rng_get 调用路径调用 rng_get。由于 MICROPY_HW_ENABLE_RNG 设为零rng_get 使用 MicroPython STM32 rng.c 的定义调用不安全的 Yasmarang 非硬件钱包熵。简单说固件变更覆盖了创建新钱包时未使用的函数因包含 Python 方法覆盖在所有情况下关闭硬件 RNG 使用转而用非常弱的随机数生成器。最后证据就是提交信息“runs”。开发者遇到这种情况应停下来无论报酬多少都不值得给他人带来潜在巨大破坏不要发布不理解的代码。【对 MicroPython 的反思】从核心看这似乎是多层复杂性的后果有 MicroPython 库、C 代码和 Python 应用之间的绑定还有 Coldcard 添加的新功能。打补丁的开发者是不是被迫编写和处理 C 代码的 Python 开发者呢MicroPython 给嵌入式开发者一种错觉认为无需了解 C 语言、CPU 或其他高级概念就能进行嵌入式编程这是谎言这场灾难就是相信这个谎言的后果。开发者必须理解发布的代码没有借口。层层误导会让理解更困难进行变更时要确保达到预期效果。这里的提交信息揭示了真相对代码“最关键的部分”缺乏谨慎和理解不可原谅。作为比特币开发者要花时间理解变更清晰记录并验证是否达预期效果。当人们生活受影响时不会也不应同情开发者开发者要意识到让资金面临的风险任务至关重要。希望整个行业从这次事件吸取教训开发者社区携手发布安全的代码。