一张AVIF图片就能接管服务器?Next.js 8月双Critical补丁背后的供应链警钟

2026年8月25日,Vercel打破了自己原定的发布计划。按照 Next.js 新确立的月度安全发布流程,这批补丁本应在 8 月 26 日上线——官方 8 月 20 日就发布了预告,给全球团队留出了一周多的升级窗口。但就在发布前一天,安全团队在上游依赖库中识别出一个新的 Critical 级漏洞,于是 16.3.3(Active LTS)和 15.5.24(Maintenance LTS)被提前一天推向 npm。

这批补丁修复了两个未授权远程代码执行(RCE)漏洞:一个藏在图片优化 API 的 AVIF 处理链路里——攻击者只需要让服务器“看一眼”一张恶意构造的图片;另一个只在 Windows 文件系统上生效,CVSS 评分高达 9.0,且官方明确表示没有任何已知的临时规避方案。两个漏洞都不需要身份验证、不需要用户交互,攻击向量直接是网络。

本文不打算复述新闻稿。我们把这次事件拆开看三层:漏洞本身的技术原理(为什么“优化一张图片”会变成“执行任意代码”)、供应链层面的传导路径(Next.js → sharp → libheif 这条链路上每一环的责任边界),以及 Next.js 团队在这次事件中做出的三个值得写进工程笔记的决策。所有事实均来自 Next.js 官方安全公告、GitHub Security Advisory 以及安全媒体报道,来源会在文中标注。

一、事件全貌:一次“提前一天”的紧急发布

先看时间线。这条线本身就是一个有意思的工程故事:

日期事件
2026-07-13Next.js 宣布正式确立月度安全发布流程(security release program)
2026-07-21首批计划内安全发布:修复 4 个 High + 5 个 Medium 漏洞
2026-08-20官方博客预告 8 月 26 日将发布包含 1 个 Critical 漏洞的补丁
2026-08-25因上游依赖 libheif 中发现新的 Critical 漏洞,提前一天发布 16.3.3 / 15.5.24
2026-08-26GitHub Advisory 公开细节,安全媒体跟进报道

两个漏洞的核心事实如下。

漏洞一:AVIF 图片优化 API 中的未授权 RCE(Critical)

  • 编号:GHSA-2xp9-vwfh-vxw4(Next.js 侧)/ GHSA-g89c-p67h-r497(libheif 侧)
  • 根因:sharp 依赖的底层 C 库 libheif 存在漏洞,当 Next.js 优化一张攻击者可控的 AVIF 图片时可触发未授权 RCE
  • CVSS v4 向量:CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H——注意后面的影响维度全是 H
  • 受影响版本:Next.js 10.0.0 至 15.5.24 之前,以及 16.3.3 之前的 16.x 版本(此范围来自 Cyber Security News 的报道)
  • 修复方式:补丁版本直接禁用 AVIF 优化,直到上游修复传播完成

漏洞二:Windows 服务器上的未授权 RCE(Critical,CVE-2026-75604)

  • 编号:CVE-2026-75604 / GHSA-p293-qw3h-jr36
  • CVSS v3.1 评分:9.0,向量 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
  • 弱点分类:CWE-22 路径遍历(Improper Limitation of a Pathname to a Restricted Directory)
  • 触发条件:应用同时具备两个特征——使用 Pages Router 或 App Router(不含 Cache Components),且服务器运行在 Windows 文件系统上;Linux 与 macOS 不受影响
  • 受影响版本:>= 13.4 且 < 15.5.24,以及 >= 16.0 且 < 16.3.3
  • 临时方案:。官方原话是“You should upgrade immediately if your server is hosted on Windows”
  • 报告者:evolutionstorm 与 B0RI

升级命令本身很简单:

# 15.5.x 系列
npm install next@15.5.24
# 16.3.x 系列
npm install next@16.3.3

但“升级”这两个字背后,有一整条值得深挖的技术链。

二、漏洞拆解(一):为什么一张图片能让服务器执行任意代码

要理解第一个漏洞,得先看 Next.js 图片优化的完整调用链。

当你写下 <Image src="..." /> 并请求一张经过优化的图片时,请求会进入 Next.js 内置的 Image Optimization API。这个 API 的底层是 sharp——Node.js 生态事实标准的原生图像处理库,而 sharp 的底层是 libvips;当图片格式是 AVIF 时,libvips 又要依赖 libheif 这个 C 库来完成 HEIF 容器解析和 AV1 解码。

也就是说,一条 HTTP 请求进来,最终会触达一连串 C/C++ 原生代码。这才是问题的核心。

图像解析库是内存安全漏洞的重灾区。 AVIF 的容器格式 HEIF 继承自 ISO Base Media File Format(MP4 的同族),结构极其复杂:box 嵌套、metadata 索引、tile 切片、色彩配置文件……解析器要在不受信任的输入上做大量指针运算和内存操作。C/C++ 语言没有内存安全保障,一个越界读写就可能被武器化为代码执行。这不是理论风险——2023 年的 libwebp CVE-2023-4863(Huffman 编码堆缓冲区溢出)就是一个先例,它当时影响了几乎所有主流浏览器的图像管线。

这次的攻击面有一个放大器:Image Optimization API 接受远程 URL 作为图片源。如果你的 next.config.js 里配置了宽松的 remotePatterns,攻击者甚至不需要向你的服务器上传任何文件——只要能让 Next.js 去拉取一个他们控制的 URL,恶意 AVIF 文件就会进入处理链路。这也是为什么该漏洞被定为“未授权”:攻击者不需要登录,不需要会话,一次构造好的请求就足够。

从架构视角看,这是典型的能力暴露问题:Next.js 把“把任意图片转成 WebP/AVIF”这个高性能能力,通过一个公开 HTTP 端点暴露了出去,而这个能力的实现依赖一长串未经内存安全验证的原生代码。每多支持一种格式,攻击面就多一个扇区。AVIF 恰好是那个最近被打开的、藏了雷的扇区。

官方的修复方式很能说明问题:不是修 libheif,而是直接禁用 AVIF 优化。公告里写得很清楚——“The patched releases disable AVIF optimization until an upstream fix is propagated”。补丁版本会拒绝把图片转成 AVIF 格式,直到上游修复到位。这是一个典型的“止损优先于功能”决策,我们第四节再展开。

三、漏洞拆解(二):路径遍历如何在 Windows 上升级为 RCE

第二个漏洞 CVE-2026-75604 同样是 Critical、同样未授权,但原理完全不同——它指向 CWE-22,路径遍历。

路径遍历本身是老朋友了:应用用外部输入拼接文件路径,但没有正确中和 ../ 这类特殊元素,导致路径逃出预期目录。放在 Web 开发语境里,这通常意味着“读到不该读的文件”,属于信息泄露级别的风险。那为什么这里能定到 9.0 的 Critical RCE?

官方公告没有披露漏洞细节(这是负责任披露的惯例,细节留给了补丁反向工程),但结合公告里的两个条件——“uses a Windows filesystem” 和 “Pages Router and App Router without Cache Components”——可以做合理推断:Next.js 服务端在处理请求时存在用请求相关数据构造文件路径的逻辑(增量缓存、静态资源解析、.next 构建产物寻址都在这个范围内),在 Windows 上,路径遍历叠加该平台的文件系统语义,让攻击者不仅可能越权读写文件,还可能把写入操作落到能影响后续代码执行的敏感位置。Windows 路径的向后兼容语义(8.3 短文件名、大小写不敏感、反斜杠分隔符、设备路径等)历来是路径处理逻辑的雷区,这类“Linux/macOS 无恙、Windows 中招”的差异化漏洞在 Node.js 生态并不罕见。

三个值得注意的工程信号:

  1. “Pages Router 和不含 Cache Components 的 App Router 都受影响”——这几乎覆盖了存量 Next.js 应用的全部形态。Cache Components 是较新的架构方向,没启用它的 App Router 应用与 Pages Router 应用暴露在同一个风险下。换句话说,这不是某个实验性功能引入的边角问题,而是主路径上的洞。
  2. CVSS 向量里攻击复杂度是 High(AC:H)。结合 9.0 的总分看,这不是“发一个请求就拿到 shell”的脚本小子级漏洞,但“复杂”不等于“不可利用”——公告发布后,细节必然会被逆向研究,PoC 出现只是时间问题。CVSS 的攻击复杂度衡量的是利用条件的苛刻程度,而不是“会不会被利用”。
  3. 没有任何 workaround。对比很多漏洞公告都会附上“暂时可以关闭某配置项规避”,这次官方直接说没有。对一个部署在 Windows 上的 Next.js 应用,唯一的止血手段就是升级。

顺带一提,这个漏洞由 evolutionstorm 与 B0RI 两位研究者报告,是通过 Vercel 在 HackerOne 上运营的 Open Source Bug Bounty 渠道进来的——这个项目的运转状况,本身就是 Next.js 今年安全投入的一个注脚。

四、三个值得写进工程笔记的决策

如果只把这次事件当新闻看,收获就止于“快升级”。但作为工程案例,Next.js 团队在这次发布中的处理方式有三处值得细品。

决策一:用功能开关当止血带,而不是等上游修复

libheif 的漏洞(GHSA-g89c-p67h-r497)在 Next.js 的下游是 libvips/sharp,在上游是 libheif 项目本身。等上游发版、等 sharp 适配、再等 Next.js 集成测试,这条链走完可能要几周。期间所有暴露 Image Optimization API 的 Next.js 应用都是活靶子。于是团队选择了一个激进但正确的方案:补丁版本直接禁用 AVIF 输出。图片还能优化,只是不再产出 AVIF 格式(退回 WebP 等替代格式)。用户损失的是一点压缩率,换来的是攻击面直接清零。这是“上游未修复时,下游如何自救”的教科书示范——前提是你的系统里每个高风险功能都预留了 kill switch。

决策二:平台级分层缓解,保护没有升级的用户

公告发布同日,Vercel 的 changelog 明确写道:托管在其平台上的应用已经受到保护,无需任何操作——因为 Vercel 在识别到 AVIF 漏洞后,直接在自己托管的 Image Optimization 服务上禁用了 AVIF 优化,“AVIF inputs are served as-is”。这是分层防御的现实演绎:框架层发补丁,托管层在入口处拦截,两层之间的时间差由平台兜底。自建机房或用其他平台的团队享受不到这层保护,这也解释了为什么同一份公告对不同部署形态的用户,紧迫程度完全不同。

决策三:预告式发布遇上紧急漏洞,提前一天而不是推迟

7 月 13 日的公告里,Next.js 解释了为什么要建立月度安全发布节奏:历史 ad-hoc 补丁没有预告、经常打乱用户的升级计划。同时他们也在公告里埋了一句关键的话——“For urgent disclosures that cannot wait, or vulnerabilities that are already being exploited in the wild, we will still publish ad-hoc patches”。8 月 25 日这次就是该条款的首次实践:原定 26 日发布,25 日在上游依赖中发现新 Critical 漏洞后,没有选择“顺延到下个月一起修”,而是提前一天带伤发布。流程是给常规问题的,不是给紧急问题当借口的——这句话值得每个维护着大规模开源项目的团队记住。

还有一层背景让这件事更有时代感:Next.js 在 7 月的公告里坦言,行业漏洞研究量正被 LLM 辅助发现工具快速推高(他们引用了 Mozilla 的例子——单次 Firefox 发布中披露的 271 个问题全部来自 Anthropic 模型的自动化挖掘),所以 Vercel 自己也在用 deepsec 等同代工具对 Next.js 做对抗性扫描。框架的安全节奏正在被工具侧的进步倒逼加速,8 月这次“预告一天后被新发现打乱”的发布,很可能只是未来常态的一个预演。

五、升级自查清单:别让补丁停在 CI 里

看完分析,动手部分给一份可以直接执行的自查清单。

第一步,确认版本是否在受影响范围

# 查看 next 实际解析到的版本(注意 workspace/monorepo 下要看最终生效值)
npm ls next
# 快速看 package.json 声明
node -p "require('./node_modules/next/package.json').version"

对照范围:>= 13.4 && < 15.5.24,或 >= 16.0 && < 16.3.3,中招即升级。如果你的版本低于 13.4,说明已经脱离所有支持窗口,该考虑的是迁移而不是打补丁。

第二步,升级并重建依赖树

npm install next@16.3.3
# 或 15.x 线
npm install next@15.5.24
# 确保 lockfile 已刷新(尤其 CI 缓存了旧 lockfile 的场景)
npm ci

第三步,Docker 用户注意:镜像里跑的还是旧版本是最常见的翻车点

补丁要落到生产镜像才算数:

# 基础镜像升级后必须完整重建,不要复用旧 layer 缓存
# docker build --no-cache -t my-app:patched .
FROM node:22-slim
COPY package*.json ./
RUN npm ci # 这里必须吃到新的 next 版本
COPY . .
RUN npm run build
CMD ["npm", "start"]

第四步,验证 AVIF 已被禁用

升级到补丁版本后,图片优化端点不再产出 AVIF:

# 请求优化后的图片,确认响应不再是 AVIF
curl -sI "https://your-app.com/_next/image?url=%2Ftest.jpg&w=640&q=75" \
  | grep -i content-type
# 补丁版本应返回 image/webp 等,而非 image/avif

如果你的业务确实强依赖 AVIF(例如 CDN 层按 content-type 做缓存策略),需要评估降级到 WebP 后的体积差异,并等上游 libheif 修复传播后关注后续 Next.js 版本恢复该能力。

第五步,日志回溯

网络安全媒体报道给出的建议是重点排查两类痕迹:一是请求 URL 中含路径遍历特征模式(../、编码后的 %2e%2e%2f 等)的记录,二是图片优化端点处理 AVIF 来源的异常请求。检查 Image Optimization API 的暴露面(remotePatterns 是否配置得过于宽松)也应当提上日程。

六、局限性

必须说明本文分析的边界。其一,CVE-2026-75604 的完整漏洞细节(具体哪段路径构造逻辑可被注入、Windows 上如何从遍历升级到代码执行)官方并未公开,本文第三节基于 CWE-22 分类、受影响路由形态与 Windows 文件系统特性做出的推断,属于合理推理而非逆向结论,待补丁 diff 被社区分析后可能修正。其二,libheif 侧漏洞的具体内存破坏原语(越界读还是写、可否稳定利用)同样未披露,CVSS v4 向量中的 AT:P(需要攻击前置条件)暗示利用存在一定门槛,实际可武器化程度尚待观察。其三,AVIF 影响版本区间(10.0.0 起)来自第三方媒体报道而非官方公告原文,引用时请以 GitHub Advisory 页面为准。其四,本文写作时补丁发布不足 48 小时,社区 PoC、实际利用态势、上游 libheif 的修复时间表都还是未知数,相关结论存在时效性。

七、结论

回头看,这次事件里有三个层面的教训。

使用者:Next.js 的月度安全公告应该进每个团队的日历。这次的预告机制已经做得足够好——提前一周告知严重级别,升级窗口敞开着,但“知道”和“打了”之间永远隔着最远的距离。尤其 Windows 部署的应用,这次没有 workaround,没有借口。

框架开发者:Next.js 的处理展示了一个成熟开源项目面对供应链漏洞的标准姿势——上游爆雷时下游快速隔离(禁用 AVIF)、平台层兜底(Vercel 托管服务拦截)、紧急情况突破既定流程(提前一天发布)。三者共同点是把用户的安全时间窗口放在流程美感之前。

整个生态:Node.js 应用对原生 C 库的依赖是深层结构性风险。你的 package.json 里只有一层 sharp,但它的传递依赖树里埋着 libheif、libvips、libwebp 这些历史包袱。LLM 辅助漏洞挖掘正在让这条链上的问题被发现得越来越快(Mozilla 单次发布 271 个自动化发现的问题就是明证),“我的依赖出问题多久我能知道、多久我能止血”这个问题,值得每个团队现在就想好答案。

相关资源:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值