You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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 #138
ResolveOnSearchPath (RunCommand/RunCommand.cs, around lines 469–498, called from CreateStartInfo around line 416) was added in #137. On Windows, when the name has no extension, it tries every PATHEXT extension in each overlay PATH directory. The default list is .COM;.EXE;.BAT;.CMD, and the first hit wins. So ExecuteAsync("npm", ...) now resolves to C:\nodejs\npm.cmd.
That changes what can run:
Before Look a bare executable name up on the overlay PATH [patch] #137: with UseShellExecute = false, .NET calls CreateProcess(null, "<FileName> <args>"). For a name with no extension, CreateProcess only ever appends .exe. A bare name could never start a batch file.
The escaping doesn't cover cmd.exe:ArgumentList escaping follows the CommandLineToArgvW rules. It does nothing about cmd metacharacters such as & | < > ^ %.
This is the same class of bug as BatBadBut (CVE-2024-24576). I worked it out from the code; I have not run it on Windows.
Failure scenario
varoptions=newCommandOptions{EnvironmentVariables=newDictionary<string,string?>{["PATH"]=@"C:\nodejs"}};awaitRunCommand.ExecuteAsync("npm",["install",userInput],handler,options,ct);// userInput = "x&calc" → cmd.exe runs `npm install x` and then `calc`
The README presents the argument-vector API as the way to avoid quoting problems, and this breaks that promise without warning. Whether a batch file can be started at all now also depends on whether PATH happens to be in the overlay. Without the overlay, the same call fails with "file not found".
Priority: High. The PATH lookup added in Look a bare executable name up on the overlay PATH [patch] #137 lets a bare name like npm resolve to a .cmd/.bat on Windows. The argument-vector API then stops protecting callers: cmd.exe re-parses the arguments, so &, | and % in user-supplied values run as commands. This is the BatBadBut class (CVE-2024-24576). It only applies on Windows when PATH is in the overlay, but it silently breaks the README's main safety promise, and it shipped in a patch release.
Area / suggested assignment:ResolveOnSearchPath / CreateStartInfo in RunCommand/RunCommand.cs, plus the README section on argument quoting.
Next step: Option 1 (try only .exe for a name with no extension, as CreateProcess does) is the smallest change and restores the pre-Look a bare executable name up on the overlay PATH [patch] #137 set of startable files. Ship it as a patch, with a Windows test where the overlay PATH holds tool.cmd and an argument contains &. Option 3 (cmd.exe escaping) can follow later if starting batch files by bare name turns out to be wanted. This was worked out from the code, not run on Windows, so the test should confirm the repro first.
Activity
matt-edmondson commentedon Nov 4, 2026
Triage
npmresolve to a.cmd/.baton Windows. The argument-vector API then stops protecting callers: cmd.exe re-parses the arguments, so&,|and%in user-supplied values run as commands. This is the BatBadBut class (CVE-2024-24576). It only applies on Windows whenPATHis in the overlay, but it silently breaks the README's main safety promise, and it shipped in a patch release.ResolveOnSearchPath/CreateStartInfoinRunCommand/RunCommand.cs, plus the README section on argument quoting..exefor a name with no extension, as CreateProcess does) is the smallest change and restores the pre-Look a bare executable name up on the overlay PATH [patch] #137 set of startable files. Ship it as a patch, with a Windows test where the overlayPATHholdstool.cmdand an argument contains&. Option 3 (cmd.exe escaping) can follow later if starting batch files by bare name turns out to be wanted. This was worked out from the code, not run on Windows, so the test should confirm the repro first.Generated by Claude Code