FlawOpen

flawopen.com/Teardowns/cve-2024-27980-nodejs-windows-batch-injection

● CVE-2024-27980 · CVSS 8.1 · High
FlawOpen Security Research

CVE-2024-27980: Node.js Windows Command Injection

On Windows, spawn() and spawnSync() could allow command injection when launching batch files, even without the shell option.

💡 Plain English Explainer (ELI5)

Imagine a program handing arguments to a batch file, while Windows needs a command interpreter to run that file. The interpreter can read argument text as command syntax. Node.js fixed this by refusing direct batch-file launches instead of guessing a safe escape for every argument.

Core Concepts & Subsystem Terms

child_process.spawn()
Node.js asynchronous API that starts a process from an executable and an argument list.
Batch file
A .bat or .cmd file interpreted by the Windows shell, rather than a regular executable with universal argv parsing.
Shell metacharacter
A character whose meaning depends on the command interpreter and may change command structure.
EINVAL
The error code Node.js uses to reject unsafe direct batch-file spawning.

Framework mappings

  • CWE reference for the weakness described in this guide: CWE-77

Root Cause Analysis

On Windows, .bat and .cmd files are interpreted by a command shell; their arguments cannot always be escaped unambiguously. Node.js reported that a malicious command-line argument could inject commands through child_process.spawn() and spawnSync() even when shell was not enabled. The upstream patch detects a .bat or .cmd suffix case-insensitively and returns EINVAL before uv_spawn(). It does not implement sanitizeBatchArg(), and it does not make shell: true safe. A later advisory identified an incomplete fix for other batch-file extensions (CVE-2024-36138); use an updated release that includes that follow-up fix.

Step-by-Step Attack Flow

Step 1

Application calls the process API

On Windows, an application calls child_process.spawn() or spawnSync() to launch a .bat or .cmd file with arguments that may contain external data.

Step 2

Target is a batch file

Batch files follow shell parsing rules; an argument array does not by itself prevent metacharacter interpretation.

Step 3

Windows interprets the arguments

The vulnerable behavior could let an argument be interpreted as command syntax even when shell: false.

Step 4

Node.js rejects direct spawning

The patch returns EINVAL for direct .bat/.cmd spawning. CVE-2024-36138 found a remaining gap for other extensions, so install a release containing both fixes.

Source Code: Flaw vs. Secure Implementation

UNPATCHED FLAW
// Excerpt from src/process_wrap.cc before the security patch
node::Utf8Value file(env->isolate(), file_v);
options.file = *file;

// The filename was passed to uv_spawn() without rejecting batch files.
HARDENED SECURE PATCH
// Excerpt from the upstream CVE-2024-27980 patch
node::Utf8Value file(env->isolate(), file_v);
options.file = *file;

// Batch arguments cannot always be escaped unambiguously.
if (IsWindowsBatchFile(options.file))
  err = UV_EINVAL;

if (err == 0) {
  err = uv_spawn(env->event_loop(), &wrap->process_, &options);
  wrap->MarkAsInitialized();
}

Engineering & System Hardening Checklist

Sources