---
id: CVE-2026-49402
title: 'Deno: Command Injection via spawnSync & spawn on Windows'
summary: 'Deno: Command Injection via spawnSync & spawn on Windows'
severity: high
cvss: 8.1
cwe:
  - CWE-78
vendor: deno
product: deno
ecosystem: rust
affected:
  - deno < 2.7.10
patched:
  - deno 2.7.10
published: '2026-06-16'
updated: '2026-06-16'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-7xh3-mhg9-jcw8'
references:
  - url: 'https://github.com/denoland/deno/security/advisories/GHSA-7xh3-mhg9-jcw8'
  - url: 'https://github.com/advisories/GHSA-7xh3-mhg9-jcw8'
tags:
  - ghsa
  - rust
epss: 0.00445
epssPercentile: 0.38078
ingestedAt: '2026-06-29T14:31:47.713Z'
---

## Overview

## Summary

Deno's `node:child_process` 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, `child_process` 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:child_process";

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:child_process";

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 `child_process.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:child_process` 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`.

## Affected packages

- `deno < 2.7.10`

## Remediation

Upgrade to a patched release:

- `deno 2.7.10`
