结论:清单做不全,后面的漏洞评估就没有基础
现代软件产品中,自己写的代码往往只占一小部分,大量功能来自第三方组件——操作系统、运行库、框架、驱动、工具库。
这些组件带来两个问题:一是它们可能有已知漏洞,二是它们的维护状态不由你控制。
软件物料清单的作用是把「产品里到底有什么」说清楚。 清单做不全,就无法判断某个新披露的漏洞是否影响自己的产品——因为你不知道产品里有没有那个组件。
这是所有后续工作的基础。 漏洞监测、影响评估、更新决策,都建立在清单之上。
清单的内容
一份可用的组件清单应当包含:
| 字段 | 说明 |
|---|---|
| 组件名称 | 明确的标识 |
| 版本 | 精确到具体版本号 |
| 供应方 | 组件的提供者 |
| 许可证 | 使用条款 |
| 依赖关系 | 直接还是间接依赖 |
| 使用范围 | 用到了哪些功能 |
| 引入方式 | 源码、二进制、还是服务 |
| 维护状态 | 是否仍在维护 |
「版本精确到具体版本号」很重要。 写「某库 2.x」是不够的,因为漏洞通常影响特定的版本区间。版本不精确,漏洞影响就判断不了。
「使用范围」有实际价值。 一个大型库可能只用到其中很小一部分功能,如果新漏洞出现在未使用的功能中,影响评估的结论会不同。
间接依赖的处理
直接依赖。 你主动引入的组件。
间接依赖。 直接依赖所依赖的组件,以及更深层的依赖。
实际情况是:间接依赖的数量通常远大于直接依赖。 引入几十个直接依赖,展开后的依赖树可能有几百个组件。
而漏洞可能出现在依赖树的任何一层。 所以清单必须覆盖完整的依赖树,只列直接依赖是不够的。
建议用工具生成依赖树,手工维护很难做全,也容易在版本更新后失效。
清单的生成与维护
构建时生成。 在构建过程中自动生成清单,保证与实际构建产物一致。
版本绑定。 每个发布版本对应一份清单。
变更记录。 组件增删和版本变更要有记录。
格式的选择。 用通用的格式便于工具处理和对外提供。
存档。 已发布版本的清单要长期保存,因为产品在市场上的生命周期可能很长。
「构建时自动生成」比事后人工整理可靠得多,因为人工整理容易遗漏,而且每次发布都要重做。
漏洞监测的做法
有了清单,监测的做法是:
建立监测机制。 订阅漏洞信息源,或使用自动化工具。
定期比对。 把新披露的漏洞与清单比对,找出可能受影响的组件。
影响评估。 受影响的组件是否在产品中被实际使用、使用的是否是受影响的功能、产品的使用场景是否会触发该漏洞。
风险判定。 结合产品的使用环境判断实际风险。
处理决策。 更新组件、增加缓解措施、还是判定不受影响。
记录。 每个漏洞的评估结论和处理要有记录。
「不受影响」的判定也要记录。 判定某个漏洞不影响产品,理由要写下来——将来被问到时能说清楚。
更新决策的考虑
发现受影响的组件后,更新与否要权衡:
漏洞的严重程度。 以及在本产品场景下的实际可利用性。
更新的影响。 组件更新可能带来兼容性问题,需要回归验证。
验证的工作量。 按软件安全性级别确定的回归范围。
发布的可行性。 产品是否有安全的更新通道、用户是否会更新。
替代的缓解措施。 如果暂时不能更新,能否通过配置或架构调整降低风险。
「用户是否会更新」是实际问题。 发布了更新但用户不装,风险依然存在。所以更新机制的易用性和更新的通知方式都要考虑。
组件退役的处理
组件停止维护是必然会遇到的情况:
提前识别。 关注组件的维护状态,不要等到完全停止维护才发现。
评估影响。 停止维护意味着新漏洞不会被修复。
替代方案。 寻找替代组件或自行维护。
迁移计划。 替换组件需要开发和验证工作,要提前安排。
风险接受。 如果短期内无法替换,要有风险评估和缓解措施。
建议在清单中标注每个组件的维护状态和预期的支持期限,这样能提前看到哪些组件需要规划替换。
与产品支持期限的关系
产品的安全支持期限受组件支持期限制约:
组件停止维护后,基于它的产品也难以持续提供安全更新。
所以产品的支持期限承诺要考虑组件的情况。
建议在产品资料中明确安全支持期限,让用户能够规划。
对于长生命周期的医疗器械,组件选择时就要考虑维护期限——选择维护期长、社区活跃的组件,比选择功能更强但维护不确定的组件更稳妥。
提交时的组织
作为证据提交时,建议包含:
完整的组件清单;清单的生成方法说明;漏洞监测机制的说明;已识别漏洞的评估记录;以及更新策略和支持期限承诺。
「监测机制的说明」是审查关注的点 ——不只看当前有没有漏洞,还看你有没有持续发现和响应的能力。
许可证方面的考虑
清单中的许可证信息不只是法务问题,也关系到产品的可持续性:
使用条款的限制。 某些许可证对商业使用、分发、修改有条件。
传染性条款。 某些许可证要求衍生作品采用相同许可,这可能影响自有代码。
归属声明的义务。 需要在产品中标注组件信息。
专利条款。 部分许可证涉及专利授权。
许可证变更的风险。 组件的许可证可能在新版本中改变。
建议在引入组件时就审查许可证,而不是产品做完再审。发现许可证不兼容时更换组件,比产品上市后处理要容易得多。
我们的做法
承接含软件产品的委托时,如果涉及网络安全相关的验证,我们会要求提供组件清单。没有清单,漏洞扫描的覆盖面就无法确认 ——扫描出来的结果是全的还是漏了一半,说不清楚。
对于清单中标注的第三方组件,我们会在验证中关注它们引入的接口和通道,因为这些是威胁建模中容易被遗漏的入口点。
如果你在准备软件相关的资料,不确定组件清单怎么做、要覆盖到什么程度,可以把软件架构发过来一起讨论,或者直接联系:132 4819 8029。能力范围见服务介绍,送检要求见送检要求,流程见检测流程。
English version
Conclusion. In modern software products, code written in-house often accounts for a small share of the whole, with most functionality coming from third-party components: operating systems, runtimes, frameworks, drivers and utility libraries. These bring two problems: they may carry known vulnerabilities, and their maintenance status lies outside your control. A software bill of materials states what is actually in the product. Without a complete one, you cannot judge whether a newly disclosed vulnerability affects your product, because you do not know whether the component is present. That list is the foundation for everything after: vulnerability monitoring, impact assessment and update decisions all rest on it.
Contents of the list. A usable component list should carry the component name as a definite identifier; the version, precise to a specific version number; the supplier; the licence and its terms; the dependency relationship, whether direct or indirect; the scope of use, meaning which functions are exercised; how it was incorporated, whether as source, binary or service; and its maintenance status. Precise versions matter: writing a library as version 2.x is insufficient, because vulnerabilities generally affect particular version ranges and imprecise versions leave impact unjudgeable. Scope of use carries practical value: a large library may contribute only a small part of its functionality, and a new vulnerability in an unused function leads to a different impact conclusion.
Indirect dependencies. Direct dependencies are components you deliberately incorporated. Indirect dependencies are what those depend on, and what those in turn depend on. In practice the number of indirect dependencies far exceeds the direct ones: a few dozen direct dependencies can expand into a tree of several hundred components. Vulnerabilities can appear at any level of that tree, so the list must cover it completely and listing direct dependencies alone is insufficient. Generate the dependency tree with tooling: manual maintenance rarely achieves completeness and falls out of date as versions change.
Generating and maintaining the list. Generate at build time, automatically, so that the list matches the actual build artefact. Bind to versions, with one list per released version. Record changes, covering additions, removals and version changes. Choose a common format, for tooling compatibility and external provision. And archive lists for released versions long-term, since a product's market life may be lengthy. Automatic generation at build time is far more reliable than compiling by hand afterwards, which is prone to omission and must be redone at every release.
Vulnerability monitoring. With a list in place, establish a monitoring mechanism by subscribing to vulnerability sources or using automated tooling. Compare periodically, matching newly disclosed vulnerabilities against the list to find potentially affected components. Assess impact, considering whether the affected component is actually used in the product, whether the affected functionality is exercised, and whether the product's use scenario would trigger the vulnerability. Judge the real risk in the product's operating environment. Decide on handling, whether updating the component, adding mitigations or concluding no impact. And record the assessment and decision for each vulnerability. Record conclusions of no impact as well, with the reasons written down, so that the judgement can be explained if questioned later.
Update decisions. Having found an affected component, weigh the severity of the vulnerability and its practical exploitability in your product's context; the effect of updating, since component updates can introduce compatibility problems requiring regression verification; the verification workload, determined by the regression scope your software safety class requires; the feasibility of release, meaning whether the product has a secure update channel and whether users will apply updates; and alternative mitigations, where configuration or architectural adjustment can reduce risk if updating is not immediately possible. Whether users apply updates is a practical matter: a released update that nobody installs leaves the risk in place, so ease of updating and how users are notified both need consideration.
Component retirement. Components ceasing maintenance is inevitable. Identify it early by tracking maintenance status rather than discovering it once support has ended. Assess the implications, since no maintenance means new vulnerabilities will not be fixed. Find alternatives, whether a replacement component or taking on maintenance yourself. Plan the migration, since replacement requires development and verification and needs scheduling in advance. And accept residual risk where replacement is not possible in the short term, with an assessment and mitigations. Annotate the list with each component's maintenance status and expected support horizon, so that components needing replacement become visible early.
Relationship to product support periods. A product's security support period is constrained by its components': once a component ceases maintenance, a product built on it struggles to continue providing security updates. Support period commitments must therefore reflect component circumstances. State the security support period in the product documentation so that users can plan. And for long-lifecycle medical devices, consider maintenance horizons when selecting components: a component with a long support horizon and an active community is safer than one with more capability but uncertain maintenance.
Organising it for submission. As evidence, include the complete component list; a description of how it is generated; a description of the vulnerability monitoring mechanism; assessment records for identified vulnerabilities; and the update strategy and support period commitment. The monitoring mechanism is what reviewers attend to: the question is not only whether vulnerabilities exist now but whether you have the capability to find and respond to them continuously.
How we handle it. For products involving cybersecurity verification we ask for the component list. Without it, the coverage of vulnerability scanning cannot be confirmed, and whether the results are complete or miss half of the product cannot be established. For third-party components in the list we attend during verification to the interfaces and channels they introduce, since those are the entry points most often omitted from threat modelling.
Send us the software architecture and we will work through the component list and its coverage. Phone or WeChat: +86 132 4819 8029.