CVE-2026-49402: Deno: Command Injection via spawnSync & spawn on Windows
Summary
Deno's node:childprocess implementation provided an escapeShellArg() helper used when callers passed shell: true to spawn / spawnSync / exec and friends. On Windows, the helper failed to quote arguments that contained cmd.exe metacharacters such as &, |, <, >, ^, !, (, ), and did not neutralize % (which cmd.exe expands even inside double-quoted strings). An attacker who controlled any portion of an argument passed to such a call could inject arbitrary additional commands into the spawned cmd.exe invocation.
This was the Windows counterpart to CVE-2026-27190, which fixed the same class of bug in the Unix branch of escapeShellArg.
Details
On Windows, childprocess with shell: true ran the command via cmd.exe /d /s /c "<command line>". Deno assembled that command line by joining the program name and each argument through escapeShellArg().
The vulnerable check was:
ts // If no special characters, return as-is if (!/[\s"\\]/.test(arg)) { return arg; }
The regex covered only whitespace, double-quote, and backslash. Any argument containing cmd.exe-significant characters but none of those three was returned unquoted and therefore interpreted by the shell. The most straightforward exploit chained commands with &:
js import { spawnSync } from "node:childprocess";
spawnSync("echo", ["test&calc.exe"], { shell: true, encoding: "utf-8" });
The reporter confirmed this launched calc.exe on Windows 11 with Deno 2.7.5. The same shape worked for |, <, >, ^, !, (, and ).
A secondary defect existed even when arguments were quoted: cmd.exe expands %FOO% environment-variable references inside double-quoted strings. Without either doubling % or rejecting it, an argument like "%USERPROFILE%" leaked environment data into the command line.
Proof of concept
From the report, run on Windows with Deno < 2.7.10:
js import { spawnSync } from "node:childprocess";
const maliciousInput = "test&calc.exe"; const result = spawnSync("echo", [maliciousInput], { shell: true, encoding: "utf-8", }); console.log(result);
Observed: calc.exe launched as a side effect of the echo call.
Impact
Any Deno program on Windows that called childprocess.spawn / spawnSync / exec (or any shell helper that funneled through escapeShellArg) with shell: true and incorporated untrusted input into an argument was exposed to arbitrary command execution in the context of the Deno process. The CVSS vector treated this as network-reachable / high-complexity because the typical exposure path was a Deno service accepting external input and forwarding it to a shelled-out subprocess.
Not affected:
- Calls without shell: true (the default), which executed the program directly via CreateProcess without cmd.exe interpretation. - Unix platforms, which used the single-quote branch of escapeShellArg and were already fixed under CVE-2026-27190. - Callers that built command strings themselves and passed them as a single string with shell: true — those were the caller's responsibility and were never sanitized by Deno.
Workarounds
Users on unpatched versions could mitigate by:
- Avoiding shell: true in node:childprocess calls on Windows. - Building the argv directly and invoking the program without a shell. - Filtering or rejecting any externally-supplied argument values that contained cmd.exe metacharacters (& | < > ^ ! ( ) %) before passing them to spawn / spawnSync / exec.
Other sources
Deno is a JavaScript, TypeScript, and WebAssembly runtime. Prior to 2.7.10, Deno's node:childprocess implementation provided an escapeShellArg() helper used when callers passed shell: true to spawn / spawnSync / exec and friends. On Windows, the helper failed to quote arguments that contained cmd.exe metacharacters and did not neutralize % (which cmd.exe expands even inside double-quoted strings). An attacker who controlled any portion of an argument passed to such a call could inject arbitrary additional commands into the spawned cmd.exe invocation. This vulnerability is fixed in 2.7.10.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
rust/denoto a version that resolves this vulnerability.Fixed in 2.7.10 - Upgrade
Upgrade
Denoto a version that resolves this vulnerability.Fixed in 2.7.10 - Compensating control
On Windows, mitigate until upgraded by either (a) rejecting/filtering any externally supplied argument values that contain cmd.exe metacharacters `& | < > ^ !` (and also ensure `(` and `)` are rejected as part of the same set), or (b) refusing to call `node:child_process.spawn` / `spawnSync` / `exec` with `shell: true` when untrusted input is incorporated into any argument.
- Compensating control
On Windows, mitigate until upgraded by rejecting inputs that include `%` (because cmd.exe expands `%FOO%` environment-variable references even inside double-quoted strings).
Event History
Frequently Asked Questions
What is the severity of CVE-2026-49402?
CVE-2026-49402 has a high severity rating of 8.1.
What type of vulnerability is CVE-2026-49402?
CVE-2026-49402 is categorized as an OS Command Injection vulnerability.
How do I fix CVE-2026-49402?
To mitigate CVE-2026-49402, ensure that you sanitize and properly quote arguments passed to shell commands in your Deno applications.
What is the impact of CVE-2026-49402?
The impact of CVE-2026-49402 can lead to command injection vulnerabilities that allow an attacker to execute arbitrary commands on the affected system.
In which software is CVE-2026-49402 found?
CVE-2026-49402 is found in the Rust-based Deno software.