☰
Erlang/OTP 漏洞披露与 OpenVEX 声明解析:从 CVE 追踪到第三方 vendored 依赖审计
2026/9/25 5:09:10 网站建设 项目流程
  • 编程语言
  • 语言运行时
  • 标准库
  • 编译器
  • 并发编程

【免费下载链接】otp

Erlang/OTP

项目地址:https://gitcode.com/gh_mirrors/ot/otp
点击查看免费下载

Erlang/OTP 使用 OpenVEX 规范统一披露自身与第三方依赖的漏洞信息,将"哪个 CVE 影响哪个 OTP 版本、哪个 OTP 应用"以机器可读的结构化声明发布出来,供安全扫描器与开发者直接消费。本文以仓库中的官方文档 vulnerabilities.md 为主线,结合当前仓库(OTP_VERSION 标记为 30.0-rc0)的源码实证,完整讲解 VEX 声明的获取方式、双重版本标识、vendored 第三方依赖的审计边界,以及如何据此制定升级策略。

为什么 Erlang/OTP 需要一套漏洞披露规范

Erlang/OTP 并不是一个单体二进制,而是由erts、kernel、stdlib、ssl、ssh、crypto等数十个应用组成的发行版,同时运行时还内嵌(vendor)了 pcre2、zlib、zstd 等一批第三方 C/C++ 库。这带来两个安全追踪难题:

  1. 一个 CVE 到底影响哪些 OTP 版本?同一漏洞可能只存在于某个 OTP release 的某个应用版本中,且应用版本可以独立于 release 单独升级;
  2. 第三方库的 CVE 是否波及 Erlang/OTP?内嵌的第三方源码副本与构建时链接的系统库是两回事,不能混为一谈。

为此,Erlang/OTP 采用OpenVEX 规范来回答这些问题。OpenVEX 的核心产物是结构化的"声明"(statement):每个声明描述一个漏洞(如CVE-2025-48038)、受影响/已修复/不受影响的软件产品集合(如pkg:github/erlang/otp@OTP-28.0),以及对应的状态(affected/fixed/not_affected)。这种统一格式让 CVE 与具体版本之间的对应关系可以被工具自动解析,而不是散落在各条公告邮件里。

获取 VEX 声明:发布位置与文件命名

Erlang/OTP 为当前仍受维护的 OTP release持续发布 OpenVEX 声明,统一存放在官方下载站的download/vex/目录下。文件名遵循固定模式:

otp-<release>.openvex.json

其中<release>对应 OTP 版本号,例如otp-28.openvex.json。每个受维护的 release 拥有一个独立文件,安全团队可以直接把对应版本号的 JSON 文件接入扫描流水线,无需人工解析公告。

Erlang/OTP 第一方 CVE 声明:为何采用双重版本标识

release 与应用版本双维度寻址

由于 OTP 应用(如ssh)可以独立于整个 release 发布补丁版本,单一维度无法精确表达影响范围。因此 OpenVEX 声明中的products同时使用两类 purl(Package URL)标识:

  • release 级:pkg:github/erlang/otp@OTP-28.0,指向整个 OTP 发行版;
  • 应用级:pkg:otp/ssh@5.3,指向某个 OTP 应用(pkg:otp命名空间下的应用名@应用版本)。

这种双维度设计正是为了应对"单独升级某个应用即可修复漏洞,而不必等待整个 release 升级"的现实场景。

affected 声明示例

下面是从otp-28.openvex.json中截取的实际声明(以CVE-2025-48038为例),完整保留原始字段:

{ "vulnerability": { "name": "CVE-2025-48038" }, "timestamp": "2025-09-16T08:22:13.223967395Z", "products": [ { "@id": "pkg:github/erlang/otp@OTP-28.0" }, { "@id": "pkg:github/erlang/otp@OTP-28.0.1" }, { "@id": "pkg:github/erlang/otp@OTP-28.0.2" }, { "@id": "pkg:otp/ssh@5.3" }, { "@id": "pkg:otp/ssh@5.3.1" }, { "@id": "pkg:otp/ssh@5.3.2" } ], "status": "affected", "action_statement": "Update to any of the following versions: pkg:otp/ssh@5.3.3", "action_statement_timestamp": "2025-09-16T08:22:13.223967395Z" }

逐字段解读:

  • vulnerability.name:漏洞标识,即 CVE 编号;
  • timestamp:声明的发布时间(RFC 3339 格式 UTC);
  • products:受影响的完整版本清单,同时列出 release(OTP-28.0、28.0.1、28.0.2)与应用(ssh@5.3、5.3.1、5.3.2);
  • status:affected表示这些版本确实存在该漏洞;
  • action_statement:可选字段,给出规避或修复动作,这里明确指引升级到ssh@5.3.3;
  • action_statement_timestamp:该动作建议的时间戳。

fixed 声明示例

同一份文档中会为同一 CVE 再生成一条fixed声明,指向首个不再受该漏洞影响的版本。继续以CVE-2025-48038为例:

{ "vulnerability": { "name": "CVE-2025-48038" }, "timestamp": "2025-09-16T08:22:13.241103494Z", "products": [ { "@id": "pkg:github/erlang/otp@OTP-28.0.4" }, { "@id": "pkg:github/erlang/otp@OTP-28.0.3" }, { "@id": "pkg:otp/ssh@5.3.3" } ], "status": "fixed" }

可见修复落在OTP-28.0.3(以及包含该修复的28.0.4)与ssh@5.3.3上。对使用者而言,最直接的判断依据就是应用级版本:只要ssh升级到5.3.3及以上即不再受影响,无需关心整个 release 是否升级。

第三方依赖的 VEX 声明:vendored 代码的审计边界

vendoring 与范围界定

Erlang/OTP 以vendor方式将部分第三方库的源码副本直接纳入发行版(例如仓库中 erts/emulator/pcre、erts/emulator/zlib、erts/emulator/zstd 等目录)。因此第三方 VEX 声明覆盖任何作为源码包含在 Erlang/OTP release 中、且确实易受攻击的代码。

文档同时划出了一条重要边界:

构建过程中动态或静态链接的库不在此声明范围内。例如任何涉及安全的 Erlang 应用都会依赖构建时动态/静态链接的 OpenSSL cryptolib 版本。

换言之,OpenVEX 声明只对 Erlang/OTP内置的源码副本负责,绝不代表"链接了系统 OpenSSL 的自有部署"也安全。

为什么用 commit SHA1 标识版本

与第一方声明使用语义化版本号不同,第三方声明以上游仓库的 commit SHA1标识受影响/已修复的版本。原因在于这些依赖是 C/C++ 代码,业界漏洞扫描器(如 OSV)惯于按 SHA1 提交区间报告漏洞范围,语义化 tag 无法精确到代码快照。

not_affected 声明示例

以 OpenSSL 为例,Erlang/OTP 对CVE-2023-6129发布如下声明:

{ "vulnerability": { "name": "CVE-2023-6129" }, "timestamp": "2025-06-18T12:18:16.47247833+02:00", "products": [ { "@id": "pkg:github/openssl/openssl@01d5e2318405362b4de5e670c90d9b40a351d053" } ], "status": "not_affected", "justification": "vulnerable_code_not_present" }

解读要点:

  • products中的pkg:github/openssl/openssl@01d5e2318405362b4de5e670c90d9b40a351d053表示 Erlang/OTP 内置的 OpenSSL 代码取自上游仓库该 commit(文档注明对应 OpenSSL 3.1.4)的源码副本;
  • status为not_affected,justification为vulnerable_code_not_present,即声明该 commit 的源码中不存在此漏洞对应的易受攻击代码;
  • 该声明针对的是Erlang/OTP 内包含的这份源码。文档明确提醒:如果你自己构建 Erlang/OTP 并在构建过程中链接任意版本的 OpenSSL(如 3.5.2 甚至同为 3.1.4),你的项目就产生了新的构建与运行依赖,完全可能受CVE-2023-6129影响——内置副本的not_affected保护不了外部链接。

注:上述 OpenSSL 示例来自 vulnerabilities.md 原文,其中给出的内置路径为lib/erl_interface/src/openssl/与erts/emulator/openssl/。从当前仓库(30.0-rc0)的源码结构看,erts/emulator下实际保留的 vendored 目录为 pcre、zlib、zstd、ryu、asmjit 等,示例旨在说明声明机制而非当前版本的目录清单。

仓库实证:vendored 依赖清单与 vendor.info

当前仓库用vendor.info文件精确记录每个内嵌第三方库的版本、来源与 commit SHA,这正是第三方 VEX 声明得以生成的基础。以下均可在仓库中直接核对:

库版本信息记录文件
pcre210.47,shaf454e231fe5006dd7ff8f4693fd2b8eb94333429vendor.info
zlib1.3.2,shada607da739fa6047df13e66a2af6b8bec7c2a498vendor.info
zstdv1.5.7,shaf8745da6ff1ad1e7bab384bd1f9d742439278e99vendor.info
ryu(含 STL to_chars)sha4c0618b0e44f7ef027ebae05d2cc7812048f7c8f/37d575ede5ade50ad95b857f22ed7f1be4b1f2dfvendor.info
asmjitsha5fe1940275d04432da841896bac0a66cc2375551vendor.info

以 pcre2 为例,vendor.info 记录了downloadLocation(上游仓库)、versionInfo(10.47)、sha(上游 commit)、purl(pkg:github/PCRE2Project/pcre2)等字段,并标注"annotation": "Vendor package modified in Erlang/OTP",说明这不是一次无改动的拷贝。

更新流程如何沉淀 SHA

第三方库升级时,SHA 与版本号由仓库中的更新脚本自动写入vendor.info。以 erts/emulator/zstd/update.sh 为例,脚本会:

  1. 通过 GitHub API 获取上游最新 release tag(VSN);
  2. git clone对应 tag 的源码,并执行git rev-parse --verify HEAD记录 commit SHA;
  3. 将lib/{common,compress,decompress}等目录复制进erts/emulator/zstd,并把公开头文件重命名为erl_zstd.h等以避免与系统头文件冲突(对应代码见 erl_zstd.h);
  4. 用 jq 改写vendor.info的versionInfo与sha字段。

这套"版本 + SHA + purl"的记录机制,与 OpenVEX 第三方声明按 commit SHA1 寻址的做法完全对齐——扫描器拿到vendor.info中的 SHA,就能与 VEX 声明中的products精确匹配。

vendored 代码不是简单拷贝:以 PCRE2 为例

值得强调的是,Erlang/OTP 对 vendored 库往往有深度定制。仓库中的 erts/emulator/pcre/README.pcre_update.md 详细记录了 PCRE2 集成的三处关键改造:

  1. 可中断/可重启的正则匹配:修改pcre2_match主执行循环,把递归所需的局部变量改为堆上分配的"栈帧"结构(PcreExecContext),配合COST_CHK、COST宏与LOOP_COUNT注释实现 reduction 计数与 trap,使超长正则匹配不会阻塞 Erlang 调度器;
  2. 符号隐藏:以-fvisibility=hidden编译全部 PCRE2 文件,避免与 NIF/driver 链接的真实 PCRE2 库产生符号冲突;
  3. 功能裁剪:移除 UTF16、JIT、DFA 执行等无关功能,仅保留 VM 所需部分。

这种深度耦合意味着:第三方库的上游 CVE 是否影响 Erlang/OTP,不能仅凭"版本号是否在影响区间"判断,必须结合 Erlang/OTP 对源码的具体裁剪与修补——这正是 OpenVEX 声明中not_affected/justification存在的意义,也解释了为何第三方声明必须针对"Erlang/OTP 内置的那份源码"逐一断言。

Windows 二进制文件

按 vulnerabilities.md 的说明,目前 Erlang/OTP 的 Windows 二进制文件不纳入 OpenVEX 规范的报告范围。也就是说,Windows 二进制形态的产物暂时没有对应的机器可读 VEX 声明。对于 Windows 部署,可以推断更稳妥的做法是:结合对应 OTP 版本号的otp-<release>.openvex.json源码级声明、官方发行说明以及 Windows 构建方式的差异(例如第三方库的链接方式)来综合评估,而不要假设"源码声明可直接平移给 Windows 二进制"。

安全团队与开发者的落地建议

综合文档与仓库实现,可将 VEX 机制用于以下实战场景:

  1. 接入扫描流水线:按otp-<release>.openvex.json模式拉取当前所用 OTP 版本对应的声明文件,解析status(affected/fixed/not_affected)与justification,自动生成漏洞清单;
  2. 按应用版本制定升级计划:第一方声明同时给出 release 与应用两个维度,优先把受影响应用(如ssh)升级到声明中fixed指向的应用版本(如ssh@5.3.3),即可在不等整个 release 的前提下消除漏洞;
  3. 警惕not_affected的边界:该状态只对 Erlang/OTP 内置的第三方源码副本成立。凡是自建构建并链接外部库(尤其是 OpenSSL)的场景,都必须把外部链接版本单独纳入自己的漏洞管理,不能引用 Erlang/OTP 的声明充当"安全背书";
  4. 核对 vendored 清单:以仓库中各 vendor.info 记录的sha/versionInfo/purl为基准,与扫描器(如 OSV)的 SHA1 区间报告交叉匹配,快速确认某个第三方 CVE 是否落入内置副本的范围;
  5. 延伸审计资料:仓库还提供 SBOM.md 等软件物料清单相关文档,可与 VEX 声明配合,形成完整的"依赖清单 + 漏洞声明"审计闭环。

小结

Erlang/OTP 的漏洞披露体系以 OpenVEX 为统一载体:第一方声明用pkg:github/erlang/otp@OTP-x.y与pkg:otp/<app>@<ver>双重寻址,覆盖"应用可独立升级"的实际场景;第三方声明以 commit SHA1 定位内置源码副本,并严格限定于 vendored 代码,明确排除构建期动态/静态链接的库。理解这两套声明的语义边界,是准确评估自身 Erlang/OTP 部署安全状态、快速制定修复动作的前提。当前仓库中 vulnerabilities.md 为官方权威说明,各 vendor.info 文件为可逐条核对的实证依据,建议安全与运维团队将二者一并纳入日常审计。

  • 编程语言
  • 语言运行时
  • 标准库
  • 编译器
  • 并发编程

【免费下载链接】otp

Erlang/OTP

项目地址:https://gitcode.com/gh_mirrors/ot/otp
点击查看免费下载
上一篇:终极指南:llm-attacks如何塑造AI安全研究的未来趋势与核心挑战
下一篇:推荐文章:BCFtools - 高效的变异调用与VCF/BCF文件处理工具

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询