Skip to content

Process: fix Windows .cmd spawn EINVAL#29759

Merged
Takhoffman merged 3 commits intoopenclaw:mainfrom
icesword0760:fix/windows-cmd-spawn-einval
Mar 2, 2026
Merged

Process: fix Windows .cmd spawn EINVAL#29759
Takhoffman merged 3 commits intoopenclaw:mainfrom
icesword0760:fix/windows-cmd-spawn-einval

Conversation

@icesword0760
Copy link
Contributor

@icesword0760 icesword0760 commented Feb 28, 2026

Summary

  • Fix Windows spawn of .cmd/.bat (npm/pnpm) by running via cmd.exe to avoid EINVAL.
  • Add conservative cmd.exe argument hardening when the wrapper is required.
  • Avoid token-like PAT strings in diagnostics tests to prevent accidental secret scanning.

Test plan

  • pnpm test exec.test.ts

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d09f5aa8b5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +22 to +24
if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(arg)) {
throw new Error(
`Unsafe Windows cmd.exe argument detected: ${JSON.stringify(arg)}. ` +

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Permit literal % in cmd.exe-wrapped arguments

escapeForCmdExe now throws on any % (and &) when invoking .cmd/.bat via cmd.exe, but some existing Windows call paths pass user text as a single JSON argument (for example docsSearchCommand builds --args <payload> from the query in src/commands/docs.ts:174-178 and then runs via pnpm.cmd/npx.cmd). Queries like "100%" or "A & B" become hard failures (Unsafe Windows cmd.exe argument detected) before the subprocess starts, which is a functional regression from prior behavior for legitimate inputs.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

Fixes Windows EINVAL errors when spawning .cmd/.bat files (like npm.cmd, pnpm.cmd) by wrapping execution via cmd.exe with conservative argument hardening.

  • Detects Windows batch commands and routes them through cmd.exe with /d /s /c flags
  • Implements escapeForCmdExe() to safely quote arguments and reject dangerous cmd.exe metacharacters (&|<>^%\r\n)
  • Uses "" to escape quotes inside quoted strings (cmd.exe convention)
  • Applies fix to both runExec() and runCommandWithTimeout()

Issue found: runExec() is missing windowsVerbatimArguments: true when using the cmd.exe wrapper, which could cause Node.js to apply conflicting quote escaping on top of the cmd.exe-style escaping

Confidence Score: 2/5

  • This PR has a critical bug in runExec() that needs fixing before merge
  • The Windows cmd.exe wrapper logic is well-designed with conservative security hardening, but runExec() is missing windowsVerbatimArguments: true, which causes Node.js to apply conflicting quote escaping. This will result in malformed command lines and potential runtime failures. The fix in runCommandWithTimeout() is correct, but the bug in runExec() is critical enough to block merging
  • src/process/exec.ts needs the windowsVerbatimArguments: true fix in the runExec() function

Last reviewed commit: d09f5aa

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +91 to +96
const { stdout, stderr } = isWindowsBatchCommand(resolvedCommand)
? await execFileAsync(
process.env.ComSpec ?? "cmd.exe",
["/d", "/s", "/c", buildCmdExeCommandLine(resolvedCommand, args)],
options,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing windowsVerbatimArguments: true when spawning via cmd.exe wrapper

without this, Node.js will apply its own Windows quoting (using \" escapes) on top of the cmd.exe-style quoting (using "" escapes) from buildCmdExeCommandLine, causing malformed command lines

Suggested change
const { stdout, stderr } = isWindowsBatchCommand(resolvedCommand)
? await execFileAsync(
process.env.ComSpec ?? "cmd.exe",
["/d", "/s", "/c", buildCmdExeCommandLine(resolvedCommand, args)],
options,
)
const { stdout, stderr } = isWindowsBatchCommand(resolvedCommand)
? await execFileAsync(
process.env.ComSpec ?? "cmd.exe",
["/d", "/s", "/c", buildCmdExeCommandLine(resolvedCommand, args)],
{ ...options, windowsVerbatimArguments: true },
)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/process/exec.ts
Line: 91-96

Comment:
missing `windowsVerbatimArguments: true` when spawning via cmd.exe wrapper

without this, Node.js will apply its own Windows quoting (using `\"` escapes) on top of the cmd.exe-style quoting (using `""` escapes) from `buildCmdExeCommandLine`, causing malformed command lines

```suggestion
    const { stdout, stderr } = isWindowsBatchCommand(resolvedCommand)
      ? await execFileAsync(
          process.env.ComSpec ?? "cmd.exe",
          ["/d", "/s", "/c", buildCmdExeCommandLine(resolvedCommand, args)],
          { ...options, windowsVerbatimArguments: true },
        )
```

How can I resolve this? If you propose a fix, please make it concise.

@openclaw-barnacle openclaw-barnacle bot added extensions: diagnostics-otel Extension: diagnostics-otel and removed extensions: diagnostics-otel Extension: diagnostics-otel labels Feb 28, 2026
@Takhoffman Takhoffman force-pushed the fix/windows-cmd-spawn-einval branch from 44dd446 to de82564 Compare March 2, 2026 13:49
@Takhoffman Takhoffman merged commit 6e008e9 into openclaw:main Mar 2, 2026
9 checks passed
@Takhoffman
Copy link
Contributor

PR #29759 - Process: fix Windows .cmd spawn EINVAL (#29759)

Merged via squash.

  • Merge commit: 6e008e9
  • Verified: pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts
  • Changes made:
    • Kept the .cmd/.bat cmd.exe wrapper approach in src/process/exec.ts while preserving current main behavior that routes npm/npx through node + npm-cli.js.
    • Added windowsVerbatimArguments: true for the cmd wrapper path in runExec to avoid quote mangling.
    • Added targeted Windows wrapper tests in src/process/exec.windows.test.ts and aligned them with current npm shim behavior.
  • Why these changes were made:
    • The PR hit a clean-merge conflict with newer Windows spawn logic on main; the resolved version keeps the intended EINVAL fix without regressing recent npm/npx handling.
    • The extra test coverage closes the previous gap around wrapper invocation and argument handling.
  • Changelog: CHANGELOG.md updated=false required=false opt_out=true (workstream canonicalization run)

Thanks @icesword0760!

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: de82564fd0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


function escapeForCmdExe(arg: string): string {
// Reject cmd metacharacters to avoid injection when we must pass a single command line.
if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(arg)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow % and & in wrapped cmd.exe arguments

escapeForCmdExe now throws for any argument containing % or &, but several Windows call paths pass user text through argv (for example docsSearchCommand serializes the raw query into the --args JSON payload before invoking pnpm.cmd). Inputs like 100% or A & B therefore fail before the subprocess even starts, which is a functional regression for legitimate queries and command arguments; these characters need escaping in the wrapper path rather than blanket rejection.

Useful? React with 👍 / 👎.

hanqizheng pushed a commit to hanqizheng/openclaw that referenced this pull request Mar 2, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
obviyus pushed a commit that referenced this pull request Mar 2, 2026
Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Linux2010 pushed a commit to Linux2010/openclaw that referenced this pull request Mar 2, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…ord0760

Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants