Next.js 安全漏洞排查:2026 年 5 月 13 项公告,真正危险的是 RSC 缓存投毒

Next.js 在 2026 年 5 月集中披露 13 项安全公告。本文结合 Vercel、Cloudflare 与 App Router 实际部署,梳理 SSRF、middleware 绕过和 RSC 缓存投毒的真实影响,给出 16.2.6 / 15.5.18 升级顺序、边缘缓存清理步骤与上线后的回归测试清单。

Saturday, September 5, 2026Omid Saffari
Next.js 安全漏洞排查:2026 年 5 月 13 项公告,真正危险的是 RSC 缓存投毒

Threads 上那张刷屏的 Next.js 安全漏洞截图,说的是 CVE-2026-44578:一个能触达云元数据端点的 WebSocket SSRF。在我的技术栈里,这条攻击路径根本走不通,也不值得为它恐慌。真正可能污染读者看到的每一个页面的,反而是那个几乎没人截图讨论的中危漏洞。

一句话看懂局面:该如何排查 Next.js 安全漏洞

Next.js 于 2026 年 5 月 6 日协调披露了 13 项安全公告,并在 5 月 7 日发布修复版本 16.2.6 和 15.5.18。媒体的焦点几乎都落在 WebSocket SSRF 漏洞 CVE-2026-44578 上,因为它的攻击画面足够抓眼球:攻击者升级连接后,服务器会一路访问 169.254.169.254,再由元数据端点返回 IAM 凭证。确实惊险。

但它只影响自托管部署。在前接 Cloudflare 的 Vercel 托管环境中,这条路径不可达。真正能波及我的读者的,是那个没人热议的中危 RSC 缓存投毒漏洞:遭到污染的 RSC 响应不会只停留在攻击者那一次请求里,而会进入共享边缘缓存,并持续分发给所有访客,直到我清除对应的 tag。

只要运行的是 Next.js >= 13.4.13,本周就应该升级。真正需要决定的只有三件事:升到哪个版本、按什么顺序操作,以及升级后必须重新测试什么。 下面这套排查矩阵来自我在 omidsaffari.com 上的实际操作——App Router 部署在 Vercel,前面接 Cloudflare,通过 Cache-Tag 清缓存,并使用 revalidate webhook。跑完这套流程后,我的优先级彻底离开了那条最吸睛的 CVE。

非技术创始人需要知道什么

如果产品基于 Next.js,这件事必须本周处理,不能丢进 backlog。这里真正要算的不是延迟或工程师工时,而是遭到污染的缓存页面或绕过鉴权的后台路由会直接变成客户信任危机。营销页面一旦被截图显示攻击者内容,或有人报告无需 session 就能进入 /admin,接下来一周就只能忙着解释,而不是卖产品。

只问工程团队一个问题:“我们现在是否已经升级到 16.2.6 或 15.5.18,并且在部署后清除了边缘缓存?” 如果回答比这更含糊——“正在修”“还在处理”“SSRF 不影响我们”——就说明事情还没有完成。自托管部署(ECS、EC2、Kubernetes,以及任何在自有服务器上运行 next start 的环境)风险更高,因为除了其他漏洞,它们还暴露在 SSRF 面前。再问清楚自己的系统属于哪一种,答案应该十秒内就能给出。

13 项 Next.js 安全漏洞,哪些真的会影响你的部署?

近期流传的“13 个 CVE,立即打补丁”文章都有同一个问题:把整张清单当成了同一等级的平面列表。事实并非如此。每项公告都有触发前提——自托管、Turbopack、Cache Components、CSP nonce 或 i18n。真正的暴露面,只是与你的部署条件相匹配的那部分。下面仍是这 13 项,只是改按触发条件归类。

Middleware 与代理绕过漏洞组(5 项,多数为高危)。其中影响最大的是 GHSA-267c-6grr-h53f:App Router 的 segment-prefetch URL 可以绕过 middleware 鉴权。这个漏洞组还包括 5 月 7 日发布的未完全修复后续公告 GHSA-26hh-7cqf-hhc6,它会影响 Turbopack;另外还有 Pages Router i18n 默认 locale 路径绕过,以及动态路由参数注入绕过。触发前提:使用 Next.js middleware 执行鉴权或 rewrite——几乎所有应用都符合。

SSRF,CVE-2026-44578。自托管服务器中的 WebSocket upgrade handler 可以访问 80 端口上的内部 HTTP 端点,包括云元数据服务。受影响范围:13.4.13+ 至 <15.5.16,以及 16.0.0–<16.2.5,仅限自托管部署。已确认 Vercel 托管部署不受影响。

拒绝服务(DoS),共 2 项。一项是上游 RSC DoS;另一项是已启用 Cache Components 的应用可能遭遇连接耗尽型 DoS(高危,GHSA-q4gf-8mx6-v5v3)。第二项的触发前提是明确启用了 Cache Components,而绝大多数应用并没有。

RSC 缓存投毒(中危)。RSC payload 流程中的 cache-busting 碰撞,允许精心构造的请求污染缓存响应。触发前提:在任意下游位置缓存了 RSC 响应,包括 CDN、反向代理、Vercel edge 或 Cloudflare。这正是我的技术栈最需要关注的一项。

XSS,共 2 项。一项是 CVE-2026-44581(中危),影响生成 CSP nonce 的 App Router 应用;另一项出现在消费不可信输入的 beforeInteractive 脚本中。触发前提分别是:使用带 nonce 的 CSP,或把用户输入传入 beforeInteractive script tag。

把部署满足的所有前提逐项记下来,那才是你的真实漏洞清单。对 omidsaffari.com 而言,结果是:middleware 绕过漏洞组(是)、SSRF(否,托管于 Vercel)、RSC DoS(是,上游漏洞)、Cache Components DoS(否,未启用)、RSC 缓存投毒(是,而且影响会被放大)、CSP nonce XSS(是)、beforeInteractive XSS(否)。8 项高危或中危公告最终只剩 5 项与我有关,而实际爆炸半径最大的一项并不是最出名的那个漏洞。

为什么刷屏的 SSRF 未必影响你,RSC 缓存投毒却可能影响每个页面?

CVE-2026-44578 必须由 Node 侧的 next start 服务器处理 WebSocket upgrade 并跟随重定向,攻击才能成立。Vercel 并不会以这种方式把我的请求送进该服务器,因此 SSRF 路径不可达:平台会终止 WebSocket,而元数据端点又位于 IMDSv2 之后,其 hop limit 也撑不过这条路径。前面再加一层 Cloudflare,并不会改变结论。在 Vercel + Cloudflare 的拓扑下,那张惊险的攻击截图无法复现。

RSC 缓存投毒则完全相反。漏洞位于所有请求都会经过的处理路径中,后果是 RSC payload 被污染——也就是读者最终接收的序列化 React 树。在我的站点上,这份 payload 不会只留在攻击者自己的请求中,而会进入这里:

Http
Cache-Control: public, s-maxage=300, stale-while-revalidate=86400
Cache-Tag: article:nextjs-may-2026-security-triage

s-maxage=300 表示 Cloudflare 会保存该响应五分钟;stale-while-revalidate=86400 表示它过期后仍可继续提供一天,同时在后台重新验证。Cache-Tag 是我的清理机制:每次发布新修订时,revalidate webhook 会触发 tag purge,让该对象从缓存中消失。

沿着一次缓存投毒的过程看就很清楚。攻击者访问一条可利用 cache-busting 碰撞的路由;Cloudflare 发现响应可以缓存,便按该 URL 的 cache key 保存,并标记为 article:<slug>。此后访问这个 slug 的每一位用户,拿到的都是边缘节点里的受污染 RSC payload——不经过源站,也不会再走 middleware,更不会经过我十分钟后才补上的任何 WAF 规则。污染对象已经落在下游,会一直存在到 s-maxage 窗口结束,或发布流水线执行 purge。对于已经分布到 300 个 PoP 的响应,源站 WAF 毫无作用。

因此,真正面临风险的是已经发布的内容引擎产物,而不是某个内部 API。在这 13 项公告中,SSRF 被评为高危,缓存投毒则是中危;但对前置缓存的 RSC 站点而言,实际影响的优先级恰好相反。

Next.js 升级怎么做:别踩 Turbopack 后续修复的坑

第一步,确认当前真正运行的版本。使用 caret range 时,package.json 并不能反映实际解析出的版本,应检查 lockfile。

Bash
bun pm ls | grep next
# or
npm ls next

然后精确锁定到 16.2.6(Next.js 16 分支)或 15.5.18(Next.js 15 分支)。不要用 16.2.5,也不要用 15.5.16。

Bash
bun add next@16.2.6
# or
npm install next@16.2.6 --save-exact

必须精确锁版本,是因为有一个鲜少被提及的坑。最初 13 项公告的修复于 5 月 6 日进入 16.2.5 / 15.5.16。5 月 7 日,Vercel 又发布 GHSA-26hh-7cqf-hhc6:segment-prefetch middleware 绕过此前并未修复完整,经 Turbopack 提供请求时仍可被利用。不使用 Turbopack 的用户在 16.2.5 / 15.5.16 已受保护,Turbopack 用户则没有。完整修复版本是 16.2.6 / 15.5.18。

如果还在 13.x 或 14.x 分支,不会再有补丁,Vercel 也不会 backport。唯一的修复方式是迁移到 15.x 或 16.x,而且应按一次迁移来评估,不能当作简单的 bun update。只要应用并非微不足道,至少要预留一周;破坏性变化确实存在,尤其集中在 middleware matcher 和 App Router 的默认缓存行为。

部署完成后,务必清除边缘缓存。 这是我本周看到的其他文章普遍漏掉的一步。不执行 purge,补丁上线前被 Cloudflare 缓存的 RSC payload 仍然存在;如果漏洞暴露期间有人利用过它,其中甚至可能已经被污染,并会继续从边缘节点提供,直到 s-maxage 到期。我的技术栈执行的是:

Bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE/purge_cache" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything": true}'

接下来验证结果。选择一条受 middleware 鉴权保护的路由,按安全公告中的 segment-prefetch URL 结构构造请求,并在生产环境重放。预期响应应是 401、302,或你的 middleware 对未认证请求返回的其他状态。如果拿到带内容的 200,说明 middleware 补丁没有生效;这是部署问题,不是 Next.js 本身的问题。

升到 16.2.6 后,哪些地方可能出问题?

必须坦白说,这些版本并非纯粹的安全补丁。多项修复有意改变了路由与 cache key 行为,因为漏洞本身就出在这些位置。因此,行为差异是预期之内的事。

针对 .rsc 和 segment-prefetch URL 的 middleware matcher 收紧。 segment-prefetch 绕过修复改变了 matcher 的匹配方式。如果 matcher pattern 依赖旧 URL 结构,就需要重新验证;尤其是使用 negative lookahead 排除 _next 路径,并默认 .rsc 一定在该路径下的情况。我不得不放宽一条 matcher,让它明确捕获受保护路由上的 segment-prefetch 后缀。修复只花了五分钟,但如果没有 replay test,它会成为无声的回归。

CSP nonce 处理。 XSS 修复(CVE-2026-44581)改变了 nonce 在 App Router render 过程中的传递方式。如果在 middleware 中生成 nonce,并在 Script 组件中引用,部署后应先让 CSP 以 report-only 模式运行一天。我没有看到违规报告,但这项变化确实存在,而且我听说有一个团队因此不得不更新 nonce 生成流程。

Cache Components 行为变化。 如果启用了 Cache Components,因而处在连接耗尽型 DoS 的修复路径上,这项修复会改变负载下 cache miss 的合并方式。需要重新测试 hot path。我没有使用 Cache Components,所以无需处理这一项。

我在确认升级完成前执行的验证清单:

Text
[ ] next version pinned to 16.2.6 in lockfile
[ ] middleware auth replay on /admin via segment-prefetch URL  401
[ ] middleware auth replay via .rsc URL  401
[ ] RSC cache key sanity: same URL, two clients, identical payload
[ ] forced edge purge after deploy
[ ] CSP report-only on for 24h with no new violations
[ ] one full revalidate cycle on a high-traffic page

请为 staging 测试预留时间。这不是一次零风险的补丁升级,因为安全修复会有意调整路由与 cache key 行为。周二下午能否顺利完成部署,而不是周二晚上陷入事故,关键就在于切换生产环境之前是否对鉴权路径做过 replay test。

应该打补丁,而不是依赖 WAF:这次事件的架构启示

Vercel 没有为这次发布提供 WAF 规则。changelog 明确表示,打补丁是唯一完整的缓解方案;这个判断是对的,因为这些漏洞的恶意请求结构与合法请求重叠太多,无法在边缘层干净地过滤。Cloudflare 于 5 月 6 日推出了 WAF 规则和 framework-adapter 缓解措施,但定位是纵深防御,不能替代升级。措辞值得仔细看:Cloudflare changelog 明确说,这些 WAF 规则只是在 rollout 窗口期降低暴露,而不是升级后的替代措施。

这也是本周事件带来的架构启示。如果一套技术栈能在一个下午完成框架升级、重新部署和边缘缓存清理,那么 13 个 CVE 的协调披露就只是周二待办清单上的一项。如果做不到——因为升级等同于迁移、系统没有 purge 能力,或部署流水线卡着人工 gate——暴露时间就会与 rollout 一样长。可能是几天,有时甚至数周。

这与限制 Agent 爆炸半径的思路完全一致:系统性的快速恢复能力胜过被动过滤。你无法拦住每一个恶意请求,也无法阻止每一次不良 Agent 调用;真正要做的是让事件发生后的响应窗口以分钟计,并依靠拓扑限制爆炸半径,而不是寄希望于侥幸。

今晚就升级。锁定 16.2.6 或 15.5.18,完成后清除缓存。那条有截图传播的 CVE 并不是首要风险;真正值得担心的,是那个会触及每一个缓存页面的中危漏洞。

部署在 Vercel 上,也需要升级吗?

需要。Vercel 只消除了自托管 SSRF(CVE-2026-44578)的风险;middleware 绕过、RSC 缓存投毒、DoS 和 XSS 公告仍然影响 Vercel 托管的 App Router 应用。

16.2.5 / 15.5.16 已经够用,还是必须升到 16.2.6 / 15.5.18?

请直接升级到 16.2.6 / 15.5.18。较早的版本修复了最初 13 项漏洞,但 5 月 7 日的后续公告(GHSA-26hh-7cqf-hhc6)表明,Turbopack 用户仍可遭遇 segment-prefetch 绕过。

我还在用 Next.js 14,补丁在哪里?

没有补丁。13.x 和 14.x 都不会获得修复;唯一办法是迁移到 15.x 或 16.x。请把它按一次迁移来规划,而不是普通版本升级。

升级前能否先靠 Cloudflare 或 Vercel WAF 规则顶住?

只能作为纵深防御。Cloudflare 于 5 月 6 日推出了 WAF 与 adapter 缓解措施;Vercel 没有发布 WAF 规则,并明确表示打补丁才是唯一完整的修复方式。

哪一项公告真正威胁前置缓存的 RSC 站点?

RSC 缓存投毒公告。遭到污染的响应一旦按 s-maxage 缓存在边缘节点,就会持续提供给所有访客,直到对应的 Cache-Tag 被清除。

最近更新

2026年9月5日

分类Build

在 Google 中优先显示本站

将 omidsaffari.com 添加为 Google 搜索的优先来源

把 omidsaffari.com 设为优先来源,Google 会在 Top Stories、AI Overviews 和 AI Mode 中为您优先展示。

更多 Build 文章

查看全部 Build 文章
订阅通讯

每周日,一封信。 写运转中的系统,不写热评。

来自一组 AI 项目组合运营的构建日志、生产系统与一线笔记。

每周一期。无垃圾邮件。随时退订。