The vulnerability is a client-side path traversal that is enabled by a lack of validation on the server side during prerendering.
Server-Side Flaw: During the server-side rendering (specifically, prerendering), Nuxt serializes the application state. The plugin defined in packages/nuxt/src/app/plugins/revive-payload.server.ts includes a reducer for 'Island' components. The original code for this reducer (data => data && data?.__nuxt_island) would accept any object with a __nuxt_island property and serialize it without validating its contents. This allows an attacker who can control data returned from an API during prerendering to inject a malicious Nuxt Island object with a path traversal payload in the key field (e.g., { "__nuxt_island": { "key": "../../../../internal/service" } }).
Client-Side Execution: When a user navigates to the prerendered page, the client-side JavaScript kicks in. A function within packages/nuxt/src/app/plugins/revive-payload.client.ts (referred to as the "Island reviver") deserializes the state. When it encounters the malicious __nuxt_island object, it takes the key and attempts to fetch the component's data from /__nuxt_island/${key}.json. Due to the lack of sanitization, the client constructs a URL with the path traversal sequence, like /__nuxt_island/../../../../internal/service.json, and sends a request to this unintended endpoint.
The Fix: The provided patch addresses the vulnerability at the source by fixing the server-side flaw. It introduces a validation function isValidIslandKey and modifies the 'Island' reducer in revive-payload.server.ts to use it (data => data && data?.__nuxt_island && isValidIslandKey(data.__nuxt_island.key) && data.__nuxt_island). This ensures that only valid keys are serialized, preventing the malicious payload from ever reaching the client.
The primary vulnerable function identified from the patch is the anonymous reducer within defineNuxtPlugin in revive-payload.server.ts because it fails to validate input. However, the function that actually performs the path traversal is on the client side, in revive-payload.client.ts. While its exact name is not in the provided data, its role as the "Island reviver" is clear from the vulnerability description.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| nuxt | npm | >= 3.6.0, < 3.19.0 | 3.19.0 |
| nuxt | npm | >= 4.0.0, < 4.1.0 | 4.1.0 |
Ongoing coverage of React2Shell