Skip to content

chore(deps): update dependency nuxt to v3.21.7 [security] - #231

Open
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-nuxt-vulnerability
Open

chore(deps): update dependency nuxt to v3.21.7 [security]#231
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-nuxt-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Mar 7, 2025

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
nuxt (source) 3.0.03.21.7 age confidence

nuxt vulnerable to Cross-site Scripting in navigateTo if used after SSR

CVE-2024-34343 / GHSA-vf6r-87q4-2vjf

More information

Details

Summary

The navigateTo function attempts to blockthe javascript: protocol, but does not correctly use API's provided by unjs/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 parseURL function. This function will refuse to parse poorly formatted URLs. Parsing javascript:alert(1) returns null/"" for all values.

Next, the protocol of the URL is then checked using the isScriptProtocol function. 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 parseURL implementation, bypassing the isScriptProtocol checks.

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 URL constructor 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 Score: 5.1 / 10 (Medium)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Nuxt allows DOS via cache poisoning with payload rendering response

CVE-2025-27415 / GHSA-jvhm-gjrh-3h93

More information

Details

Summary

By sending a crafted HTTP request to a server behind an CDN, it is possible in some circumstances to poison the CDN cache and highly impacts the availability of a site.

It is possible to craft a request, such as https://mysite.com/?/_payload.json which will be rendered as JSON. If the CDN in front of a Nuxt site ignores the query string when determining whether to cache a route, then this JSON response could be served to future visitors to the site.

Impact

An attacker can perform this attack to a vulnerable site in order to make a site unavailable indefinitely. It is also possible in the case where the cache will be reset to make a small script to send a request each X seconds (=caching duration) so that the cache is permanently poisoned making the site completely unavailable.

Conclusion :

This is similar to a vulnerability in Next.js that resulted in CVE-2024-46982 (and see this article, in particular the "Internal URL parameter and pageProps" part, the latter being very similar to the one concerning us here.)

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

References

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/vue head components, re-exported by Nuxt) wrote its default-slot content to the innerHTML of 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:

<NoScript>{{ route.query.banner }}</NoScript>

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 than link, meta, noframes, or style implicitly 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 safe textContent path.

Affected versions

All currently supported versions of nuxt that ship the <NoScript> global component.

Patches

Fixed in nuxt@4.4.7 (commit 4b054e9d) and backported to nuxt@3.21.7 (commit 7fea9fd6). The fix escapes <NoScript> slot content with escapeHtml from @vue/shared and writes it to textContent rather than innerHTML. Slot content is now rendered as text; intentional markup inside <NoScript> is no longer parsed as HTML.

Workarounds

Until you can upgrade:

  • Do not interpolate untrusted input into <NoScript> slots. Replace <NoScript>{{ x }}</NoScript> with a static string, or sanitise / HTML-escape x at the source.
  • If you must render dynamic noscript content, write the tag yourself via useHead({ noscript: [{ textContent: escapedValue }] }) after escaping escapedValue.
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 Score: 2.3 / 10 (Low)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Nuxt: Reflected XSS in <NuxtLink> via unsanitised javascript: or data: URL

CVE-2026-53722 / GHSA-934w-87qh-qr26

More information

Details

Summary

<NuxtLink> did not validate the URL scheme of values bound to its to or href props before rendering them into the href attribute of the underlying <a> element. When an application binds attacker-controlled input (a query parameter, a CMS field, a user-supplied profile URL) to <NuxtLink :to> or :href, the attacker can supply a javascript: or vbscript: URL that is reflected verbatim into the rendered markup. Clicking the link executes the supplied script in the origin of the Nuxt application, resulting in reflected DOM-based cross-site scripting. A data:text/html,... payload reflected through the same sink does not execute in the application's origin but enables a same-tab phishing surface anchored to a legitimate application link.

The same value was exposed to consumers of the component's custom slot via the href and route.href props, so applications that re-bind those values to their own anchors were affected identically.

Unlike the previously reported navigateTo issue (CVE-2024-34343), the sink here is the rendered anchor itself; the existing isScriptProtocol checks in navigateTo and reloadNuxtApp are not on the code path. The onClick handler intentionally returns early for external links so the browser's native protocol-based navigation runs.

Affected component
  • File: packages/nuxt/src/app/components/nuxt-link.ts
  • Sink: h('a', { href: href.value, ... }) in the default render, plus the href / route.href props passed to the custom slot.
  • Broken check: external auto-detection treated any hasProtocol(path, { acceptRelative: true }) value as an "external link", then rendered the value directly as <a href> without rejecting script-capable protocols. There was no equivalent of the navigateTo isScriptProtocol(protocol) gate in this path.
Impact

Any Nuxt application that binds user-controlled values to <NuxtLink :to> / :href was vulnerable. Common shapes: profile-link rendering (<NuxtLink :to="user.website">), "share this" / "open in new tab" handlers that pass through a query parameter, CMS-driven landing pages that render <NuxtLink :to="cms.cta.url">, and marketplace listings that show seller-supplied links.

For javascript: / vbscript: the primitive is reflected XSS in the application's first-party origin (session theft for non-HttpOnly cookies, CSRF token theft, account takeover via DOM rewriting, credential harvesting via fake login overlays). For data:text/html,... the attacker gets a same-tab phishing surface anchored to a legitimate application link.

Patches

Fixed in nuxt@4.4.7 (commit 0103ce06) and backported to nuxt@3.21.7 (commit 53284043). The fix sanitises the resolved external href before it is passed to <a> or the custom slot: control characters and whitespace are stripped, leading view-source: prefixes are unwrapped, and any remaining script-capable scheme (per isScriptProtocol) causes the href to be replaced with an empty string.

Workarounds

Until you can upgrade, validate URLs at the source before binding them to <NuxtLink :to> / :href. For example, only accept paths that start with / (and not //), or run user-supplied URLs through new URL(value) and reject anything whose protocol is not in an allow-list (typically http: and https:).

Severity

  • CVSS Score: 5.1 / 10 (Medium)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

nuxt/nuxt (nuxt)

v3.21.7

Compare Source

3.21.7 is the a security hotfix release.

👉 make sure to check https://github.com/nuxt/nuxt/security/advisories to view open advisories resolved by this release.

👉 Changelog

compare changes

🩹 Fixes
  • nitro: Assign noSSR before deciding payload extraction (#​35108)
  • vite: Avoid filtering out dirs with shared prefix from allowDirs (#​35112)
  • nuxt: Use resolve from pathe for buildCache path boundary check (#​35111)
  • nuxt: Prevent sibling-directory traversal in test component wrapper (#​35110)
  • nitro: Pass event data to isValid in dev clipboard-copy listener (#​35109)
  • nuxt: Validate protocols in reloadNuxtApp path before reload (#​35115)
  • vite: Resolve vite clientServer with ssr: false (#​34959)
  • vite: Prefix public asset virtuals with null byte (38d330179)
  • nuxt: Handle missing payload in chunkError listener (#​35155)
  • vite: Close vite dev server on nuxt close (d007d7060)
  • kit,nuxt: Handle cancelling prompts to install packages (59821a5ca)
  • nuxt: Await in-lifght template generation when closing nuxt (#​35181)
  • webpack: Surface compilation errors when stats.toString is empty (71dccff2b)
  • kit: Improve TS extension stripping/substitutions (#​35233)
  • nuxt: Preserve .d.mts/.d.cts in resolveTypePaths (#​35235)
  • nuxt: Reject prototype-chain keys in the island registry (#​35205)
  • nitro: Gate chrome devtools workspace endpoint to local requests (#​35201)
  • nuxt: Escape props in <NuxtClientFallback> ssr output (#​35199)
  • nuxt: Apply isScriptProtocol guard to navigateTo open option (#​35206)
  • rspack,webpack: Require loopback host when missing same-origin signals (#​35200)
  • nuxt: Absolutely resolve defu in app config template (40bedf0db)
  • nuxt: Match route rules case-insensitively to mirror vue-router (3f3e3fa7b)
  • nuxt: Escape <NoScript> slot content (7fea9fd68)
  • nuxt: Block path-normalization open redirect in navigateTo (1f2dd5e78)
  • nuxt: Reject cross-origin paths in reloadNuxtApp (6497d99dd)
  • vite: Bind vite-node IPC to a permissioned filesystem socket (c293bf950)
  • nuxt: Reject script-capable protocols in <NuxtLink> href (53284043d)
  • nuxt: Clarify page and layout usage warnings (#​35184)
  • nuxt: Do not absolutely resolve defu (d11d7b1b5)
📖 Documentation
  • Edit for clarity and grammar (#​35214)
  • Add dedicated module dependencies page (#​35171)
🏡 Chore
  • Use execFileSync for safety in release scripts (9a455a658)
  • Assert there is always a tag (8da21fba8)
  • Fix type in test (bc2837125)
  • Fix lychee dynamic composable exclude (#​35119)
  • Add autofix action tag in comment (70eba297f)
  • Update renovate minimum release age (27a6821a1)
✅ Tests
  • Update test for js payload rendering (b51a80840)
  • Improve reliability of hmr test (0078499f0)
🤖 CI
  • Always run all tests for 4.x/3.x (0519c0ade)
  • Update to agentscan v1.8.0 (#​35120)
  • Automatically close PRs from automated accounts (#​35161)
  • Migrate from tibdex (6277aedcb)
  • Disable provenance-change enforcement in dependency-review (1d4910eed)
  • Add zizmor github actions check (#​35089)
❤️ Contributors

v3.21.6

Compare Source

3.21.6 is the next patch release.

👉 Changelog

compare changes

🩹 Fixes
  • nuxt: Prefer our own builder/server deps (#​35029)
  • nitro: Add json extension to payload cache items (#​35043)
  • nuxt: Handle errors fetching app manifest (#​35050)
  • nuxt: Preserve setPageLayout props on same-path navigation (#​35055)
  • vite: Don't strip buildAssetsDir from vite-node SSR ids (#​35040)
  • nuxt: Mark useLoadingIndicator properties as readonly (#​35062)
  • vite: Strip queries in css inline styles map (#​35067)
  • nuxt: Encode html-significant characters in external redirect body (#​35052)
  • nitro: Validate island request hash matches props (#​35077)
  • nitro: Use regexp to strip query (042b615e6)
  • nitro: Use statusCode for nitro v2 compatibility (82dcd6a31)
  • nuxt: Render component-less parent routes during client-side nav (#​35036)
  • nuxt: Run middleware for page islands (#​35092)
💅 Refactors
  • rspack,webpack: Extract same-origin check for dev middleware (#​35051)
📖 Documentation
  • Remove CSB, set node 22 and use steps for clarity (#​35066)
🏡 Chore
✅ Tests
  • Relax relative time assertion (256513eb0)
  • Move build assets dir fixture out of app/ (6d2ac69ff)
🤖 CI
❤️ Contributors

v3.21.5

Compare Source

3.21.5 is the next patch release.

👉 Changelog

compare changes

🔥 Performance
  • kit: Cache layer roots and short-circuit isIgnored relative (#​35015)
🩹 Fixes
  • nitro: Correct payload route rule for / + override ssr: true (#​34990)
  • nitro: Break recursive rendering deadlocks during prerender (#​34939)
  • vite: Drop redundant css link when entry styles are inlined (#​34950)
  • nuxt: Only force suspense remount after first resolve (#​34949)
  • kit: Read .env before resolving nuxt schema (#​34958)
  • nitro: Preserve serverHandlers array after nitro:config (#​34985)
  • vite: Only consider CSS inlined when styles are actually emitted (#​35006)
  • nuxt: Handle string presets in auto-imports (#​35013)
  • nuxt: Correct island transform for server pages and 'deep' mode (#​35005)
  • vite: Inline css for non-island children of server components (#​35001)
  • nuxt: Defer head DOM updates until page transition finishes (#​35016)
  • nuxt: Explicitly freeze head during island plugin phase (#​35010)
  • vite: Inline css imported from non-vue js modules (#​35020)
  • nitro: Remove unused middleware (fe857d36b)
📖 Documentation
  • Add warning about routing in server components (#​34994)
🏡 Chore
✅ Tests
  • Extract server components fixture + add some failing tests (#​34995)
  • Isolate buildDir per matrix project for shared fixtures (#​35007)
  • Split env testing into separate file (fd4019cf8)
  • Use 3.x style tsconfig (86625efad)
  • Use more 3.x style tsconfigs (4a9bde3f3)
  • Correct import path (133d5f6d7)
  • Update snapshots (9fc42f788)
❤️ Contributors

v3.21.4

Compare Source

v3.21.2

Compare Source

v3.21.1

Compare Source

3.21.1 is a regularly schedule patch release.

👉 Changelog

compare changes

🩹 Fixes
  • nuxt: Correct reference format of server builder (#​34177)
  • nuxt: Add status/statusText getters to NuxtError (#​34188)
  • schema: Add direnv and vendor to default ignore (#​34190)
  • nuxt: Focus hash links after navigation (#​34193)
  • nuxt: Exclude head runtime from unhead imports transform (#​34195)
  • kit: Include prereleases in semver satisfy check (#​34210)
  • nuxt: Watch server/ for builder:watch hook (#​34208)
  • nitro: Encode unicode paths in x-nitro-prerender header (#​34202)
  • nitro: Preserve error.message for fatal errors (#​34226)
  • Only enable dynamic imports when ts plugin (#​34205)
  • webpack: Use H3Error for 403 in dev server (#​34233)
  • nuxt: Ensure NuxtError extends Error type (#​34242)
  • vite: Use H3Error for 404 in dev server (#​34225)
  • nuxt: Add backwards compat for #app barrel export in keyed functions (#​34199)
  • nuxt: Track + re-add custom routes on hmr (#​32044)
  • nuxt: Keep vnode when leaving deeper nested route (#​33778)
  • vite: Prevent CSS flickering in dev mode after config changes (#​33856)
  • nuxt: Do not start view transition if there is no route (#​33723)
  • nuxt: Call deferHydration done on NuxtPage unmount (#​34152)
  • nuxt: Handle invalid datetime in ` (#​33992)
  • nuxt: Preserve middleware error status in 404 fallback (#​34148)
  • nitro: Do not augment nuxt/schema (#​34255)
  • nuxt: Cache manifest files to preserve buildId (#​34002)
  • nuxt: Don't decode query string in SSR context URL (#​34252)
  • nuxt: Allow specifying moduleDependencies by meta.name (#​34263)
  • nuxt: Resolve #components import mapping conflict for packages outside rootDir (#​34139)
  • vite,webpack: Use node.res to send 403/404 (#​34266)
  • nitro,nuxt: Align path encoding with vue-router (#​34265)
  • nitro: Augment nuxt/schema once more (9f5bb611d)
💅 Refactors
  • nuxt: Prefer genObjectKey to omit unnecessary quotes (#​34245)
  • nuxt: Use ComponentProps helper to extract layout props (#​34248)
📖 Documentation
  • Remove link to ai guide entirely (084b5d7f2)
  • Update roadmap dates (#​34166)
  • Clarify shared type context limitations for custom imports (#​34194)
  • Fix broken links (#​34223)
  • Document payload extraction for ISR/SWR routes (#​34222)
  • Update example of email validation (#​34247)
  • Add documentation for keyedComposables (#​34201)
🏡 Chore
✅ Tests
  • Vitest v4 compatibility (70e147b71)
  • Add runtime tests for deeply nested <NuxtPage> navigation (707a9dc44)
  • Resolve merge issues in tests (85abddc54)
❤️ Contributors

v3.21.0

Compare Source

3.21.0 is the next minor release.

Nuxt 4.3 and 3.21 bring powerful new features for layouts, caching, and developer experience – plus significant performance improvements under the hood.

📣 Some News

Extended v3 Support

Early this month, I opened a discussion to find out how the upgrade had gone from v3 to v4. I was really pleased to hear how well it had gone for most people.

Having said that, we're committed to making sure no one gets left behind. And so we will continue to provide security updates and critical bug fix releases beyond the previously announced end-of-life date of January 31, 2026, meaning Nuxt v3 will meet its end-of-life on July 31, 2026.

[!TIP]
As usual, today also brings a minor release for v3, with many of the same improvements backported from v4.3.

Preparing for Nuxt 5

We're closer than ever to the releases of Nuxt v5 and Nitro v3. In the coming weeks, the main branch of the Nuxt repository will begin receiving initial commits for Nuxt 5. However, it's still business as usual.

  • Continue making pull requests to the main branch
  • We'll backport changes to the 4.x and 3.x branches

Keep an eye out on the Upgrade Guide – we'll be adding details about how you can already start migrating your projects to prepare for Nuxt v4 with future.compatibilityVersion: 5.

🗂️ Route Rule Layouts

But that's enough about the future. We have a lot of good things for you today!

First, you can now set layouts directly in route rules using the new appLayout property (#​31092). This provides a centralized, declarative way to manage layouts across your application without scattering definePageMeta calls throughout your pages.

export default defineNuxtConfig({
  routeRules: {
    '/admin/**': { appLayout: 'admin' },
    '/dashboard/**': { appLayout: 'dashboard' },
    '/auth/**': { appLayout: 'minimal' }
  }
})

This might be useful for:

  • Admin panels with a shared layout across many routes
  • Marketing pages that need a different layout from the app

[!TIP]
Plus, you can pass props to layouts now! See the setPageLayout improvements below.

📦 ISR/SWR Payload Extraction

Payload extraction now works with ISR (incremental static regeneration), SWR (stale-while-revalidate) and cache routeRules (#​33467). Previously, only pre-rendered pages could generate _payload.json files.

This means:

  • Client-side navigation to ISR/SWR pages can use cached payloads
  • CDNs (Vercel, Netlify, Cloudflare) can cache payload files alongside HTML
  • Fewer API calls during navigation – data can be prefetched and served from the cached payload
export default defineNuxtConfig({
  routeRules: {
    '/products/**': { 
      isr: 3600, // Revalidate every hour
    }
  }
})

🧹 Dev Mode Payload Extraction

Related to the above, payload extraction now also works in development mode (#​30784). This makes it easier to test and debug payload behavior without needing to run a production build.

[!IMPORTANT]
Payload extraction works in dev mode with nitro.static set to true, or for individual pages which have isr, swr, prerender or cache route rules.

🚫 Disable Modules from Layers

When extending Nuxt layers, you can now disable specific modules that you don't need (#​33883). Just pass false to the module's options:

export default defineNuxtConfig({
  extends: ['../shared-layer'],
  // disable @nuxt/image from layer
  image: false,
})

🏷️ Route Groups in Page Meta

Route groups (folders wrapped in parentheses like (protected)/) are now exposed in page meta (#​33460). This makes it easy to check which groups a route belongs to in middleware or anywhere you have access to the route.

<script setup lang="ts">
// This page's meta will include: { groups: ['protected'] }
useRoute().meta.groups
</script>
export default defineNuxtRouteMiddleware((to) => {
  if (to.meta.groups?.includes('protected') && !isAuthenticated()) {
    return navigateTo('/login')
  }
})

This provides a clean, convention-based approach to route-level authorization without needing to add definePageMeta to every protected page.

🎨 Layout Props with setPageLayout

The setPageLayout composable now accepts a second parameter to pass props to your layout (#​33805):

export default defineNuxtRouteMiddleware((to) => {
  setPageLayout('admin', {
    sidebar: true,
    theme: 'dark'
  })
})
<script setup lang="ts">
defineProps<{
  sidebar?: boolean
  theme?: 'light' | 'dark'
}>()
</script>

🔧 #server Alias

A new #server alias provides clean imports within your server directory (#​33870), similar to how #shared works:

// Before: relative path hell
import { helper } from '../../../../utils/helper'

// After: clean and predictable
import { helper } from '#server/utils/helper'

The alias includes import protection – you can't accidentally import #server code from client or shared contexts.

🪟 Draggable Error Overlay

The development error overlay introduced in Nuxt 4.2 is now draggable and can be minimized (#​33695). You can:

  • Drag it to any corner of the screen (it snaps to edges)
  • Minimize it to a small pill button when you want to keep working
  • Your position and minimized state persist across page reloads

This is a quality-of-life improvement when you're iterating on fixes and don't want the overlay blocking your view.

https://github.com/user-attachments/assets/nuxt_4-3_error_demo.mp4

⚙️ Async Plugin Constructors

Module authors can now use async functions when adding build plugins (#​33619):

export default defineNuxtModule({
  async setup() {
    // Lazy load only when actually needed
    addVitePlugin(() => import('my-cool-plugin').then(r => r.default()))
    
    // No need to load webpack plugin if using Vite
    addWebpackPlugin(() => import('my-cool-plugin/webpack').then(r => r.default()))
  }
})

This enables true lazy loading of build plugins, avoiding unnecessary code loading when plugins aren't needed.

🚀 Performance Improvements

This release includes several performance optimizations for faster builds:

  • Hook filters - Internal plugins now use filters to avoid running hooks unnecessarily (#​33898)
  • SSR styles optimization - The nuxt:ssr-styles plugin is now significantly faster (#​33862, #​33865)
  • Layer alias transform - Skipped when using Vite (it handles this natively) (#​33864)
  • Route rules compilation - Route rules are now compiled into a client chunk using rou3, removing the need for radix3 in the client bundle and eliminating app manifest fetches (#​33920)

🎨 Inline Styles for Webpack/Rspack

The inlineStyles feature now works with webpack and rspack builders (#​33966), not just Vite. This enables critical CSS inlining for better Core Web Vitals regardless of your bundler choice.

⚠️ Deprecations

statusCodestatus, statusMessagestatusText

In preparation for Nitro v3 and H3 v2, we're moving to use Web API naming conventions (#​33912). The old properties still work but are deprecated in advance of v5:

- throw createError({ statusCode: 404, statusMessage: 'Not Found' })
+ throw createError({ status: 404, statusText: 'Not Found' })

🐛 Bug Fixes

Notable fixes in this release:

  • Fixed head component deduplication using key attribute (#​33958, #​33963)
  • Fixed async data properties not being reactive in Options API (#​34119)
  • Fixed useCookie unsafe number parsing during decode (#​34007)
  • Fixed NuxtPage not re-rendering when nested NuxtLayout has layouts disabled (#​34078)
  • Fixed client-side pathname decoding for non-ASCII route aliases (#​34043)
  • Fixed suspense remounting when navigating after pending state (#​33991)
  • Fixed clipboard copy in error overlay (#​33873)
  • Enabled allowArbitraryExtensions by default in TypeScript config (#​34084)
  • Added noUncheckedIndexedAccess to server tsconfig for safer typing (#​33985)

[!IMPORTANT]
Enabling noUncheckedIndexedAccess in the Nitro server TypeScript config improves type safety but may surface new type errors in your server code. This change was necessary because Nuxt's app context performs type checks on server routes (learn more).

While we recommend keeping this enabled for better type safety, you can disable it if needed:

export default defineNuxtConfig({
  nitro: {
    typescript: {
      tsConfig: {
        compilerOptions: {
          noUncheckedIndexedAccess: false
        }
      }
    }
  }
})

Note that disabling this may allow type errors to slip through that could cause runtime issues with indexed access.

📚 Documentation

  • Improved module author guides with clearer structure (#​33803)
  • Added MCP setup instructions for Claude Desktop (#​33914)
  • Added layers directory documentation (#​33967)
  • Added Deno package manager examples (#​34070)
  • Clarified type-checking context limitations for server routes (#​33964)

🎉 Nuxt 3.21.0

Alongside v4.3.0, we're releasing Nuxt v3.21.0 with many of the same improvements backported to the 3.x branch. This release includes:

  • All the same features: Route rule layouts, ISR payload extraction, layout props with setPageLayout, #server alias, draggable error overlay, and more
  • All performance improvements: SSR styles optimization, hook filters, and route rules compilation
  • Module disabling: Disable layer modules by setting options to false
  • Critical bug fixes: Async data reactivity in Options API, useCookie number parsing, head component deduplication, and more

✅ Upgrading

Our recommendation for upgrading is to run:

npx nuxt@latest upgrade --dedupe --channel=v3

This will deduplicate your lockfile and help ensure you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.

[!TIP]
Check out our upgrade guide if upgrading from an older version.

👉 Changelog

compare changes

🚀 Enhancements
  • kit: Support async constructor for adding plugins (#​33619)
  • kit: Export Nuxt major version type (#​33700)
  • schema: Add #server alias for server directory imports (#​33870)
  • schema: Hoist nitro crossws types (6ff79ea6c)
  • nitro,nuxt: Compile route rules into client chunk (#​33920)
  • nuxt: Allow disabling modules by setting module options to false (#​33883)
  • kit: Allow specifying moduleDependencies as an async function (#​33504)
  • nuxt: Support appLayout in route rules (#​31092)
  • nuxt: Add route groups to page meta (#​33460)
  • nuxt: Enable payload extraction for ISR/SWR routes (#​33467)
  • nuxt: Allow updating props with setPageLayout (#​33805)
  • nuxt: Enable dragging and minimizing for error overlay (#​33695)
  • nitro,nuxt: Add support for payload extraction in dev (#​30784)
  • rspack,webpack: Add inline styles (#​33966)
  • kit: Add forward-compatible nitro types (#​34036)
🔥 Performance
  • nuxt: Do not init layer alias transform when using vite (#​33864)
  • vite: Add hook filters for ssr styles plugin (#​33865)
  • vite: Optimize nuxt:ssr-styles plugin (#​33862)
  • nuxt: Use filter for vfs plugin load (5bd8e81ed)
  • nuxt,vite: Use filters to avoid running hooks unnecessarily (e762a1e20)
  • nuxt,vite: Add more filters to internal plugins (#​33898)
🩹 Fixes
  • kit: Normalize local layer paths with trailing slashes (#​33858)
  • nuxt: Avoid overwriting multiple head input in island handler (#​33849)
  • nuxt: Update meta instead of calling router.replace in page hmr (#​33897)
  • nuxt: Don't call page:loading:end in cache if already called (fbbe10133)
  • vite: Add error handling for parsing NUXT_VITE_NODE_OPTIONS (8abb7ef5b)
  • nuxt: Do not skip middleware when appMiddleware references invalid key (ed8bb68c5)
  • nitro: Clipboard copy in error overlay (#​33873)
  • webpack,rspack: Resolve deep imports in virtual files (#​33927)
  • webpack: Disable async chunks in dev mode (c4bfd0a49)
  • webpack: Correctly evaluate sourcemap name (93e3d92b9)
  • nuxt: Handle node10 resolution for nuxt/meta (b748840bc)
  • nuxt: Do not early return if component priorities conflict (#​33955)
  • nuxt: Use key for tag deduplication in <Head> component (#​33958)
  • schema,vite: Resolve build.transpile when initialising vite (#​33868)
  • nuxt,rspack,webpack: Inject module identifiers for webpack builders (#​33962)
  • nuxt: Add key to head components for proper deduplication (#​33963)
  • nitro: Check prettyResponse.body type before error overlay (#​33977)
  • nuxt: Don't URI-encode static route paths (#​33990)
  • nuxt: Skip internal stub routes from prerender (#​34001)
  • kit,schema: Align module onUpgrade arguments with types (#​33988)
  • nuxt: Handle unsafe number parsing in useCookie decode (#​34007)
  • nuxt: Do not externalise rou3 (7da94e8c3)
  • nitro: Add noUncheckedIndexedAccess to server tsconfig (#​33985)
  • nuxt: Update global reference to globalThis in useRequestFetch (#​33976)
  • vite: Configure hmr port for server build (#​33929)
  • kit: Add forward compatible nitro v3 types (#​34053)
  • nitro,nuxt: Do not import nitro deps in builders (#​34054)
  • nitro: Add h3 types to auto-imports (#​34035)
  • schema: Add some more directories to ignore (9cb9a19dd)
  • nitro: Also augment nuxt/schema (9b40196a6)
  • nuxt: Make asyncData properties reactive in Options API (#​34119)
  • nuxt: Rerender NuxtPage when nested NuxtLayout has explicitly disabled layouts (#​34078)
  • nuxt,schema: Clean up types (5ce351d0f)
  • nuxt: Allow user augmentation of runtime config (dd30410cb)
  • kit,nitro: Enable allowArbitraryExtensions by default (#​34084)
  • nuxt: Decode client-side pathname for non-ASCII route aliases (#​34043)
  • nuxt: Force remount suspense when navigating after pending (#​33991)
  • nuxt: Add documentation link to server builder error message (#​34122)
  • nuxt: Validate placeholder/fallback tags + warn about placeholder/fallback props (f7912d3f3)
  • nuxt: Force flush useAsyncData debounced execute post watcher flush (#​34125)
  • nitro: Process isr/swr/cache keys (7f2bf4d13)
  • nuxt: Add typeFrom support for imports.d.ts template exports (#​34135)
  • nuxt: Ensure we inline styles for hydrate-never components (#​34132)
?

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 3 times, most recently from 1ab3483 to b2501f7 Compare March 17, 2025 14:11
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from b2501f7 to 57729a8 Compare April 1, 2025 08:23
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 57729a8 to fb7208b Compare April 8, 2025 15:51
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from fb7208b to 6c23c8d Compare April 24, 2025 13:04
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 6c23c8d to 0dcf426 Compare May 19, 2025 15:28
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from cbd2a8e to 5dbed3b Compare June 4, 2025 07:22
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 5dbed3b to 10a5008 Compare June 22, 2025 12:02
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 10a5008 to d335ab2 Compare July 2, 2025 20:05
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from 72addf9 to 1b9a047 Compare August 13, 2025 12:47
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.12.4 [security] chore(deps): update dependency nuxt to v3.16.0 [security] Aug 13, 2025
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 1b9a047 to 978e89a Compare August 19, 2025 11:59
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 978e89a to f630878 Compare August 31, 2025 12:06
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from f630878 to 19c4266 Compare September 25, 2025 17:42
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 19c4266 to 11c7539 Compare October 15, 2025 22:51
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.16.0 [security] chore(deps): update dependency nuxt to v3.12.4 [security] Oct 15, 2025
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 11c7539 to b1847cb Compare October 21, 2025 19:35
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from b1847cb to dfe4e0e Compare November 10, 2025 22:59
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from dfe4e0e to 96200a8 Compare November 18, 2025 23:09
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 96200a8 to c4391c1 Compare December 3, 2025 16:38
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from c4391c1 to b1cf454 Compare December 31, 2025 18:44
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from b1cf454 to 588398b Compare January 8, 2026 21:03
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from 427abdf to 5e832b4 Compare January 23, 2026 21:15
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 5e832b4 to 9698d9c Compare February 2, 2026 15:48
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from 4171025 to 81bcf42 Compare February 17, 2026 18:34
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.12.4 [security] - autoclosed chore(deps): update dependency nuxt to v3.12.4 [security] Mar 30, 2026
@renovate renovate Bot reopened this Mar 30, 2026
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 3 times, most recently from 4ded004 to b460fa5 Compare April 1, 2026 21:52
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from b460fa5 to f5688fb Compare April 8, 2026 15:57
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.12.4 [security] chore(deps): update dependency nuxt to v3.12.4 [security] - autoclosed Apr 27, 2026
@renovate renovate Bot closed this Apr 27, 2026
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.12.4 [security] - autoclosed chore(deps): update dependency nuxt to v3.12.4 [security] Apr 27, 2026
@renovate renovate Bot reopened this Apr 27, 2026
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from f5688fb to 8a7b481 Compare April 27, 2026 20:09
@socket-security

socket-security Bot commented Apr 27, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 8a7b481 to 5da17e0 Compare April 29, 2026 17:43
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 5da17e0 to 642667f Compare May 12, 2026 14:26
@socket-security

socket-security Bot commented May 12, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednuxt@​3.0.0 ⏵ 3.21.1197 +2100 +20100 +2594100

View full report

@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 642667f to c840190 Compare May 18, 2026 13:58
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from a6db30d to fd3d833 Compare June 2, 2026 00:12
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from fd3d833 to 7b44e35 Compare June 11, 2026 10:06
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from a84e222 to 4c1abc4 Compare July 17, 2026 03:20
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from d471d0e to 82a42c3 Compare July 24, 2026 22:52
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from 82a42c3 to 42c2a1e Compare July 30, 2026 19:52
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch 2 times, most recently from 74dff48 to a3d7d79 Compare August 14, 2026 22:00
@renovate
renovate Bot force-pushed the renovate/npm-nuxt-vulnerability branch from a3d7d79 to b9ce56c Compare August 26, 2026 10:46
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v3.12.4 [security] chore(deps): update dependency nuxt to v3.21.7 [security] Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants