为什么软件膨胀仍然是最大的漏洞 (2024) - 呼吁精简软件
IEEE.org IEEE Xplore Digital Library IEEE Standards More Sites Sign In Join IEEE
Why Bloat Is Still Software’s Biggest Vulnerability
Share FOR THE TECHNOLOGY INSIDER
Topics
Aerospace AI Biomedical Climate Tech Computing Consumer Electronics Energy History of Technology Robotics Semiconductors Telecommunications Transportation
Sections
Features News Opinion Careers DIY Engineering Resources
More
Newsletters Special Reports Collections Explainers Top Programming Languages Robots Guide ↗ IEEE Job Site ↗
For IEEE Members
Current Issue Magazine Archive The Institute The Institute Archive
IEEE Spectrum
About Us Contact Us Reprints & Permissions ↗ [Advertising ↗](https://spectrum.ieee.org/<https:/advertise.ieee.org/ >)
Follow IEEE Spectrum
Support IEEE Spectrum
IEEE Spectrum is the flagship publication of the IEEE — the world’s largest professional organization devoted to engineering and applied sciences. Our articles, podcasts, and infographics inform our readers about developments in technology, engineering, and science. Join IEEE Subscribe About IEEE Contact & Support Accessibility Nondiscrimination Policy Terms IEEE Privacy Policy Cookie Preferences Ad Privacy Options © Copyright 2025 IEEE — All rights reserved. A public charity, IEEE is the world's largest technical professional organization dedicated to advancing technology for the benefit of humanity.
Why Bloat Is Still Software’s Biggest Vulnerability
A 2024 plea for lean software
Bert Hubert 08 Feb 2024 10 min read
本文献给计算先驱 Niklaus Wirth 的纪念,他于 2024 年 1 月 1 日去世。1995 年,他撰写了一篇有影响力的文章,名为《A Plea for Lean Software》,发表在 IEEE Computer Society 的会员杂志 Computer 上,在我作为企业家和软件开发人员的早期职业生涯中读过。在接下来的内容中,我试图在近 30 年后提出同样的论点,并针对当今的计算恐怖进行更新。本文的一个版本最初发表在我的个人博客 Berthub.eu 上。
几年前,我在当地一所大学做了一个关于网络安全的演讲,题为“Cyber and Information Security: Have We All Gone Mad?”。今天仍然值得一读,因为我们_已经_集体发疯了。
如今,我们构建和交付软件的方式大多是荒谬的,导致应用程序使用数百万行代码来打开车库门,以及其他简单的程序导入1,600 个外部代码库——依赖项——来源不明。软件安全情况严峻,这既是代码质量的问题,也是代码数量的问题。我们许多程序员都知道目前的情况是站不住脚的。可悲的是,许多程序员(及其管理层)从未经历过其他任何事情。对于我们其余的人来说,我们很少有时间做得更好。
这不仅仅是你;我们不仅仅是怀旧:今天的软件确实非常奇怪。
让我简要地回顾一下软件安全的可怕状态,然后花一些时间讨论为什么会如此糟糕。我还提到了一些监管和立法方面的事情,我们可以利用这些事情使软件质量再次成为优先事项。最后,我谈谈我编写的一个实际有用的软件,作为可以仍然创建最小和简单但又现代的软件的概念验证。
我希望这篇文章能为想要改进现状的受苦的程序员和技术人员提供一些精神和道义上的支持。这不仅仅是你;我们不仅仅是怀旧:今天的软件确实非常奇怪。
软件安全的可怕状态
在没有全部“老家伙 (48) 对着云大喊大叫”的情况下,让我重申一些显而易见的事情。软件安全的状态是_可怕的_。如果我们只看过去的一年,如果你运行了像Ivanti、MOVEit、Outlook、Confluence、Barracuda Email Security Gateway、Citrix NetScaler ADC, and NetScaler Gateway等行业标准软件,那么你很可能已经被黑客入侵了。即使是拥有近乎无限资源的公司(如 Apple 和 Google)也犯了微不足道的“最差实践”安全错误,使他们的客户处于危险之中。然而,我们仍然依赖所有这些产品。
软件现在(理所当然地)被认为是非常危险的,以至于我们告诉每个人不要自己运行它。
软件现在(理所当然地)被认为是非常危险的,以至于我们告诉每个人不要自己运行它。相反,你应该将它留给“X 即服务”提供商,或者仅仅留给“云”。将此与假设的情况进行比较,在这种情况下,汽车非常容易着火,以至于建议不要自己驾驶汽车,而是将其留给始终伴随专业消防员的专业人员。
然后,假设云能够以某种方式使不安全的软件值得信赖。然而,在过去的一年中,我们了解到微软的电子邮件平台遭到了彻底的黑客攻击,包括机密的政府电子邮件。(两次!)也有对 Azure 云安全性的合理担忧。与此同时,行业宠儿 Okta 提供基于云的软件,使用户能够登录到各种应用程序,遭到了全面的控制。这是他们在两年内的第二次违规行为。此外,随后还出现了一系列可疑的 Okta 用户遭到黑客攻击的事件。
显然,我们需要更好的软件。
欧盟为此颁布了三项立法:针对重要服务的 NIS2;针对几乎所有商业软件和电子设备的 Cyber Resilience Act;以及扩展到软件的修订后的 Product Liability Directive。立法总是很困难,并且他们是否做对了还有待观察。但是,如今软件安全性如此糟糕,以至于需要立法似乎是显而易见的。
为什么软件安全性如此糟糕
我想谈谈激励机制。今天的情况显然对商业运营商有利。制作更安全的软件需要时间和大量工作,并且当前的安全事件似乎并未影响利润或股价。你可以通过偷工减料来加快上市时间。因此,从经济角度来看,我们所看到的一切都是完全可以预测的。立法对于改变这种等式可能非常重要。
软件的安全性取决于两个因素——源代码中安全问题的_密度_以及黑客可以访问的_代码量_。正如美国国防界在 20 世纪 80 年代喜欢指出的那样,数量本身就具有质量。反过来适用于软件——你拥有的越多,你面临的风险就越大。
例如,由于 iMessage 暴露的巨大攻击面,Apple iPhone 用户多年来屡次遭到黑客攻击。可以将未经请求的 iMessage 发送给 Apple 用户。然后,手机会立即处理该消息,以便可以预览它。问题在于,Apple 凭借其智慧决定,此类未经请求的消息需要支持各种图像格式,意外地包括具有使用古代格式的奇怪嵌入式压缩字体的 PDF,该格式有效地包含了一种编程语言。因此,有人可以将未经请求的消息发送到你的 iPhone,该消息可以探测手机其余部分的弱点。
通过这种方式,攻击者能够从手机数百万行代码中的安全漏洞中获益。你不需要很高的错误密度就能在数百万行代码中找到一个可利用的漏洞。
擦除代码中的所有错误并不能让你免受实施自动执行嵌入在文档中的代码的功能的决定的影响。
Apple 可以通过将预览限制为更小的图像格式范围,甚至限制为单个“已知良好”图像格式来防止这种情况。Apple 可以通过简单地向攻击者暴露更少的代码行来避免大量痛苦。顺便说一句,欧盟的 Cyber Resilience Act 明确告诉供应商要最大限度地减少攻击面。
Apple(迄今为止)不是该领域中最严重的违规者。但它是一家备受尊敬且资源充足的公司,通常会认真考虑他们所做的事情。甚至他们也犯了错误,因为他们不必要地发布和暴露了太多代码。
我们不能编写更好的代码吗?
有些人认为最大的问题是代码的质量,以其中的错误密度来表示。在这方面正在发生许多有趣的事情,例如使用 Rust 等内存安全语言。其他语言也提高了它们的安全性。Fuzzer——自动修改计算机程序输入以查找弱点和错误的测试工具——也变得越来越先进。
但是许多安全问题都存在于代码的底层逻辑中。例如,Barracuda 电子邮件漏洞源自第三方库,该库实际上会在扫描 病毒 时执行 Excel 电子表格中的代码。擦除代码中的所有错误并不能让你免受实施自动执行嵌入在文档中的代码的功能的决定的影响。
软件交付的状态
另一个问题是,我们通常不知道我们实际交付的是什么代码。软件变得_巨大_。1995 年,Niklaus Wirth 哀叹软件的规模已增长到兆字节。在他的文章“A Plea for Lean Software”中,他继续描述了他的 Oberon 操作系统,该操作系统仅有 200 KB,包括编辑器和编译器。现在有些项目仅配置文件的体积就超过 200 KB。
如今,一个典型的应用程序构建在 Electron JS 上,这是一个包含 Chromium (“Chrome”) 和 Node.JS 的框架,它提供了对数万个 JavaScript 软件程序包的访问权限。我估计,如果包括依赖项,仅使用 Electron JS 就至少需要 5000 万行代码。也许更多。与此同时,该应用程序可能会提取数百或数千个帮助程序包。许多使用的程序包默认也会向广告商和其他数据经纪人泄露你的用户的信息。依赖项提取进一步的依赖项,并且包含在构建中的内容每天都在变化,没有人真正知道。
如果此应用程序控制你家中的任何物品,它还将连接到 Amazon 上的软件堆栈,可能也由 Node.js 提供支持,也提取许多依赖项。
我们可能正在查看超过 5000 万行活动代码,以打开车库门......
但等等,还有更多。我们过去将软件作为编译器的输出或作为要解释的一堆文件来交付。然后,必须_安装_和_配置_此类软件才能正常工作。让你的代码打包以像这样交付需要大量工作。但这是一项很好的工作,因为它迫使人们思考他们的“程序包”中包含的内容。然后,此软件包将基于配置与操作系统和本地服务集成。
由于该软件在与开发该软件的计算机不同的计算机上运行,因此人们必须真正知道他们交付的内容并仔细考虑。有时它不起作用,导致开发人员告诉运维人员:“嗯,它在我的系统上运行”,以及反驳说“然后备份你的电子邮件,我们将你的笔记本电脑投入生产!”这个笑话。
这过去是一个笑话,但现在我们通常将软件作为容器交付,不仅交付软件本身,还包括操作系统文件,以确保该软件在已知的环境中运行。这通常需要有效地交付完整的计算机磁盘映像。这再次大大增加了部署的代码量。请注意,你可以使用 Docker 等容器来做好事(见下文),但 Docker Hub 上有很多超过 350 MB 的镜像。
总而言之,我们可能正在查看超过 5000 万行活动代码,以打开车库门,在多台服务器上运行多个操作系统映像。
现在,即使所有包含的依赖项都是黄金的,我们是否确定他们的安全更新是否已到达你的车库门开启器应用程序?我想知道有多少 Electron 应用程序仍在交付去年让 Google 和 Apple 争先恐后发布更新的图像处理错误。我们甚至不知道。
但更糟糕的是,众所周知,所有这些依赖项_都不是_黄金的。Node.js 生态系统具有滑稽的历史,程序包存储库被接管、劫持或由其他人以相同的名称复活,有些人对你的安全怀有恶意计划。PyPI(Python 的 Node.js 对应项)遭受了类似的问题。依赖项始终需要仔细检查,但不能合理地期望任何人经常检查数千个依赖项。但我们宁愿不考虑这一点。(请注意,你也不应过度并毫无必要地重新实现所有内容,以防止依赖项。有一些非常好的模块可能比你自己的输入更安全。)
世界交付的代码太多,我们甚至不知道我们交付了什么,并且我们对我们_确实_知道我们交付了什么的内容不够努力(或者根本不)查看。
你_可以_今天编写精简的代码
写作被称为你发现你不知道你在说什么的过程。与此同时,实际上做事是你发现你也不知道你在写什么的过程。
在对 Wirth 的 Oberon 项目进行小型重演中,我也编写了一些代码来证明一个观点,并让我自己放心,我仍然知道我在说和写什么。你还能以旧方式制作有用且现代的软件吗?我决定尝试创建一个简约但功能齐全的图像共享解决方案,我可以信任它。
Trifecta 就是结果。它是实际的独立软件,可让你使用浏览器拖放图像以轻松共享。多年来,我不得不为此目的使用 imgur,这让我很痛苦。imgur 不仅会在我的浏览器中安装大量 cookie 和跟踪器,而且我还会将这些跟踪器强加给查看我共享的图像的人。如果你想自托管这样的 Web 服务,你也不想被黑客入侵。我发现的大多数你可以自己运行的图像共享解决方案都基于我不太信任的巨大框架,原因如上所述。
所以,为了说明一个观点,我决定创建一个简约但有用的图像共享解决方案,我可以信任它。更重要的是,其他人也可以信任它,因为你可以在几个小时内查看所有 Trifecta 的代码。它包含 1,600 行新的源代码,以及大约五个重要的依赖项。
你最终会得到总共 3 兆字节的代码。
相比之下,另一个图像共享解决方案以 288 MB 的 Docker 镜像交付,尽管诚然它看起来更好并且具有更多功能。但不是价值 285 MB 的。另一个比较是这个基于 Node 的图片共享解决方案,它记录在案,有 1,600 个依赖项,显然总共有超过 400 万行 JavaScript。
世界交付的代码太多,其中大部分来自第三方,有时是无意的,其中大部分未经检查。
请注意,Trifecta 并非旨在作为随机人员可以共享图像的公共站点,因为这往往不会有好结果。但是,它非常适合公司或个人使用。你可以在此处阅读有关该项目的更多信息,并且还有一个页面介绍用于交付如此小的独立解决方案的技术。
对 Trifecta 的回应
这非常有趣。到目前为止,对 Trifecta 最常见的响应是我应该使用一大堆 Amazon Web Services 来部署它。对于一个明确声明的目标是提供不依赖外部服务的独立软件的项目来说,这是一个极其奇怪的反应。我不确定这里发生了什么。
另一种反应是我对 Docker 的处理不公平,并且你绝对可以出于好的目的使用容器。我完全同意。但我也看看人们实际上在做什么(也包括其他形式的容器或虚拟机),并且它不是那么好。
我想用 Niklaus Wirth 1995 年论文中的一些观察结果来结束这篇文章:
“对于某些人来说,复杂性等于力量。(…) 越来越多地,人们似乎将复杂性误解为成熟,这令人费解——无法理解的东西应该引起怀疑而不是钦佩。”
我同样观察到有些人更喜欢复杂的系统。正如 Tony Hoare 早在很久以前就指出的那样,“软件设计中有两种方法。一种是使程序变得非常简单,显然没有错误。另一种是使其变得非常复杂,以至于没有明显的错误。”如果你无法执行第一种变体,那么第二种方法可能看起来非常有吸引力。
回到 Wirth:
“时间压力可能是臃肿软件出现的最主要原因。设计师承受的时间压力会阻碍仔细的规划。它还会阻止改进可接受的解决方案;相反,它会鼓励快速构思的软件添加和更正。时间压力会逐渐腐蚀工程师的质量和完美标准。它对人以及产品都有不利的影响。”
当你可以交付整个预先安装的操作系统映像(该映像可以正常工作)时,为什么要花费数周的时间来缩减软件的规模?
“软件爆炸的瘟疫不是‘自然法则’。它是可以避免的,而软件工程师的任务是遏制它。”
如果这确实是软件人员的责任,那么我们或许应该要求更多的时间来完成它。
世界交付的代码太多,其中大部分来自第三方,有时是无意的,其中大部分未经检查。因此,存在一个由平庸代码组成的巨大的_攻击面_。目前正在努力提高代码本身的质量,但是许多漏洞是由于逻辑故障造成的,并且在扫描这些漏洞方面进展甚微。与此同时,通过缩减我们向世界公开的代码量,可以取得巨大的进步。这将增加产品的上市时间,但是立法即将到来,应该迫使供应商更加认真地对待安全性。
Trifecta 就像上面提到的 Wirth 的 Oberon 项目一样,旨在证明即使代码和依赖项数量有限,你也可以交付很多功能。通过努力和立法,也许未来可能会再次带来低于 5000 万行的车库门开启器。让我们努力实现它。