跨越冥河:Spring Boot 3.5 与“僵尸依赖”危机
当依赖项变成“僵尸” Spring Boot 3.5:下一次跨越
明天我将(很早地)出发前往科隆参加 JCON Europe,随后在周末前往 Devoxx France 发表更多演讲。如果你也在现场,欢迎来打个招呼。HeroDevs 在两场活动中都设有展位。
在深入研究了 Tomcat 8.5 停止维护 (EOL) 背后的 CVE 故事之后,我将注意力转向了 Spring Boot 3.5。同样的问题,不同的框架:当一个项目跨过 EOL(生命周期结束)这条线时,你的安全态势实际上会发生什么?
CVE 的盲点
我们大多数人都理解 CVE 的“概念”。漏洞被发现、报告、分配严重性评分并修补。我们运行扫描器,检查仪表板,更新依赖项。系统运作良好。
但事实并非如此。在“生命周期结束”之后,情况就变了。
我们似乎对 CVE 的来源存在集体盲点。我们关注的是产出:公告、补丁、扫描器警报。我们很少思考这个过程,或者那些从事这项工作的人。谁发现了漏洞?谁报告了漏洞?谁分配了 CVE 标识符?
更关键的是:当一个项目达到生命周期结束时,这个流程会发生什么?
答案是:它会枯竭。不是一下子,甚至不是剧烈地。它只是……停止了。
冥河
将从活跃开发和维护模式转变为 EOL 模式,想象成跨越冥河(River Styx)。在“生者”的一侧,有维护者积极查看代码,安全研究人员提交报告,CNA(CVE 编号授权机构)分配标识符,以及一个尽管有缺陷但至少还能运作的披露流程。
而在另一侧?是死一般的寂静。
漏洞并不会消失。代码不会因为没人维护就神奇地变得安全。停止的是“报告”过程。研究人员会将注意力转移到受支持的版本上。维护者会停止对旧分支的问题进行分类。到达 CNA 的报告变少了,对于一个没人会去修补的代码库,分配的标识符也变少了。
身处活跃一侧的人们知道下游存在问题。他们可以在死代码中看到漏洞模式。但他们不会以任何易于发现的方式告诉任何人。他们没有义务这样做,也没有相应的机制。他们不报告问题,因为他们根本没打算修复它。
这就是长期以来的模式。
事实上,任何问题能被修复都令人惊叹。我当然不是指责任何人,认为过去的做法是错误的。我始终感谢那些开发并分享其成果的人们。开源是令人惊叹的,如果没有它,开发者的生活将不可同日而语。
规则变了,习惯没变
然而,世界已经改变,开源正被武器化来对付我们。面对无情的恶意行为者大军,我们旧有的确定性正被破坏、稀释和损害。过去我们可以接受 EOL 意味着“稳定”且“没什么好看的”,但现在情况已不再如此。
维护者的肌肉记忆告诉他们,不报告针对 EOL 分支的 CVE 是正确的做法(因为他们没打算修复它)。这种肌肉记忆现在反而对我们不利。
而那些恶意行为者呢?他们注视着一切……
他们观察在受维护版本上报告的 CVE,挑选出有利可图的,然后在较旧的 EOL 版本上进行尝试。
于是:一个维护者在概念上已知晓、但并未出现在任何 CVE 数据库中的漏洞被利用了。这对恶意行为者来说是一次“免费搭车”。
现实中的表现
一个漏洞同时存在于受支持版本和 EOL 分支中。在受支持的一侧,研究人员发现它,报告它,获得 CVE 编号,并发布补丁。
而在 EOL 的一侧?同样的漏洞存在于同样的代码中。但此时关注的研究人员更少了,提交的报告也更少了。漏洞不会出现在你的扫描结果中。不是因为它不存在,而是因为没人去填那份文书。
当依赖项变成“僵尸”
很快,针对 EOL 项目的公开 CVE 数量就会下降。如果你足够幸运,那是因为确实没有漏洞了。代码库处于我们传统意义上的“稳定”状态。但更可能的情况是,软件并没有变得更安全。发生的一切仅仅是记录问题的系统停止了运作。
据我所知,没有人对这种效应进行过严谨的研究。但如果你去问任何从事开源安全支持的人,这正是他们每次都能看到的模式。这正是像我所在的公司这类机构存在的核心原因。
你的依赖项最终会处于两种状态之一:确实稳定,或者更常见的——僵尸化。失去了支持,积累着隐藏的 CVE。在技术上存在于你的栈中,但在安全层面功能上已死。它们正在缓慢恶化,而你的扫描器却给你亮起了绿灯。
我们需要停止认为“沉默”意味着“稳定”。事实往往恰恰相反。
Spring Boot 3.5:下一次跨越
Spring Boot 3.5 将于 2026 年 6 月 30 日结束开源支持。距离现在大约还有 80 天。
当它跨过那条线时,它不会孤单。Spring Framework 6.2、Spring Security 以及整个 Spring 产品组合都将同时失去社区补丁。保护大量 Java 应用的 CVE 报告渠道将开始为这些版本停摆。
我们以前看过这部电影
Spring Boot 2.7 于 2023 年 11 月停止维护。自那时起,该分支已经出现了多个 CVE。例如 CVE-2024-38807:引导加载程序中的签名欺骗漏洞。没有可用的开源补丁。仍在使用 2.7 的团队必须自己修复,支付商业支持费用,或者承担风险。
2.7 进入 EOL 的时间越长,CVE 的流出就越安静。并不是更安全,只是更安静了。也许你已经能听到那拖着脚步的声音……
基于这种模式,Spring Boot 3.5 几乎不可能不遵循同样的轨迹。从稳定到僵尸的转变不是“是否会发生”的问题,而是当维护者将重心转移到 4.0 后,报告流程会以多快的速度枯竭的问题。
窗口期依然开放,但仅限当下
但关键在于:这不会在一夜之间发生。我们还有时间。向“僵尸”状态的过渡是渐进的,而这个窗口期至关重要。
你越快评估从 3.5 到 4.0 的迁移规模,你的处境就越主动。也许这意味着按照自己的节奏进行迁移;也许意味着安排商业支持来填补空白,或者完全寻找另一条路径。最糟糕的做法是等到沉默降临时,还天真地以为一切安好。
地图,不仅仅是风景
这就是现状。现在让我们谈谈地图。
在我最近的 JDK 8 到 25 迁移回顾中,我梳理了 Java 十七年发布历程中的每一个重大变化。我规划了团队在最终实现现代化时实际面临的问题。我将对 Spring Boot 3.5 到 4.0 做同样的事情。
在接下来的文章中,我将按严重程度梳理技术挑战。包括明显的编译错误、运行时故障以及可能逃过测试套件的隐藏行为变化。我将分析成本,探索替代方案,并拆解一个现实的迁移时间表是什么样的。
向“僵尸”的转变即将波及 Spring Boot 3.5。唯一的问题是,你是会做好准备,还是会被它突袭。如果你本周(4 月 13 日至 15 日)参加 Spring I/O Barcelona,欢迎来 HeroDevs 展位找我。我很乐意交流迁移过程中的“战争故事”。
Steve Poole 是 Java Champion、Oracle ACE 和 IBM Champion。同时也是 HeroDevs 的开发者倡导者,以及 No Regressions 通讯的作者。欢迎在 JCON 或 Devoxx France 的 HeroDevs 展位找到他。