在上线前预防漏洞

ZDNET AI··作者 David Gewirtz

关键信息

文章强调了设计阶段要重点考虑信任边界、身份、授权、数据暴露、日志和故障模式等安全问题。它还强调依赖卫生,以降低隐藏的供应链暴露风险,这与包白名单、完整性校验和受控依赖管理的做法一致。

资讯摘要

文章把软件看作一个完整的生命周期,从最初的想法开始,直到编码、测试、部署、用户使用以及最终退役。它的核心观点是,安全应该尽早内建,因为一旦缺陷进入代码和生产系统,修复成本会更高,也更困难。文中使用 secure-at-the-source 和 secure-by-design 这两个术语,来描述一种从需求和设计阶段就把安全与可靠性纳入其中的方法。文章认为,与其只问事后如何更快地发现和修复问题,不如更早地问:风险是从哪里进入开发流程的,以及如何在前期把它们消除。

文章强调,预防应当发生在写代码之前的设计阶段,因为架构选择本身就可能制造或减少漏洞。它特别指出,信任边界、身份、授权、数据暴露、日志和故障模式等方面,如果设计不当,都可能形成安全缺口。文章还建议进行威胁建模,例如询问谁会使用系统、系统会接触哪些数据、会信任哪些服务、攻击者可能做什么,以及某个组件被攻破时会发生什么。最后,文章把这种预防性思路延伸到依赖卫生,提醒团队谨慎选择和管理依赖,以便在生产前避免隐藏的供应链风险。

在上线前预防漏洞

资讯正文

ZDNET 的要点:

安全的软件必须从编码之前就开始构建。

威胁建模有助于团队及早发现有风险的假设。

依赖卫生可以防止隐藏的供应链风险。

软件有其生命周期。从一个想法的火花,到编码、测试、部署、客户使用,再到最终修订或退役,每一行代码、每个模块和每个组件都会越来越嵌入、越来越固化为整体解决方案的一部分,因此一旦后来出现问题,就更难修复。然而,我们往往只在软件进入后期使用阶段后才去修补它。本文将讨论在部署前主动防止缺陷进入生产环境的策略。

这种方法有两个关键术语:secure-at-the-source 和 secure-by-design。这两个术语都指在软件生命周期最早阶段就将安全性和可靠性构建进代码的过程。我们将重点讨论如何在所有阶段中都把安全性设计进去,从需求和设计开始,到编码、依赖项选择、构建流水线、部署以及维护。另请参阅:最佳零信任安全平台:利用快速、安全的访问控制保护你的网络边界。

这种方法要求在整个生命周期中完成思维转变。过去我们可能会问:“我们能多快找到并修复出错的地方?”这仍然是一个有效的问题。但我们现在要更早地提出另一个问题:“风险是从哪里进入我们的开发流程的,我们又能在设计、工具、模板、依赖项和评审中做出哪些改变,让更少的风险首先进入代码?”

防范应从写代码之前开始

编码总是从对期望结果的设想开始。这个过程会引发设计阶段,设计人员和开发者(有时是同一个人或同一批人)会一起确定如何开展编码过程。正是在这里,在写下第一行代码之前,漏洞就开始显现。

另请参阅:什么是杀毒软件,到 2026 年你还需要它吗?

之所以会出现这种情况,是因为设计决策会影响实现。在推进设计时,请仔细考虑以下因素:

信任边界:用户、服务、网络或系统之间边界定义不清,可能意味着某个被攻破的区域会影响到本应隔离的应用部分。

身份:如果系统无法可靠地知道是谁或什么在发起请求,那么所有下游安全决策都会变得可疑。

授权:如果架构不能始终一致地强制执行每个用户或服务被允许做什么,攻击者可能获得本不该拥有的操作或数据访问权限。

数据暴露:如果敏感数据流经过多系统、日志、API 或客户端组件,就更容易泄露或被滥用。

日志记录:如果日志缺失、过多或设计不当,团队可能要么错过攻击,要么无意中把敏感信息存到不该放的地方。

故障模式:如果系统在数据处于开放状态时失败、在错误期间泄露细节,或在压力下表现不可预测,那么宕机和攻击就可能演变成安全事件。

我们都听过这句话:“还能出什么问题呢?”

这句话通常是在有人提出某个大胆而可能并不明智的计划之后说的。但如果你把这句话反过来,认真地问一问“究竟会出什么问题?”你就可以开始对你的软件做威胁建模了。在确定设计之前,你还可以问:谁会使用这个系统?它会接触哪些数据?它会信任哪些服务?攻击者可能会尝试哪些恶意行为?如果某一部分失败或被攻陷,会发生什么?

在设计之初就提前思考这些问题,把威胁和安全问题放在首位,有助于你尽早发现有风险的假设,而此时设计仍然具有灵活性。这样,你的团队就能在这些选择变成昂贵的代码、生产依赖项或面向客户的漏洞之前,做出更安全的决定。在开始编码之前,先想清楚“足够安全”意味着什么。提前规划安全考虑,意味着从一开始就把身份验证、授权、加密、可审计性、数据保留、滥用场景以及恢复行为纳入设计之中。

CISA(Cybersecurity and Infrastructure Security Agency)是美国主要的网络防御机构。CISA 正在推动一种 Secure by Design 策略,即由供应商在技术产品的设计和制造过程中就将网络安全融入其中。根据 CISA 的说法,“按照 Secure by Design 原则设计的产品,会将客户安全作为核心业务要求,而不只是把它当作一项技术功能。”如果你对这种方法感兴趣——而且你真的应该感兴趣——我建议你阅读 CISA 关于这一策略的详细文件。

防护延伸到了开发者工作流内部。我还记得几十年前,编辑器演变成交互式开发环境(IDE)并真正成为助手的那一天。那项功能就是符号调试器,它让你能够追踪代码流程、检查变量并设置断点。IDE 立刻提升了我的代码质量,因为我可以持续监控每个变量,看到哪些内容在变化、又是什么时候发生变化的。从那以后,IDE 一直在持续改进。某个阶段,开发者加入了在你编写代码时监控代码的功能,在你输入时就标出错误。对非程序员来说,这项功能就像文字处理软件里的拼写检查器在单词下方显示那些波浪线一样,只不过它检查的是整段代码。

尽管围绕 vibe coding 的炒作不断,人工仍然会继续写代码。也许不会是全部代码,也许也不会是所有程序员,但仍然会有经验丰富的开发者逐行创建代码。对于这些开发者来说,源码即安全意味着 IDE 应该能够像标记语法问题一样,标记安全问题,而且要在代码编写过程中就完成。

开发者工作流中其他从源头确保安全的补充措施还包括:在合并前对 pull request 进行检查、在仓库中发出依赖项警报、在机密信息变成事故之前进行检测、在 CI/CD 流水线中进行自动化测试、在选择库时提供更安全的包使用指导、将发现的问题与实际工作关联起来的问题跟踪,以及防止高风险更改在未被注意的情况下进入生产环境的部署检查。就在今年,Amazon(按理说最应该知道这样做有多不妥的一家公司)推送了一次代码变更,导致客户无法结账、浏览商品以及访问自己的账户。尽管我们中的一些人可能更希望这种事情更常发生一点,好让我们不必把所有钱都送给 Bezos,但事实是,哪怕只是一次部署错误,也让 Amazon 损失了数百万美元。这次昂贵的失误表明,如果不能在发布之前捕获错误和漏洞,会付出多么高的代价。在部署流程的某个环节,Amazon 没有使用预防性安全措施。它的防护机制(假设它有的话)没有发挥作用。作为开发过程的一部分,程序员和编程团队可以通过从既有的安全编码模式入手来帮助保护自己的产出。使用已批准的框架、可复用的身份验证和授权库、安全默认设置、安全模板以及平台服务,可以为代码提供一个标准化基础,让开发者不必为每个模块都去选择实现模式。此外:AI 在 2026 年可能造成前所未有破坏的 10 种方式。美国国家标准与技术研究院(NIST)是美国商务部下属的一个不具监管职能的联邦机构,它提出了一个“降低软件漏洞风险”的框架。NIST SP 800-218 提议了一套软件开发生命周期最佳实践,可减少漏洞。其中一些做法包括:准备组织:定义角色、标准、培训和安全工作流程。定义安全要求:在开发前明确安全预期。使用安全默认设置:减少开发者必须手动做出的高风险选择。保护开发环境:保护工具、代码仓库、流水线和凭据。审查源代码:尽早发现设计和实现层面的弱点。测试可执行代码:使用动态测试、模糊测试和运行时检查。保护软件完整性:验证制品、来源和发布真实性。分析漏洞:理解根本原因,而不仅仅是单个 bug。NIST 指南还建议跟踪、评估并更新依赖项。我们接下来会深入讨论这一点。管理供应链风险 在过去几年里,我们都非常熟悉当供应链中断时会发生什么。比如,我们都记得 2020 年那场“大厕纸短缺”。供应链是一个用来描述某种东西如何从原材料开始,经过制造、运输,最终到达分销和消费环节的术语。软件开发也有供应链,只不过我们使用的术语是“依赖项”。没有人会在某个产品或服务中把所有代码都独自写完。

相反,大多数事情都是由其他公司或开源开发者编写的软件构件搭建起来的。而这些构件本身,往往又由其他构件组成,形成了几乎包揽幕后所有工作的模块。另请参阅:AI 正在悄悄“毒害”自己并把模型推向崩溃——但有办法解决

问题在于,这些构件以开源库、容器、API、构建工具、SaaS 组件以及 AI 生成代码的形式存在,都会在最终方案中引入漏洞和缺陷。有时,恶意行为者会向开源工具提交修改,而核心开发者未能发现。另一些时候,简单的编码错误也会导致漏洞。关键在于,对大多数开发者来说,这些依赖项就是黑盒。更糟的是,它们还在不断变化。随着更新推出,这些更新也会被纳入生产软件中。这一步意味着,原本完全安全的依赖项,可能会在后续更新中被攻破。换个角度想:虽然你的代码也可能存在漏洞,但只要它并未被广泛使用,威胁者可能还需要一段时间才能发现这些漏洞。而这些依赖项呢?它们的漏洞往往早已广为人知,而且常常在非法市场上被兜售。让你的软件变得脆弱,最简单的方法就是依赖脆弱的软件。另请参阅:在 AI 时代,企业绝不能犯错的 5 种安全策略——以及它们为何至关重要

所有这些交互都意味着,必须强力推进依赖项治理。在集成和审批流程中,务必选择能够被验证、确实有人维护的软件包,锁定已知版本,审查传递性依赖,监控已知漏洞,并避免使用维护薄弱、所有权变更可疑或安全信号不佳的库。如果这意味着要替换依赖项或选择不同的供应商,那么其收益远远超过供应链切换成本。

减少事后应对型安全

应对安全事件或软件故障糟透了。刚喝下第一口咖啡两口,你就会因为一封邮件或一条通知而感觉脉搏飙升,因为它描述了一切如何刚刚彻底失控。若这种事发生在半夜,那就更糟。设计并交付以安全为目标的软件,可以减少这种压力波动。这种做法还能降低组织的总体责任风险、减少负面报道,并增强客户信心。在发布前实施设计变更,无疑会比生产环境事故、客户通知、紧急修补程序或补偿性控制措施的临时替代方案更便宜,也更不痛苦。

这种转变是一种文化变革。源头即安全(secure-at-the-source)把开发质量作为设计和编码中的核心实践。安全必须成为软件编写方式的一部分。不要等到所有代码都写完、构建完成之后,才发现哪些地方需要重写和重新构建。更不要等到,万一可能的话,等到愤怒的客户冲着你大吼大叫的时候——问我怎么知道的——因为他们依赖的某些东西糟糕地崩溃了。你的胃酸(或者没有胃酸)会感谢你的。

你的开发人员会欢迎在日常工作流程中加入安全护栏,还是会把它们视为又一层阻力?欢迎在下方评论区告诉我们。你可以在社交媒体上关注我每天的项目更新。也请订阅我的每周更新通讯,并在 Twitter/X 上关注 @DavidGewirtz,在 Facebook 上关注 Facebook.com/DavidGewirtz,在 Instagram 上关注 Instagram.com/DavidGewirtz,在 Bluesky 上关注 @DavidGewirtz.com,并在 YouTube 上关注 YouTube.com/DavidGewirtzTV。

来源与参考

  1. 原始链接
  2. Stopping bugs before they ship: The shift to preventative security

收录于 2026-05-12