chore(deps): update devdependency nuxt to v3.21.10 [security] - #236
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update devdependency nuxt to v3.21.10 [security]#236renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
September 25, 2025 17:59
f08d777 to
d553bf6
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
October 21, 2025 20:06
d553bf6 to
c7c4695
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
November 10, 2025 22:08
c7c4695 to
55d6534
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
November 18, 2025 23:09
55d6534 to
6ca4e7e
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
December 3, 2025 15:47
6ca4e7e to
2b92157
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
December 31, 2025 18:10
2b92157 to
a28f902
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
January 8, 2026 20:52
a28f902 to
1c7c279
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
January 23, 2026 21:10
4708e19 to
a7efd7b
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
February 2, 2026 15:36
a7efd7b to
995d330
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
February 17, 2026 17:59
f6e1469 to
3b2d6da
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
March 5, 2026 17:09
3b2d6da to
6d18ee4
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
March 13, 2026 12:54
6d18ee4 to
06c4dd3
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
3 times, most recently
from
April 1, 2026 21:43
6e1bc7b to
8592786
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
April 8, 2026 15:31
8592786 to
ade3997
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
April 29, 2026 17:33
52eb5d3 to
a180228
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
May 12, 2026 13:39
a180228 to
e07161c
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
May 18, 2026 13:43
e07161c to
558be1f
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
June 2, 2026 00:03
512d998 to
8e7c4e6
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
June 11, 2026 22:07
8e7c4e6 to
a36c744
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
July 16, 2026 18:45
796eb48 to
f3122d7
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
July 24, 2026 22:37
376d8fb to
a7a72f7
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
July 30, 2026 19:43
a7a72f7 to
4f7d486
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
2 times, most recently
from
August 14, 2026 21:35
c048d2a to
79c3047
Compare
renovate
Bot
force-pushed
the
renovate/npm-nuxt-vulnerability
branch
from
August 26, 2026 10:02
79c3047 to
3a55a3b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
3.16.0→3.21.10nuxt vulnerable to Cross-site Scripting in navigateTo if used after SSR
CVE-2024-34343 / GHSA-vf6r-87q4-2vjf
More information
Details
Summary
The
navigateTofunction attempts to blockthejavascript:protocol, but does not correctly use API's provided byunjs/ufo. This library also contains parsing discrepancies.Details
The function first tests to see if the specified URL has a protocol. This uses the unjs/ufo package for URL parsing. This function works effectively, and returns true for a
javascript:protocol.After this, the URL is parsed using the
parseURLfunction. This function will refuse to parse poorly formatted URLs. Parsingjavascript:alert(1)returns null/"" for all values.Next, the protocol of the URL is then checked using the
isScriptProtocolfunction. This function simply checks the input against a list of protocols, and does not perform any parsing.The combination of refusing to parse poorly formatted URLs, and not performing additional parsing means that script checks fail as no protocol can be found. Even if a protocol was identified, whitespace is not stripped in the
parseURLimplementation, bypassing theisScriptProtocolchecks.Certain special protocols are identified at the top of
parseURL. Inserting a newline or tab into this sequence will block the special protocol check, and bypass the latter checks.PoC
POC - https://stackblitz.com/edit/nuxt-xss-navigateto?file=app.vue
Attempt payload X, then attempt payload Y.
Impact
XSS, access to cookies, make requests on user's behalf.
Recommendations
As always with these bugs, the
URLconstructor provided by the browser is always the safest method of parsing a URL.Given the cross-platform requirements of nuxt/ufo a more appropriate solution is to make parsing consistent between functions, and to adapt parsing to be more consistent with the WHATWG URL specification.
Note
I've reported this vulnerability here as it is unclear if this is a bug in ufo or a misuse of the ufo library.
This ONLY has impact after SSR has occurred, the
javascript:protocol within a location header does not trigger XSS.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt has Client-Side Path Traversal in Nuxt Island Payload Revival
CVE-2025-59414 / GHSA-p6jq-8vc4-79f6
More information
Details
Summary
A client-side path traversal vulnerability in Nuxt's Island payload revival mechanism allowed attackers to manipulate client-side requests to different endpoints within the same application domain when specific prerendering conditions are met.
Technical Details
The vulnerability occurs in the client-side payload revival process (revive-payload.client.ts) where Nuxt Islands are automatically fetched when encountering serialized
__nuxt_islandobjects. The issue affects the following flow:__nuxt_islandobjectdevalue.stringifyand stored in the prerendered pagedevalue.parsedeserializes the payload/__nuxt_island/${key}.jsonwherekeycould contain path traversal sequencesPrerequisites for Exploitation
This vulnerability requires all of the following conditions:
nitro.prerender)useFetch,useAsyncData, or similar composablesAttack Scenario
This could cause the client to make requests to
/__nuxt_island/../../../../internal/service.jsonif path traversal is not properly handled by the server.Impact Assessment
Mitigation
Action Required:
Temporary Workarounds (if immediate update is not possible):
Fix Details
The fix implemented validation for Island keys in
revive-payload.server.ts:/^[a-z][a-z\d-]*_[a-z\d]+$/iSeverity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Reflected XSS in
navigateTo()external redirectCVE-2026-45669 / GHSA-fx6j-w5w5-h468
More information
Details
Summary
navigateTo()withexternal: truegenerates a server-side HTML redirect body containing a<meta http-equiv="refresh">tag. The destination URL is only sanitized by replacing"with%22, leaving<,>,&, and'unencoded. An attacker who can influence the URL passed tonavigateTo(url, { external: true })can break out of thecontent="…"attribute and inject arbitrary HTML/JavaScript that executes under the application's origin.This is a different root cause from CVE-2024-34343 (GHSA-vf6r-87q4-2vjf), which addressed
javascript:protocol bypass. The issue here is triggered by any valid URL containing>.Impact
Applications that pass user-controlled input to
navigateTo(url, { external: true })— typically via a?next=/?redirect=query parameter used for post-login or "return to" flows — are vulnerable to reflected cross-site scripting. The injected script runs in the context of the application's origin during the server-rendered redirect response, before the meta-refresh fires.Details
In
packages/nuxt/src/app/composables/router.ts, the SSR redirect path builds an HTML response body with only"percent-encoded in the destination URL:The
Locationheader is normalised throughencodeURL()(which uses theURLconstructor and correctly percent-encodes attribute-significant characters). The HTML body uses a narrower sanitiser. That mismatch is the root cause.Proof of concept
Global middleware that forwards a query parameter to
navigateTo:Request:
Response body:
The
>afterevil.example/xterminates thecontent="…"attribute, and the<img onerror>tag executes JavaScript in the application's origin before any redirectoccurs.
Patches
Fixed in
nuxt@4.4.6andnuxt@3.21.6by #35052. The fix percent-encodes the full set of HTML-attribute-significant characters (&,",',<,>) before interpolating the URL into the meta-refresh bodyWorkarounds
If you can't upgrade immediately, validate user-controlled URLs before passing them to
navigateTo(url, { external: true }). At minimum, normalise throughnew URL(input).toString()and reject inputs containing<or>(a normalised URL with these characters is malformed and safe to refuse).Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt:
__nuxt_islandendpoint does not bind responses to request props, enabling shared-cache poisoningCVE-2026-46342 / GHSA-g8wj-3cr3-6w7v
More information
Details
Summary
The
/__nuxt_island/*endpoint accepts attacker-controlledpropsquery/body parameters and renders any island component without verifying that the URL-resident hash (<Name>_<hashId>.json) was actually issued for those inputs by<NuxtIsland>. The hash is computed and embedded client-side but never validated server-side, so the same path can return materially different responses depending on the query.Island components are documented as rendering independently of route context - page middleware does not apply to them, and they are intentionally cacheable as a function of their props. This advisory does not treat that contract as a vulnerability. It treats the absence of a binding between the URL the cache keys on and the response served at that URL as one.
Impact
In applications where a CDN or reverse-proxy in front of the app caches
/__nuxt_island/*keyed by path only (ignoring query) - a documented misconfiguration class, see GHSA-jvhm-gjrh-3h93 - an attacker can prime the cache for a path with their own choice of props, and subsequent users requesting the same path receive the attacker's rendered HTML rather than the response intended for them. The cache entry persists until normal expiry.Where the affected island has any prop flowing into an unsafe HTML sink in application code (
v-html,innerHTML, a third-party renderer treating a prop as HTML), this becomes stored XSS in the embedding page's origin until the cache entry expires.HttpOnlycookies remain out of reach but anything else in the origin (other cookies, in-origin requests, DOM state) is reachable by the injected script.Preconditions:
experimental.componentIslandsenabled (or the default'auto'with at least one server / island component in the app).Without the second precondition, the response shape is per-request and unaffected. Without the third, the worst case is content-swap / inert HTML injection rather than script execution.
Patches
Patched in
nuxt@4.4.6andnuxt@3.21.6by #35077. The island handler now recomputes the expectedhashIdfrom(name, props, context)using the sameohashfunction<NuxtIsland>already uses to embed the hash in the URL, and rejects requests (HTTP 400) whose URL-resident hash does not match. The response is now a pure function of the request path: a path-keyed shared cache returns the correct response to every requester for that path, and an attacker cannot synthesise a path whose hash matches arbitrary props.Workarounds
For users unable to upgrade immediately:
/__nuxt_island/*on the full query string, not on the path alone. This is the recommended configuration regardless.v-html/innerHTML/ similar HTML sinks; treat island props as untrusted user input.Note on island authentication
A separate advisory addresses
*.server.vuepages registered aspage_<routeName>islands, where the documented "middleware doesn't run for islands" contract collides with the page's owndefinePageMeta({ middleware })declaration in a way that constitutes a genuine bug rather than documented behaviour.Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt's route middleware is not enforced when rendering
.server.vuepages via/__nuxt_island/page_*CVE-2026-47200 / GHSA-hg3f-28rg-4jxj
More information
Details
Summary
When
experimental.componentIslandsis enabled (default in Nuxt 4), any.server.vuefile underpages/is automatically registered as a server island under the keypage_<routeName>and exposed via the/__nuxt_island/:nameendpoint. Until this fix, requests through that endpoint rendered the page component directly via the SSR renderer without instantiating Vue Router, which meant route middleware declared on the page (includingdefinePageMeta({ middleware })) did not run.For Nuxt applications that gate a
.server.vuepage behind route middleware as their sole auth check, an unauthenticated attacker could bypass that check by requesting/__nuxt_island/page_<routeName>_<anyhash>directly and receiving the server-rendered HTML.Affected configurations
All three conditions must hold for an application to be vulnerable:
experimental.componentIslandsis enabled (the default in Nuxt 4; opt-in in Nuxt 3)..server.vuefiles underpages/, registering them as routed pages.middleware/*.tsreferenced fromdefinePageMeta), without a server-side check inside the page or its data layer.Applications that enforce auth inside the island's own data layer (server-only API routes,
useRequestEvent+ manual session checks, etc.) were not affected. The general "route middleware does not run for non-page island components" behaviour is documented and unchanged; this advisory concerns the.server.vuepage case specifically, where running middleware is the user's clear expectation.Details
packages/nuxt/src/components/templates.ts):.server.vuepages are registered as island components withpage_prefix, making them addressable through/__nuxt_island/page_<routeName>_<hashId>.packages/nitro-server/src/runtime/handlers/island.ts): the handler resolves the requested island component and renders it viarenderer.renderToString(ssrContext). The Vue Router plugin previously short-circuited middleware execution wheneverssrContext.islandContextwas set.Proof of concept
Given a page
app/pages/secret.server.vue:with
middleware/auth.tsblocking unauthenticated access:Patches
Patched in
nuxt@4.4.6andnuxt@3.21.6by #35092. The Vue Router plugin now runs middleware and redirect handling forpage_*islands (i.e. islands that originate from.server.vuefiles inpages/). The island handler propagates middleware-issued responses (~renderResponse), and a newbeforeResolveguard returns HTTP 400 when the requestedpage_<name>does not match the route component the URL resolves to.Non-page island components are unaffected - they continue to render without route middleware, by design.
Workarounds
If you cannot upgrade immediately:
.server.vuepage itself, not via route middleware. Read the session fromuseRequestEvent()andthrow createError({ statusCode: 401 })(or redirect) before returning data. This is the recommended pattern for islands regardless of this advisory.experimental.componentIslandsif your app does not use the feature./__nuxt_island/page_*URL prefix at your reverse proxy or in a server middleware.Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Route-rule middleware bypass via case-sensitivity mismatch between vue-router and the routeRules matcher
CVE-2026-53721 / GHSA-mm7m-92g8-7m47
More information
Details
Impact
Nuxt looks up
routeRulesfor the current navigation by callinggetRouteRules({ path: to.path })from the page-router plugin and theno-pages router plugin. The compiled
routeRulesmatcher (built onrou3) performs case-sensitive matching, while vue-router is configuredwith its default
sensitive: falseand matches paths case-insensitively.The two routers therefore disagree on which rules apply to a given
request path: vue-router still matches the page record for
/Admin/dashboard, but therouteRuleslookup for the same pathreturns no match. Any
appMiddlewaredeclared viarouteRulesis neveradded to the middleware set and never runs, on both SSR and client
navigations. The same path skips other path-keyed route rules in the
same way (
ssr,redirect,appLayout, and the prerender / payloadhints used client-side).
For applications using
routeRuleswithappMiddlewareas anauthorization gate (a documented pattern), an attacker can flip the case
of any static segment in a protected URL (for example
/Admin/dashboardinstead of
/admin/dashboard) to render the protected page with themiddleware skipped. The server returns the fully server-rendered page
including any
useFetch/useAsyncDataresults captured during SSR.This is an instance of CWE-178 (Improper Handling of Case Sensitivity)
leading to CWE-863 (Incorrect Authorization) for apps that treat
appMiddlewareas an authorization boundary.Mitigating factors
routeRules.appMiddleware. The moreidiomatic
definePageMeta({ middleware })is bound to the matchedroute record and is unaffected.
server-side auth boundary; well-built apps enforce authorization
again at the API / data-fetching layer.
router.options.sensitive = trueare notaffected.
Patches
Fixed in
nuxt@4.4.7(commit07e39cd6) and backported tonuxt@3.21.7(commit3f3e3fa7). The fix normalizes the path used forrouteRuleslookups so it matches vue-router's default case-insensitive semantics.Workarounds
Until you can upgrade, you can mitigate by either:
router.options.sensitive = trueso vue-router matchescase-sensitively (this changes route-matching behaviour app-wide).
routeRules.appMiddlewareand onto
definePageMeta({ middleware: [...] })on the protectedpage components, which is bound to the matched record.
should be doing in any case).
Credit
Reported by Anthropic / Claude through Anthropic's coordinated
vulnerability disclosure process. Reference: ANT-2026-9FSEBYMC.
Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Cross-site scripting via slot content in Nuxt's head components
GHSA-m3q2-p4fw-w38m
More information
Details
Impact
Nuxt's globally registered
<NoScript>component (from@unhead/vuehead components, re-exported by Nuxt) wrote its default-slot content to theinnerHTMLof the<noscript>head tag, bypassing the HTML escaping that{{ }}interpolation normally applies in Vue templates.Applications that placed untrusted, attacker-controllable data inside a
<NoScript>slot, for example:would emit that value unescaped inside
<noscript>in the server-rendered HTML. With scripting enabled, the HTML parser treats<noscript>content in<head>under the "in head noscript" insertion mode: any tag other thanlink,meta,noframes, orstyleimplicitly closes<noscript>and is re-processed in the head. A payload such as<script>...</script>therefore escapes the element and executes in the document context.Sibling head components (
<Style>,<Title>) were not affected because they already routed slot text through the safetextContentpath.Affected versions
All currently supported versions of
nuxtthat ship the<NoScript>global component.Patches
Fixed in
nuxt@4.4.7(commit4b054e9d) and backported tonuxt@3.21.7(commit7fea9fd6). The fix escapes<NoScript>slot content withescapeHtmlfrom@vue/sharedand writes it totextContentrather thaninnerHTML. Slot content is now rendered as text; intentional markup inside<NoScript>is no longer parsed as HTML.Workarounds
Until you can upgrade:
<NoScript>slots. Replace<NoScript>{{ x }}</NoScript>with a static string, or sanitise / HTML-escapexat the source.useHead({ noscript: [{ textContent: escapedValue }] })after escapingescapedValue.Credit
Reported to Anthropic's coordinated vulnerability disclosure pipeline by Claude (Anthropic's AI assistant) and triaged by the Anthropic security team. Reference: ANT-2026-4NJYDFFM.
Independently reported by @alcls01111 via GitHub's coordinated disclosure flow (
GHSA-8grp-wcq9-925q), closed as a duplicate of this advisory.Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Unauthenticated out-of-memory crash via unbounded v-for expansion in island rendering
CVE-2026-71314 / GHSA-hxcr-hm88-mpq6
More information
Details
Impact
An unauthenticated attacker can crash a Nuxt server that renders any island / server component containing a
v-forover a prop (for examplev-for="n in count"or a<slot v-for>). Because the island URL hash is a non-secret digest of the request, the attacker can compute a valid hash for arbitrary props and send the iterated prop as a large integer. The server then expands thev-forto that many nodes during SSR, allocating memory proportional to the attacker's number. Reporter figures:count=8000000produced a 142.9 MB response;count=40000000(anditems=4000000on a slot list) produced an out-of-memory crash of the worker from a single ~130-byte request. Both the plainv-forpath (Vue'sssrRenderList) and the slot path (vforToArray) are affected.Patches
Fixed in
nuxt@4.5.1andnuxt@3.21.10. Island/server-componentv-forsources are now clamped to a maximum iteration count (MAX_VFOR_LENGTH = 100000) at the render boundary, covering the plain path, the<slot v-for>element, and thevforToArrayslot-props helper. Combined with the body-size cap (GHSA-9pgf-384g-p7mv), a single island render can no longer allocate without bound regardless of whichv-forpath is used or whether the prop arrives as an integer or an array.Workarounds
Avoid
v-fordirectly over an unclamped prop in server components, or clamp the count in the component (v-for="n in Math.min(count, 1000)"). A body-size limit in front of/__nuxt_island/only mitigates array-shaped inputs, not the integer-amplification case.References
packages/nuxt/src/app/components/vfor.tspackages/nuxt/src/components/plugins/islands-transform.tspackages/nuxt/src/app/components/utils.ts(vforToArray)Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Unauthorized Component Instantiation via Server Island Props
CVE-2026-71318 / GHSA-48hr-524c-v5w3
More information
Details
Impact
Nuxt 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, orh()), 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.For example:
{ "as": "SomeGlobalComponent" }...resolves and renders
SomeGlobalComponentif 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.Unlike the primary RCE vector (GHSA-9473-5f9j-94wq), this does not require
vue.runtimeCompilerto be enabled. A plain string prop is sufficient to trigger component resolution. Thetemplate/renderkey guard that addresses the RCE vector does not block plain string values.Some component libraries expose a polymorphic
as/asChildprop that forwards its value into<component :is>;@nuxt/ui(viareka-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 areka-ui/@nuxt/uicomponent receives the attacker'sasvalue implicitly. Unlike the RCE vector, novue.runtimeCompileris 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/uidoes not by itself register any component as a server island: the application must define the island (a.server.vuefile).Mitigating factors
<component :is>,resolveDynamicComponent,h(), or a polymorphicas/asChildprop), either explicitly or via attribute fallthrough when the island's root is such a component.RouterViewandRouterLink(both registered globally by the pages router plugin, which runs even in component islands), plus anycomponents/global/component and any component a module registers globally.RouterLinkin particular renders an attacker-influenced<a>(and, because an island that declares no props forwards all props,toand otherRouterLinkprops 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).inheritAttrs: falseon it, prevents an undeclaredasfrom falling through to a polymorphic root and neutralizes this vector.template/rendercompilation).Affected versions
Nuxt
>=3.1.0 <3.21.10and>=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 onvue.runtimeCompiler. Nuxt 2 is not affected.Note 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.Patches
Fixed in
nuxt@4.5.1andnuxt@3.21.10. Patched releases reject a top-levelasisland 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-levelaswould otherwise reach a polymorphic root component'sasprop (thereka-ui/@nuxt/uiconvention) and drive dynamic component resolution without the author binding it. Rejecting the top-levelasprop blocks that fallthrough while leaving nested data and other prop names untouched.The 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()orresolveDynamicComponent(). 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.Workarounds
Upgrade to
nuxt@4.5.1ornuxt@3.21.10. That upgrade also removes the related object-prop RCE (GHSA-9473-5f9j-94wq). In addition, in any version:<component :is>,resolveDynamicComponent, orh(). Map an untrusted discriminator through a closed allowlist of imported component definitions instead of passing the raw prop value.inheritAttrs: falseon it, so request input cannot fall through to a polymorphic root component.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Server-Side Remote Code Execution via Runtime Template Injection in Nuxt Server Island Props
CVE-2026-71320 / GHSA-9473-5f9j-94wq
More information
Details
Impact
Nuxt server islands accept props via the
/__nuxt_island/endpoint. Whenvue.runtimeCompiler: trueis enabled (off by default) and the application has a server island component that forwards props into Vue's dynamic component resolution (<component :is>,resolveDynamicComponent, orh()), an attacker can inject atemplatekey into the island props to achieve server-side remote code execution in the Nitro process.{ "as": { "template": "<attacker-controlled>" } }Vue's runtime template compiler compiles and executes the attacker-controlled
templatein the server process. The same primitive also works on the client side when the runtime compiler is active there, though the server-side path is the primary concern.Some component libraries expose a polymorphic
as/asChildprop that forwards its value into<component :is>;@nuxt/ui(viareka-ui) is a widely used example. An application is affected if such a component receives the attacker-controlled value, providedvue.runtimeCompileris also enabled. Note this does not require the island author to explicitly forward a prop: island props that the island component does not declare fall through as attributes onto its single root element (standard Vue attribute inheritance), so an island whose root is a polymorphic component receives the attacker'sasvalue implicitly. These libraries are not themselves vulnerable; they are noted only because they commonly provide the dynamic-component sink.Common configurations that satisfy the preconditions
The flaw is in Nuxt core. The library below is not itself vulnerable; it is noted because it commonly provides the dynamic-component sink an application might inadvertently expose.
@nuxt/ui(via its underlyingreka-uiprimitives) exposes a polymorphicas/asChildprop that is forwarded into Vue's dynamic-component resolution. Installing@nuxt/uidoes not by itself register any component as a server island. Exploitation requires the application to define an island component (a.server.vuefile) whose rendered output puts the attacker-controlled value on such a component'sas/asChildprop; withvue.runtimeCompiler: true, the attacker-controlledtemplateis then compiled and executed. Because undeclared island props fall through as attributes to the single root, this can happen without any explicit binding: an island whose root is areka-ui/@nuxt/uicomponent is enough. An example vulnerable island (theasvalue falls through toUButton, no explicit forwarding needed):The island URL hash (
/__nuxt_island/<Name>_<hash>.json) is a deterministic (unsalted) content hash, not an authentication token. It provides integrity relative to the URL but is not a security boundary: an attacker who knows the component name and desired props can compute a valid hash.Mitigating factors
vue.runtimeCompileris off by default in Nuxt. The vast majority of Nuxt applications are not affected.<component :is>,resolveDynamicComponent,h(), or a polymorphicas/asChildprop). This can occur explicitly or via attribute fallthrough when the island's root is such a component.Affected versions
Nuxt
>=3.4.0 <3.21.10and>=4.0.0 <4.5.1, and only whenvue.runtimeCompiler: trueand component islands are active. Earlier versions did not allow the Vue compiler to be enabled in the server bundle (the compiler dependencies have been mock-aliased on the server since v3.0.0-rc.1), so the runtime-compilation path is not reachable. Nuxt 2 is not affected (no server islands).Patches
When
vue.runtimeCompileris enabled, island requests whose decoded props contain atemplatekey at any depth are rejected with an HTTP 400 and a diagnostic suggesting the author rename the prop or disable the runtime compiler. The guard is gated on the runtime compiler being enabled, so the default configuration (compiler off) is unaffected and legitimate props that merely contain atemplatefield (for example CMS content) continue to render. Arenderkey is not rejected: island props arrive as JSON, so arendervalue can only be an inert string, which Vue ignores.Fixed in
nuxt@4.5.1and backported tonuxt@3.21.10.Workarounds
Upgrade to
nuxt@4.5.1ornuxt@3.21.10. If you cannot immediately upgrade, you can mitigate by:vue.runtimeCompileris set tofalse(the default).<component :is>,resolveDynamicComponent, orh()without sanitization./__nuxt_island/that URL-decodes and JSON-parses thepropsvalue and blocks any object property namedtemplateorrenderin the decoded island props, inspecting both query and body for all methods. Note: this only covers direct and browser-originated island requests; initial-SSR internal island renders do not transit the edge and a WAF alone does not close the vector.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: Unauthenticated CPU exhaustion parsing and hashing the Nuxt island endpoint body before hash validation
CVE-2026-71321 / GHSA-9pgf-384g-p7mv
More information
Details
Impact
The internal island renderer endpoint (
/__nuxt_island/...) decodes and hashes attacker-controlled request input before it validates the URL-resident hash. An unauthenticatedPOST /__nuxt_island/<name>_<anything>.jsonwith a large JSON body (for example ~4.6 MB / 150k keys) is fully read,destr-parsed, and run throughohashbefore the request is rejected with a 400. Because Nitro runs on a single event loop, this both wastes CPU on the doomed request and delays every concurrent request. A low request rate is enough to degrade or stall the server. No valid hash and no authentication are required.Patches
Fixed in
nuxt@4.5.1andnuxt@3.21.10. The island handler now enforces a raw body-size cap (413) and a JSON nesting-depth cap (400) before parsing or hashing, so oversized or deeply nested input is rejected cheaply.Workarounds
Put a small request-body limit in front of
/__nuxt_island/at your reverse proxy / edge (islands legitimately send only a compact props payload), or disable server components if unused.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Nuxt: URL-handling weaknesses in
navigateToandreloadNuxtApp: SSR open redirect, client-side script execution via theopenoption, and protocol-relative bypass inreloadNuxtAppCVE-2026-56326 / GHSA-c9cv-mq2m-ppp3
More information
Details
Summary
Three weaknesses in Nuxt's client-navigation URL handling, all reachable
from documented public APIs (
navigateToandreloadNuxtApp):SSR open redirect in
navigateTovia path-normalisation bypass.navigateTodecided whether a target was external by inspecting the rawinput with
hasProtocol(..., { acceptRelative: true }). Inputs such as/..//evil.com,/.//evil.com,/%2e%2e//evil.com, or/app/..//evil.comslipped past that check because they start with/, but WHATWG URL parsing then normalised them to theprotocol-relative pathname
//evil.com. The normalised value waswritten to the
Locationresponse header and into the<meta http-equiv="refresh">body of the SSR redirect page, so avictim's browser would resolve the redirect cross-origin to the
attacker's host.
Client-side script execution via
navigateTo({ open: ... }). Theclient-side early-open handler called
window.open(toPath, ...)withoutapplying the
isScriptProtocolcheck that gates the normalnavigateTopath. A target of
javascript:...(or another script-capable scheme)passed to
navigateTo(url, { open: { ... } })therefore executed in theapplication's origin instead of being rejected.
Open redirect in
reloadNuxtAppvia protocol-relative bypass.reloadNuxtApp({ path })rejects script-capable protocols by parsingthe path with
new URL(path, window.location.href)and checking theresolved
protocolagainstisScriptProtocol. Protocol-relative pathssuch as
//evil.comresolve to the current page's protocol (https:),which passes that check; the value is then assigned to
window.location.href, which the browser treats as a cross-originredirect. This is the same protocol-relative bypass family as (1), in
a different sink.
Impact
For (1), the practical risk is phishing or OAuth-code theft against any
Nuxt app that forwards user-controlled input (for example a
?next=query parameter on a login route) into
navigateToon the server. Theframework documents that
navigateToblocks external hosts unlessexternal: trueis passed, so maintainers commonly rely on it as thesafe path for post-login redirects.
For (2), any app that passes a user-controlled URL into
navigateTo(url, { open: { ... } })was vulnerable to reflected XSS inthe application's first-party origin.
For (3), any app that forwards user-controlled input into
reloadNuxtApp({ path })could be redirected cross-origin for phishingor OAuth-code theft, even on releases that already shipped the
isScriptProtocolguard added by #35115.Patches
Fixed in
nuxt@4.4.7and backported tonuxt@3.21.7. The three sinksare addressed by:
navigateTo:2cce6fb01f2dd5e7navigateTo({ open })script-protocol guard:3394716d)62fc32edreloadNuxtApp:e447a7936497d99dWorkarounds
navigateTo,for example reject any input where
new URL(target, 'http://localhost').pathnamestarts with//, oronly accept a known allow-list of paths.
allow-list (typically just
http:andhttps:) before passing it tonavigateTo({ open: ... }).//(or wherenew URL(path, window.location.href).host !== window.location.host)before passing to
reloadNuxtApp({ path }).References
Credits
Reported by Anthropic / Claude as
ANT-2026-S08HN6DHthrough Anthropic'scoordinated vulnerability disclosure programme.
The
reloadNuxtAppprotocol-relative bypass (sink 3) was independentlyreported by @alcls01111 via GitHub's
coordinated disclosure flow (
GHSA-w7fp-2cfv-4837), closed as aduplicate of this advisory.
Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:L/SA:NReferences