high · 7.5CVE-2026-71316Aug 5, 2026

CVE-2026-71316: Nuxt SSR Payload Cache Cross-User Information Disclosure

Rohit Hatagale
AI Security Researcher, SecureLayer7

Nuxt 4.x cached pages stored each user's SSR data in a shared server-side cache keyed only by URL path, letting any visitor fetch another user's private page data with a plain HTTP GET.

Packagenuxt
Ecosystemnpm
Affected>= 4.4.0, <= 4.5.0
Fixed in4.5.1
CVE-2026-71316: Nuxt SSR Payload Cache Cross-User Information Disclosure

The problem

Pages covered by cache, swr, or isr route rules in Nuxt 4.4.0-4.5.0 caused the renderer to write the full SSR payload into a shared cache:nuxt:payload storage entry keyed only by URL path. No session cookie, Authorization header, or cache.varies dimension was included in the cache key.

Once any authenticated user warmed a protected page, a later GET /<page>/_payload.json from a different user or an unauthenticated client was served the cached entry without route middleware or page guards running again. The leaked payload contains everything loaded via useFetch / useAsyncData for that route, including profile data, tenant context, billing details, and token-like values.

The HTML response was correctly varied; only the extracted payload endpoint was affected.

Proof of concept

A working proof-of-concept for CVE-2026-71316 in nuxt, with the exact payload below.

http
# Step 1: authenticated user (or crawler) warms the cached page
GET /dashboard HTTP/1.1
Host: target.example.com
Cookie: session=<valid-session-token>

# Step 2: unauthenticated attacker retrieves the cached SSR payload
GET /dashboard/_payload.json HTTP/1.1
Host: target.example.com

# Response (no auth required) -- contains the first user's full SSR state:
# {"data":{"me":{"id":1,"email":"victim@example.com","plan":"enterprise",...},...}}

The root cause is a missing import.meta.prerender gate on payload-cache reads and writes, introduced in PR #34410 when runtime payload extraction was extended to cached routes in the 4.x line. In 3.x the same code path was guarded by import.meta.prerender, so writes only happened during static prerendering where all users share the same public content.

In 4.4.0-4.5.0 that guard was dropped, making the cache active at runtime. Because the storage key was the URL path alone (CWE-524: Use of Cache Containing Sensitive Information), the payload written for user A was returned verbatim to user B with zero authorization check (CWE-862: Missing Authorization).

The cache.varies option had no effect because the payload cache ignored it entirely.

The fix

Upgrade to nuxt@4.5.1. The patch (commit ac9b41a) re-adds the import.meta.prerender gate so payload-cache reads and writes are limited to build-time prerendering only. At runtime, /_payload.json requests go through the full render pipeline, re-running route middleware and page guards.

Immediate workarounds if you cannot upgrade right now: set experimental.payloadExtraction: false in nuxt.config.ts (the standalone /_payload.json endpoint returns 404; pages still serve an inline payload), or block /**/_payload.json at your CDN or reverse proxy for authenticated routes.

After upgrading, purge any CDN or edge cache that may already hold a leaked payload.

Reporter not attributed.

References: [1][2][3][4]

Related research