Skip to content

Never resolve a bare name to a batch file on the overlay PATH [patch] - #140

Open
matt-edmondson wants to merge 1 commit into
mainfrom
fix/138-bare-name-exe-only
Open

matt-edmondson wants to merge 1 commit into
mainfrom
fix/138-bare-name-exe-only

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #138

What changed

Since #137, ResolveOnSearchPath tried a Windows name with no extension against every PATHEXT extension, so ExecuteAsync("npm", ...) with PATH in the overlay resolved to npm.cmd. CreateProcess starts a batch file through cmd.exe, which re-parses the whole command line. The argument escaping follows CommandLineToArgvW rather than cmd.exe's rules, so &, | or % in an argument ran as commands. This is the BatBadBut class (CVE-2024-24576).

This takes option 1 from the issue and triage comment: a name with no extension is now tried with .exe only. That is the one extension CreateProcess adds, so a bare name can start the same set of files it could before #137. A batch file named with its extension (npm.cmd) is still resolved, because naming it is the caller's explicit choice. The README now says this and warns against passing untrusted arguments to a batch file.

ResolveOnSearchPath no longer reads PATHEXT, so its unused environment parameter is gone. The method is internal.

Tests

  • Replaced ResolveOnSearchPathShouldApplyPathExtOnWindows with:
    • ResolveOnSearchPathShouldAddExeToANameWithNoExtensionOnWindows: a bare name finds tool.exe.
    • ResolveOnSearchPathShouldNeverResolveABareNameToABatchFileOnWindows: with tool.cmd, tool.bat and tool.com on the path, a bare tool resolves to nothing, and an explicit tool.cmd still resolves.
  • I put the .cmd pick back in temporarily and the new test failed (Expected value to be null. actual: ".../tool-....cmd"). With the fix in place it passes.
  • Full suite on Linux, net10.0: 91 passed, 2 skipped (the existing Windows-only elevation tests), 0 failed.

The resolution logic is tested through isWindows: true on Linux. I did not run the end-to-end cmd.exe repro on Windows, and the issue says its own repro was also worked out from the code.


Generated by Claude Code

Since #137, a bare name with no extension on Windows was tried with every
PATHEXT extension, so `npm` resolved to `npm.cmd`. CreateProcess starts a
batch file through cmd.exe, which re-parses the command line, and the
argument-vector escaping follows CommandLineToArgvW rather than cmd.exe's
rules, so `&`, `|` or `%` in an argument ran as commands (the BatBadBut
class, CVE-2024-24576).

A name with no extension is now tried with `.exe` only, which is all
CreateProcess adds, restoring the pre-#137 set of files a bare name can
start. A batch file named with its extension is still the caller's choice.
The README says so and warns against passing it untrusted arguments.

The PATHEXT test is replaced by one that a bare name resolves to tool.exe
and one that it never resolves to tool.cmd, tool.bat or tool.com while an
explicit tool.cmd still does.

Fixes #138

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW5DyciGEV4wZvik3pQ
@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: with PATH in the overlay, a bare name like npm now resolves to npm.cmd, so cmd.exe re-parses the arguments and &, |, % in them run as commands

2 participants