argv to a .cmd shim is re-parsed by cmd.exe — untrusted text becomes commands
args quoting · case
Affectsnode, cmd, windows
Fails assilent
Mechanismcmd reparse
Safe fixstdin payload
Symptom
Section titled “Symptom”A tool passes user text (a prompt, a title, a model name) as an argument to a CLI installed as a .cmd shim on Windows. Text containing an ampersand, a pipe, or even a bare newline executes EXTRA COMMANDS at the tool’s privileges.
// codex is codex.cmd on Windows; the .cmd launch goes through cmd.exe,// which re-parses the whole line:spawn("codex.cmd", ["exec", userText]);// userText = "hello & calc.exe" → calc runs.// Newlines work too: cmd treats CR/LF as command boundaries.Launching a .cmd/.bat file ALWAYS involves cmd.exe, and cmd re-parses the assembled command line — argv boundaries do not survive. Any untrusted byte sequence containing cmd metacharacters (& | < > ^ % and CR/LF) escapes the argument and becomes command syntax. This is the same mechanism Node hardened with CVE-2024-27980 (EINVAL on naive .cmd spawn), but wrappers that route via ComSpec re-open it.
Workaround
Section titled “Workaround”- Put untrusted payloads on STDIN, never argv (the referenced fix moves the prompt to stdin “-”).
- Before any ComSpec fallback, reject or strip command-separator bytes including CR/LF (the second referenced commit adds newlines to the separator set).