5 月 4 日在五一假期的最后一天,从上午开始很多朋友陆续发现自己的扩展被禁用,无法安装新扩展,这种情况一直持续到当天晚上,我们放出了热更新,但用户需要等待一段时间才能接收到,且关闭了实验项目的用户需手动操作。随后为了修复这个问题我们陆续发布了 66.0.4、66.0.5 两个小版本,对于使用 52-60 等不支持版本,和 61-65 非最新版的用户,也可以通过安装扩展的方式恢复使用。

问题发生时是在假期,这多少减少了遇到此问题的用户数,Firefox 的现有机制决定了我们并没有多少有效且及时的方式来快速的解决这件事。从统计数据来看,有 60% 的用户安装了扩展,中国用户由于同步机制的存在可能要更高。无论是什么原因,当一个问题会影响超过 60% 的用户时,都是不能被忽视的。考虑到部分用户为了接收热更新被迫开启了实验项目,Mozilla 删除了 5 月 4 日至 11 日收集的所有遥测数据。这篇文章会说明为什么会发生这件事,已经后续的止损,修复是如何进行的。

我会从研发与运营两侧来说明对该问题的应对。

背景:扩展的签名机制

扩展在 Firefox 中安装运行需要被签名,签名的流程是根证书离线存于硬体安全模块(HSM)中,根证书用于签署新的中间证书,中间证书用于签署最终实体证书,后者又签署单独的附加组件。中间证书是保持在线的,每隔几年需要由根证书重新签署。

每个附加组件(包括扩展、语言包、主题)都由其自己的终端实体证书签名,但几乎所有附加组件都共享一个中间证书。正是这个证书遇到了问题:它在 5 月 4 日凌晨 1 点(UTC)过期,使用该证书签名的附加组件将无法载入到 Firefox 中,5 月 3 日下午 6 点(UTC)有同事意识到了这个问题,开始著手修复。问题发生时对应的北京时间大约是上午 9 点,部分用户没有立即感知到扩展被禁用是因为 Firefox 对附加组件有效性的检查不是及时的,如果检查的时间晚于接收热修复的时间,那么可能不会受此问题的影响。

修复过程

  • 控制损害

首先,我们禁止签署新的附加组件(因为当时的证书已失效),通过 Normandy 研究系统推送第一个热修复,目的是禁止重新验证附加组件上的签名,避免影响尚未重新验证附加组件有效性的用户。

  • 方案制定

大致的方向是,我们可以重新签名扩展,或让 Firefox 先「接受」过期扩展,然后尝试修复中间证书。没有选择第一种方案的原因有两个:

  1. AMO 存在大量扩展(超过 15000 个),签名未针对批量完成进行优化,重新签名每个扩展会耗费大量时间。
  2. 扩展被签名后用户需更新所有扩展(自动检查更新约需 24 小时),对非 AMO 安装的扩展用户需要手动更新。

相比而言第二种方案几乎不需要手动干预,且需要花费的时间更短,所以之后的修复集中在这个方向上。

针对方案二,我们推送了第二个热修复补丁,用于更改 Firefox 验证证书的日期,使现有扩展正常工作,然后用新生成的有效证书,替换原来的过期证书。

从发现问题,到推送补丁修复花了大约 9 个小时,用户保守估计会在 6 到 12 个小时内收到。为什么会花这样一段时间,首先签发新的中间证书需要时间,因为根证书位于离线储存的硬体安全模块,极大的保证了安全性,但对于签发新证书显然很困难,必须要进入 HSM (硬体安全模块)找到安全位置,做一些可能的尝试,才能签发完全正确的证书,而且每次尝试都需要花费一两个小时的测试才能确切知道尝试是否正确。其次开发系统附加组件(SAO)需要一段时间,在测试好后进行签名,由于开头所描述的签名系统被禁用了(……)这里又进行了一些其他方法。

发布后用户收到的时间是由 Normandy 研究系统完成的,这套系统是之前用于进行实验性项目完成的,用户收到 SAO 后会自动运行,由于它提供了访问 Firefox 内部 API 的许可权,这让我们有办法通过这种方式将新的证书加到 Firefox 用于验证的证书库中。

这个选项在 Firefox 隐私与安全 设置中,第一次启动时会询问用户是否开启,但也有部分用户关闭了这个选项:

Normandy 每次更新请求间隔是 6 小时,对应于 about:config 中 app.normandy.run_interval_seconds,如果没有收到更新不会重新请求,这也是为什么不是所有用户会在 6 小时内确保收到更新的原因。

SAO 修复没有解决以下几种情况:

  1. 禁用遥测或实验项目的用户
  2. Firefox for Android
  3. 部分 Linux 发行版
  4. 使用代理或部分杀软会拦截补丁推送
  5. 旧版本的 Firefox

Android 版用户在当时可通过修改 about:config 中 xpinstall.signatures.required,但修改 config 的方式一定不是官方所推荐的。其他不生效的原因例如设置了主密码等,为了解决这些问题,我们发布了 66.0.4 和 66.0.5(包括 Android 版),用户更新到最新版本可以解决上述问题。

对于旧版本和不再支持版本的用户,可分别安装以下扩展:

Disabled Add-on Fix for Firefox 61 - 65 – 下载 ?? Firefox 扩展(zh-CN)?

addons.mozilla.org
图标
Disabled Add-on Fix for Firefox 57 - 60 – 下载 ?? Firefox 扩展(zh-CN)?

addons.mozilla.org

Disabled Add-on Fix for Firefox 47 - 56 – 下载 ?? Firefox 扩展(zh-CN)?

addons.mozilla.org
图标

此事件导致的其他问题有:

  1. 被禁用的扩展数据不会受影响,但移除扩展或清理过配置文档的无法恢复。
  2. 一些 Container 扩展,例如 Firefox Container,Facebook Container 启用后数据可能无法恢复,需要重新设置(有一个相关的 Bug 会对此问题进行改进)
  3. 主题需要被激活,同理如果主页和搜索是由扩展控制,也会被重置到默认值。
  4. 使用其他论坛讨论的关于此问题的一些修复方法,虽然很有用,但部分影响了后续修复的进行。(瑕不掩瑜,我非常感激一些社区朋友帮我说了官方不能提供的解决方法,后面会在运营侧提到)

综上是关于这次问题的技术说明,我们需要一个更好的方式跟踪 Firefox 内部可能存在的问题,以确保意外不会发生,另外目前的修复方式推送至用户依然偏慢,SAO 不是一个好的修复方式,并有一些副作用产生。我们仍需要一种能够快速推送更新的方式,并且使用户保证既能接收到更新,又能选择不接受其他不需要的推送。问题发生在周末,我们期望在工作日前修复,但少部分用户仍在之后几天才收到更新。


问题发生时汇集了一份文档,包括关于此问题的更新和相关负责人,以确保用户能得到及时,正确的信息。

需要明确的点有:

  1. 事件发生的背景
  2. 用户可以从哪些渠道得知问题的最新进展
  3. 收集的一些用户反馈
  4. 后续工作

背景上文已说明,简单来说,是由于附加组件签名中间证书过期,导致现有和新扩展无法运行或安装。在用户知道发生了什么以后,支持团队需要:1)确保用户可以知晓解决方式。2)快速处理大量提问。3)了解当前进展。

问题刚刚发生时,大量用户进入各种官方的平台反馈,Bugzilla 上有非常多重复的 Bug,这些大量的反馈会使运营人员疲于应对,难以发现有价值的信息,对这种情况,相关同事修改了一些页面的置顶横幅,指向 SUMO 对应页面,Bugzilla 置顶横幅指向对应 Bug,因为 SUMO 页面是静态多语言页面,且会随著进展而更新,相比于讨论这种方式更简单粗暴。原先指向的是 Discourse 的页面,负责此问题的同事在帖子中更新进展,但由于访问量过大直接 Web 响应错误。

准备好一套快速回复机制,用于解答可能遇到的问题,并提供给所有员工和运营人员。但不能推荐一些例如需手动修改 about:config,其他渠道获得的补丁,虽然可能我了解这种修改方式也是热修复正在做的。为了避免一切可能造成的影响,当时用户最好的方式就是等待,什么都不要做。

以上策略用于控制已知问题,伴随而来的一些其他情况我们也通过用户反馈获知并整理在列表中,列表主要包含三项:1)问题详情。2)来源链接。3)解决方案,如何跟进。然后更新上面的快速回复机制。

一些做了部分,或应该做而没做的事:

  • 虽然与很多可以提供帮助回复用户的社区人员联系,但没有覆盖到所有
  • 缺少一个官方途径感谢提供帮助的这些人
  • 适当的与媒体联系,告知具体情况,以免由于信息不完全导致的误解(比如有些媒体认为证书过期是由于我们忘续费了)

感谢 百度 Firefox 吧 的各位吧主和社区,微博帮忙回复的朋友,以及了解情况后原因等待一些时间来修复的用户??


推荐阅读:
相关文章