fix(code-review, windows): escape args for cmd.exe in review runner#2006
fix(code-review, windows): escape args for cmd.exe in review runner#2006AnExiledDev wants to merge 2 commits into
Conversation
…sedStdin On Windows, spawn() with shell: true routes through cmd.exe, which concatenates args with spaces and loses multi-word argument boundaries (Node.js DEP0190). The review prompt — a multi-line string with spaces — was split into separate tokens, causing codex exec to fail with "unexpected argument 'are' found". Add escapeArgForCmd() that wraps args containing spaces or cmd.exe metacharacters in double quotes before passing them to spawn(). This preserves argument boundaries through the cmd.exe re-parse while keeping shell: true for .cmd shim resolution. Closes AgentWrapper#2003
Greptile SummaryThis PR fixes a Windows-only bug where
Confidence Score: 5/5The change is a narrow, well-scoped Windows arg-escaping fix with no impact on POSIX paths and a clear paper trail of the cmd.exe quoting convention being applied. The only call site passes No files require special attention; both changed files are self-contained.
|
| Filename | Overview |
|---|---|
| packages/core/src/code-review-manager.ts | Adds escapeArgForCmd() and applies it in execFileWithClosedStdin when shell:true on Windows; the guard is correct for the current boolean-only call site but doesn't narrow to cmd.exe when shell is a string. |
| packages/core/src/tests/code-review-manager.test.ts | Six new tests cover escapeArgForCmd in isolation and replicate the platform-guard branch logic manually; the integration test for execFileWithClosedStdin does not invoke the real function. |
Sequence Diagram
sequenceDiagram
participant RCR as runCodexCodeReview
participant EWS as execFileWithClosedStdin
participant EA as escapeArgForCmd
participant SP as spawn (Node.js)
participant CMD as cmd.exe (Windows)
participant CX as codex exec
RCR->>EWS: "file="codex", args=[...prompt], shell=isWindows()"
EWS->>EWS: "options.shell && isWindows()?"
alt Windows (shell: true)
EWS->>EA: map(escapeArgForCmd) over args
EA-->>EWS: args with spaces/metacharacters wrapped in ""
EWS->>SP: "spawn("codex", escapedArgs, {shell: true})"
SP->>CMD: cmd.exe /d /s /c codex exec ... "full prompt"
CMD->>CX: receives prompt as single token
else POSIX (shell: false)
EWS->>SP: "spawn("codex", args, {shell: false})"
SP->>CX: args passed directly, no shell re-parse
end
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
packages/core/src/code-review-manager.ts:87
**cmd.exe escaping applied even when shell is not cmd.exe**
`options.shell` is typed as `boolean | string`. When it is a truthy string such as `"powershell"` or an absolute path to `pwsh.exe`, the guard `options.shell && isWindows()` still fires and applies cmd.exe-specific `""` doubling, but the actual subprocess shell will be PowerShell — which has different quoting rules. The escaping would be wrong in that scenario.
The current call site passes `shell: isWindows()` (always a boolean), so no bug today, but the function signature accepts strings and a future caller could trigger this silently.
Reviews (2): Last reviewed commit: "fix: add % to cmd.exe metachar regex and..." | Re-trigger Greptile
Include % in the escapeArgForCmd detection regex so args containing percent signs get double-quoted. Note: cmd.exe %VAR% expansion cannot be fully suppressed inside double quotes, but the review prompt and file-path args never contain literal % in practice. Add platform-guard tests using Object.defineProperty(process, 'platform') to verify the isWindows() branch in execFileWithClosedStdin fires correctly on both platforms.
Summary
shell: truebreaking review prompt argument passing on Windows by escaping args forcmd.exeinexecFileWithClosedStdinspawn()withshell: trueroutes throughcmd.exe, which concatenates args with spaces — splitting the multi-word review prompt into separate CLI tokens.codex execthen fails withunexpected argument 'are' foundescapeArgForCmd()that wraps args containing spaces orcmd.exemetacharacters (",&,|,<,>,^) in double quotes so they survive thecmd.exere-parse, while keepingshell: truefor.cmdshim resolutionCloses #2003
Test plan
escapeArgForCmd: simple passthrough, space wrapping, double-quote escaping, metacharacter handling, empty string, multi-line promptprepareGitReviewerWorkspaceis unrelated — Windows HOME path resolution)codex execreceives the full review prompt as a single argument