基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-10-24 04:35

多运行时证书信任修补与验证清单

dev.to · AI#安全#证书#运行时
Editor brief · 编辑速览

文章称 eMudhra 八个中间证书使用极小私钥,存在证书伪造风险,并列出 Node、Bun、Python、Java 等环境的修补路径。内容还提供证书链拒绝验证方法,以及托管运行时更新滞后时的临时防护方案。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

一次 CA 私钥事故,为什么会让 Node、Bun、Python 和 Java 都需要排查?原文给出的答案是:同一台机器上的程序,可能各自信任不同的证书集合。浏览器拦住了危险证书,不代表后端请求、包管理器和云函数也已经安全。

作者围绕 eMudhra 事件整理了一份升级清单,并在 Bun、Vercel Functions 上做了连接测试。最有用的结论是:修复要落实到实际运行环境,再用明确的证书拒绝验证结果。下面的事件、版本和测试结果均按原文转述,未经独立核验,不能直接当作已确认的安全公告。

浏览器已经拦截,为什么后端还会接受

按原文描述,eMudhra 在 2025 年 4 月生成的八张中间 CA 证书,其私钥都是小于 256 的整数,其中一个就是数字 4。这不是密钥只有四个字节,而是私钥数值等于 4。

中间 CA 可以签发下级证书。攻击者猜出私钥后,就可能为任意域名伪造证书;只要客户端仍信任对应证书链,请求就可能通过验证。不过,伪造证书不等于自动截获流量,攻击者还需要处在客户端与服务端之间的网络路径上。

原文给出的处置时间线是:10 月 18 日 18:05 UTC,Chrome 根证书项目收到报告,约两小时后封禁相关中间证书,Mozilla 当晚加入 OneCRL;19 日 Apple 跟进,eMudhra 吊销全部八张证书;20 日 Microsoft 跟进,Python 打包团队发布公告;21 日 Node.js、Oracle 发布修复,OpenJDK 发布公告。原文还列出 Chrome 于 10 月 27 日完全移除 G3 根证书的计划,这在当前日期仍是未来安排。

问题卡在「吊销」和「客户端执行吊销检查」之间。原文指出,Node、Bun 和 Python 的 ssl 模块默认不检查证书吊销。服务器证书被吊销了,客户端也可能继续接受。

浏览器的拦截结果,不能替后端运行时证明安全。

作者称没有发现这些私钥被利用的证据,eMudhra 也称多数中间证书未进入生产环境。这些信息影响风险判断,但不能代替修复。

升级清单要追到 venv、容器和 CI 里面

原文列出的修复门槛如下,实际执行前应与对应项目的官方公告核对:

环境 原文给出的版本或措施
Node.js 22.23.4、24.22.1、26.12.1
Bun 1.4.4
pip 每个 venv 内升级到 26.2.2
certifi 2026.10.19
uv 0.13.4
Java Oracle 更新,或替换 blocked.certs
PHP 更新系统及 ca-certificates

Node 的修复还包含 Brotli 解码器等其他安全问题。原文称 Node 20 已结束支持,未获得此次修复。CI 也要检查:actions/setup-node 中的 node-version: 24 可能命中旧缓存,作者建议增加 check-latest: true,并在日志里打印 node --version。

Bun 的结论有作者实测支撑:1.3.13 和 1.4.3 都能连接测试站点,1.4.4 则返回 CERT_REVOKED。作者还称 Bun 忽略 SSL_CERT_FILE,所以仅替换这个环境变量指向的文件,不能证明 Bun 已修复。

Python 更容易出现「解释器检查通过,pip 仍有问题」。ssl 模块使用的证书文件取决于构建和配置,而原文称 pip 会同时加载自带的 certifi 与系统证书库,没有开关可以关闭前者。全局升级 pip,不会更新已有 venv 内的副本。

新环境也可能重新带入旧版本:python -m venv 从解释器附带的 ensurepip wheel 初始化 pip。作者建议把 pip install -U pip 设为新建环境后的第一条命令;另一种临时办法是替换 ensurepip/_bundled 中的 wheel 并修改版本字符串。原文将 Homebrew Python 列为例外,称其 pip 的 certifi 指向 Homebrew 维护的证书包。

容器同理。作者引用的情况是,截至 10 月 21 日,官方 slim Python 镜像仍包含 pip 26.2.1。因此要禁用缓存重建,并进入运行中的容器确认版本。

Java 部分,原文将问题编号写为 CVE-2026-91403,评分 9.1,受影响版本包括 Java SE 8u511、11.0.33、17.0.21、21.0.13、25.0.5、27.0.1,以及 GraalVM。Oracle 的修复在 JSSE 中取消对相关中间证书的信任;临时文件在 Java 8 中叫 blacklisted.certs,其他所述版本叫 blocked.certs。原文称 Linux 发行版的 OpenJDK 包通常读取系统证书库,但具体发行版和配置仍需确认。

PHP 同期版本是 8.5.12、8.4.27、8.3.36、8.2.35。不过作者指出,此问题更依赖 PHP OpenSSL 实际读取的系统证书库,不能只盯 PHP 版本。

云函数没升级时,应用能补上哪一层

作者在 10 月 21、22、23 日分别部署 Vercel Functions 测试函数,三次报告的都是 Node v24.21.0,并成功连接测试站点,返回 CONNECTED 200。这能说明作者当时测试的部署环境存在缺口,不能外推为所有区域、所有项目的统一状态。

原文利用 Node 24 的 tls.getCACertificates() 和 tls.setDefaultCACertificates(),在冷启动时移除指定根证书:

import * as tls from 'node:tls';
import { X509Certificate } from 'node:crypto';

const DISTRUSTED = ['emSign ECC Root CA - G3', 'AAA Certificate Services'];

export function dropEmudhraRoots(): number {
  const all = tls.getCACertificates('default');
  const keep = all.filter((pem) => {
    const cn = new X509Certificate(pem).subject
      .split('\n')
      .find((line) => line.startsWith('CN='));
    return !DISTRUSTED.some((name) => cn === `CN=${name}`);
  });
  if (keep.length !== all.length) tls.setDefaultCACertificates(keep);
  return all.length - keep.length;
}

关键是调用 tls.setDefaultCACertificates(keep) 的那一行,它修改当前进程的默认信任集合。作者在 Next.js 的 instrumentation.ts 中通过 register() 调用该函数,记录移除数量;旧环境移除一个根证书后,测试请求变为 UNABLE_TO_GET_ISSUER_CERT_LOCALLY。

数组中的 AAA Certificate Services 是原文所述交叉签名链涉及的 Sectigo 根证书。作者称 Node 内置库没有它,这一项只是预防。作者还测试了 Stripe、Shopify、Anthropic 和 Vercel Blob,连接均正常,但这不是完整的业务兼容性验证。

修复最终要看连接行为。下面这组命令分别测试 curl、Node、Bun 和 Python:

curl https://dv-g3b-emudhra.we-have-a-problem.com   # 安全结果为 error (60)

node -e "fetch('https://dv-g3b-emudhra.we-have-a-problem.com').then(() => console.log('EXPOSED'), (e) => console.log('rejected:', e.cause?.code ?? e.message))"

bun -e "fetch('https://dv-g3b-emudhra.we-have-a-problem.com').then(() => console.log('EXPOSED'), (e) => console.log('rejected:', e.code ?? e.message))"

python3 -c "import urllib.request as u; u.urlopen('https://dv-g3b-emudhra.we-have-a-problem.com'); print('EXPOSED')"

要看的是错误原因:DNS 失败和超时都不能算通过,curl 的错误也需要确认来自证书验证。测试站点的证书链是否仍符合预期,同样是这个探针成立的前提。

我的判断

我认同作者把检查单位从「机器」细化到「实际发请求的程序」。前端团队的 Node 构建任务、Next.js 服务端和部署平台,很可能运行着不同版本;Python 工具又可能藏在独立 venv 中。检查宿主机一次,覆盖不了这些环境。

但原文没有提供可核验的公告链接、完整实验环境或对照数据。尤其是版本门槛、Node 20 生命周期、pip 的证书加载行为,以及发行版 OpenJDK 的处理方式,都不应仅凭这篇文章直接进入生产变更单。uv 0.13.4 只出现在清单里,原文没有解释其修复机制或测试结果。

应用内删根证书可以作为临时措施,但会改变该进程的信任范围,也未必覆盖自行传入 CA 的客户端。它比等待平台升级多了一种应急选择,同时也比直接升级运行时承担更多维护责任。

行为探针比单看版本更接近真实结果,但一次探针不能覆盖所有 TLS 调用路径。

作者提到每天及包管理器升级后运行检查脚本,还扫描磁盘上的 certifi 包。这是有价值的维护经验,不过原文没有提供脚本,不能把描述当成可复现交付。

能拿来做什么

  • 给 Node、Bun、Python 和 Java 各列出实际使用位置,至少覆盖本地、CI、容器和云函数;先确认是否使用,再对照官方公告决定修复范围。
  • 在 CI 与部署诊断日志中输出真实运行时版本,并保留证书拒绝原因,避免只凭配置文件中的版本声明判断结果。
  • 使用 Python 工具的团队应逐个检查 venv 中的 pip 和 certifi,并把升级步骤加入环境初始化流程,防止新环境重新带入旧证书包。
  • 若托管平台暂未更新,可评估原文的进程内删根方案,在初始化阶段执行、回归关键外部接口,并在平台完成修复后移除临时代码。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Agent 评估要查执行过程与重复成功率
下一篇
给 Claude Code 接入免密钥网页搜索

资讯速览

dev.to · AI · 2026-10-24 04:35

AI 评分 8.0 / 10

相关标签

#安全#证书#运行时

继续阅读

  • 用配置文件创建Claude Code审查助手
  • Agent 评估要查执行过程与重复成功率
  • 给 Claude Code 接入免密钥网页搜索
  • 从本地会话追踪 Claude Code 用量去向
  • 生产运维 Agent 如何按修复计划授权