CVE-2026-71318: Nuxt Unauthorized Component Instantiation Vulnerability
MODERATECVE-2026-71318 is a MODERATE (CVSS 4.8) unauthorized component instantiation vulnerability (CWE-20: Improper Input Validation) affecting Nuxt libraries in the npm ecosystem. The issue involves unauthorized component instantiation via server island props. Remediation is available by upgrading affected packages to version 4.5.1, 3.21.10.
CVE-2026-71318 at a Glance
Security Impact
CVSS: 4.8
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N).
How to Fix CVE-2026-71318
To remediate this vulnerability, upgrade all affected Nuxt dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install nuxt@4.5.1
npm install nuxt@3.21.10
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls nuxt
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-71318, inspect your project dependencies using npm:
npm ls nuxt
Analyze the terminal output to locate any version of Nuxt in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 4.5.1), your application is affected.
Note: The npm ls nuxt command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-20: Improper Input Validation, where the product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly. In Nuxt, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-71318 Affected Nuxt Versions
2 component(s)References
Frequently Asked Questions
What is CVE-2026-71318?
Which Nuxt versions are affected?
What version fixes CVE-2026-71318?
Is nuxt affected?
What is the CVSS score of CVE-2026-71318?
What CWE is associated with CVE-2026-71318?
How can I check npm dependencies for CVE-2026-71318?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-48hr-524c-v5w3",
"modified" : "2026-08-05T21:21:33Z",
"published" : "2026-08-05T21:21:33Z",
"aliases" : [ "CVE-2026-71318" ],
"summary" : "Nuxt: Unauthorized Component Instantiation via Server Island Props",
"details" : "## Impact\n\nNuxt server islands accept props via the `/__nuxt_island/` endpoint. When an application has a server island component that forwards props directly into Vue's dynamic component resolution (`<component :is>`, `resolveDynamicComponent`, or `h()`), an attacker can pass a plain string value (rather than a component definition) to instantiate any globally-registered Vue component or any native HTML element.\n\nFor example:\n```json\n{ \"as\": \"SomeGlobalComponent\" }\n```\n\n...resolves and renders `SomeGlobalComponent` if it is globally registered, even though the attacker should only be able to drive props for the island's declared component. Similarly, `{ \"as\": \"iframe\" }` renders an `<iframe>` element.\n\nUnlike the primary RCE vector (GHSA-9473-5f9j-94wq), this does **not** require `vue.runtimeCompiler` to be enabled. A plain string prop is sufficient to trigger component resolution. The `template`/`render` key guard that addresses the RCE vector does not block plain string values.\n\nSome component libraries expose a polymorphic `as` / `asChild` prop that forwards its value into `<component :is>`; `@nuxt/ui` (via `reka-ui`) is a widely used example. An application is affected if such a component receives the attacker-controlled value inside a server island. Note this does not require explicit prop forwarding: island props the island component does not declare fall through as attributes onto its single root element, so an island whose root is a `reka-ui` / `@nuxt/ui` component receives the attacker's `as` value implicitly. Unlike the RCE vector, no `vue.runtimeCompiler` is required, which makes this vector reachable in more configurations. These libraries are not themselves vulnerable; they are noted only because they commonly provide the dynamic-component sink. Installing `@nuxt/ui` does not by itself register any component as a server island: the application must define the island (a `.server.vue` file).\n\n## Mitigating factors\n\n- Exploitation requires a server island component that puts an attacker-controlled value onto a dynamic-component path (`<component :is>`, `resolveDynamicComponent`, `h()`, or a polymorphic `as` / `asChild` prop), either explicitly or via attribute fallthrough when the island's root is such a component.\n- Reachable components are limited to what is actually in the island app's global registry. In a default pages-enabled app that is `RouterView` and `RouterLink` (both registered globally by the pages router plugin, which runs even in component islands), plus any `components/global/` component and any component a module registers globally. `RouterLink` in particular renders an attacker-influenced `<a>` (and, because an island that declares no props forwards all props, `to` and other `RouterLink` props ride the same fallthrough). Vue built-ins (`Transition`, `KeepAlive`, `Teleport`, `Suspense`) and Nuxt auto-imports (`ClientOnly`, `NuxtLink`, `NuxtPage`, etc.) are NOT in the island app's global registry and cannot be resolved this way; an unresolved name instead renders as a native HTML element (the element-injection half of this issue).\n- Declaring the props an island accepts, or setting `inheritAttrs: false` on it, prevents an undeclared `as` from falling through to a polymorphic root and neutralizes this vector.\n- Arbitrary JavaScript execution is not possible through this vector (no `template`/`render` compilation).\n- Island component names are constrained to the build-time component registry; an attacker cannot resolve arbitrary components.\n\n## Affected versions\n\nNuxt `>=3.1.0 <3.21.10` and `>=4.0.0 <4.5.1`, with component islands active. The island prop-forwarding behavior has existed since server islands were introduced in v3.1.0, and this vector does not depend on `vue.runtimeCompiler`. Nuxt 2 is not affected.\n\nNote the patch (below) closes the implicit attribute-fallthrough path, which is the majority case. An island that *explicitly* forwards an untrusted prop into dynamic component resolution (or forwards it under a prop name other than `as`) remains the application's responsibility in every version; see Workarounds.\n\n## Patches\n\nFixed in `nuxt@4.5.1` and `nuxt@3.21.10`. Patched releases reject a top-level `as` island prop (HTTP 400 at the `/__nuxt_island/` endpoint). This closes the implicit path: island props an island does not declare fall through as attributes onto its single root, so a top-level `as` would otherwise reach a polymorphic root component's `as` prop (the `reka-ui` / `@nuxt/ui` convention) and drive dynamic component resolution without the author binding it. Rejecting the top-level `as` prop blocks that fallthrough while leaving nested data and other prop names untouched.\n\nThe framework deliberately does not attempt to block every case: it cannot safely tell a string used as data from one used as a component selector, and it has no island-local hook into Vue's `h()` or `resolveDynamicComponent()`. An island that explicitly forwards an untrusted value into `<component :is>` / `h()` / `resolveDynamicComponent()`, or that forwards it under a different polymorphic prop name, is therefore not covered by the patch and must follow the guidance below. The Nuxt documentation now warns against this.\n\n## Workarounds\n\nUpgrade to `nuxt@4.5.1` or `nuxt@3.21.10`. That upgrade also removes the related object-prop RCE (GHSA-9473-5f9j-94wq). In addition, in any version:\n\n1. Do not forward island props into `<component :is>`, `resolveDynamicComponent`, or `h()`. Map an untrusted discriminator through a closed allowlist of imported component definitions instead of passing the raw prop value.\n2. Declare the props an island accepts, or set `inheritAttrs: false` on it, so request input cannot fall through to a polymorphic root component.\n3. Avoid registering sensitive components globally that could leak information if instantiated by an attacker.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "nuxt"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "4.0.0"
}, {
"fixed" : "4.5.1"
} ]
} ]
}, {
"package" : {
"ecosystem" : "npm",
"name" : "nuxt"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "3.1.0"
}, {
"fixed" : "3.21.10"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/nuxt/nuxt/security/advisories/GHSA-48hr-524c-v5w3"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/nuxt/nuxt"
}, {
"type" : "WEB",
"url" : "https://github.com/nuxt/nuxt/releases/tag/v3.21.10"
}, {
"type" : "WEB",
"url" : "https://github.com/nuxt/nuxt/releases/tag/v4.5.1"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-20" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-08-05T21:21:33Z",
"nvd_published_at" : null
}
}