Advisory · CVE-2026-103473
Deno on Windows lets attackers smuggle commands past node:child_process shell quoting
Deno 2.7.0 through 2.9.7 on Windows escapes shell arguments for the wrong shell type, so an argument containing a quote can break out of quoting and run arbitrary OS commands.
- Vendor
- denoland
- Product
- Deno
- Identifier / CWE
- CVE-2026-103473
CWE-78 - Action timing
- Immediate
Explain it like I’m five
Deno wraps arguments in quotes before handing them to Windows shells, but it used the wrong quoting rules for the shell that actually runs. A crafty argument can slip a quote past the wrapper and turn the rest of the line into a new command.
- 01Untrusted argument
Application code passes attacker-influenced input as an argument to node:child_process with the shell option enabled on Windows.
- 02Wrong escaping rules
escapeShellArg picks its quoting rules from process.platform, but a different shell actually runs the command, so the escaping never matched the parser it was aimed at.
- 03Quoting breaks early
On the default cmd.exe path, a quote inside the argument ends the quoted region early and the remainder is parsed as command syntax; with powershell.exe, the cmd.exe-style quoting lets PowerShell expand subexpressions inside double quotes.
- 04Command runs
The injected command executes with the privileges of the Deno process.
What happened
Deno versions 2.7.0 through 2.9.7 on Windows contain a command injection vulnerability in node:child_process. The shell-argument escaper selected its quoting rules from process.platform, while a separate code path resolved which shell would actually run the command. The two never agreed: on the default Windows path, arguments were handed to cmd.exe with \" escaping, a C runtime convention that cmd.exe does not honor, so an argument containing a quote ended the quoted region early and the rest was parsed as command syntax. With a custom shell: "powershell.exe", the command was built with cmd.exe quoting and then handed to PowerShell, which expands $() inside double quotes.
Attackers can inject OS commands by passing untrusted arguments with the shell option, achieving arbitrary command execution with Deno process privileges. The vulnerability is rated critical at CVSS 9.2.
The fix (denoland/deno PR #36772) resolves the shell before building the command and escapes against the grammar that shell actually parses. It was not yet present in a released Deno version as of September 16, 2026 (release 2.9.7).
What to do
- Identify Windows hosts and CI runners running Deno 2.7.0 through 2.9.7.
- Watch the Deno release notes and upgrade to the first release that includes the quoting fix from PR #36772.
- Audit Node-compat code paths that call
child_processwithshell: trueand pass untrusted input as arguments. - Prefer passing arguments as arrays without the shell option where the call site allows it.
- Review process execution logs on affected hosts for unexpected child processes spawned under Deno.
Management note
This is a critical, remotely reachable command injection in a widely used runtime’s Node compatibility layer. The exploit condition is ordinary application behavior (shelling out with arguments), so exposure is likely wider than the call sites you remember. Treat the upgrade as urgent and pair it with a review of services that build shell commands from request data.