Windows regression: explicit Git Bash `exec_command.shell` falls back to `cmd.exe`
What version of the Codex App are you using (From “About Codex” dialog)?
26.818.41509 / codex-cli 0.149.1
What subscription do you have?
Pro 20x
What platform is your computer?
Microsoft Windows NT 10.0.26100.0 x64
What issue are you seeing?
This is a regression in the CLI core embedded in Codex Desktop on native Windows. An exec_command call can provide an absolute Git Bash executable in the shell field, but with embedded CLI 0.149.0-alpha.4.1 the command is executed by cmd.exe instead.
The same absolute shell path worked in a closer rollout using embedded CLI 0.148.0-alpha.21:
| Rollout evidence | Embedded CLI | Result |
| --- | --- | --- |
| rollout-2026-08-21T16-20-45-01a02368-7ce7-7e90-9487-6630fadf44ad.jsonl | 0.148.0-alpha.21 | Bash builtin printf, rg, and sed execute successfully through C:\Program Files\Git\bin\bash.exe |
| rollout-2026-08-24T11-29-28-01a031d0-e351-7241-80ab-cd8ba21c7709.jsonl | 0.149.0-alpha.4.1 | The same shell path produces -d was unexpected at this time. from cmd.exe |
| rollout-2026-08-24T11-33-24-01a031d4-7e07-7cf2-8e01-66b0cc07cbbf.jsonl | 0.149.0-alpha.4.1 | Four Git Bash path/login variants all produce 'printf' is not recognized... |
| rollout-2026-08-18T09-49-17-01a0128f-01c0-7380-90e5-bd5c2c65a168.jsonl | 0.148.0-alpha.9 | Earlier corroboration: wc and sed also execute successfully through the same shell path |
For example:
const r = await tools.exec_command({
cmd: "printf 'BASH=%s\\n' \"$BASH_VERSION\"",
workdir: "D:/path/to/repo",
shell: "C:/Program Files/Git/bin/bash.exe",
login: false
});
text(r.output);
Actual output:
'printf' is not recognized as an internal or external command,
operable program or batch file.
A second Bash-only command produces a characteristic cmd.exe parser error:
const r = await tools.exec_command({
cmd: "pwd && if [ -d . ]; then echo MEMORY_PRESENT; else echo MEMORY_MISSING; fi",
workdir: "D:/path/to/repo",
shell: "C:\\Program Files\\Git\\bin\\bash.exe"
});
text(r.output);
Actual output:
-d was unexpected at this time.
Git Bash itself is installed and functional. Both of these files exist:
C:\Program Files\Git\bin\bash.exe
C:\Program Files\Git\usr\bin\bash.exe
Launching the first executable directly from PowerShell with a .sh script succeeds:
BASH_VERSION=5.3.15(1)-release
PWD=/d/path/to/repo
BASH_CONDITIONAL=ok
The problem occurs when bash is not resolvable by bare name from the Codex process PATH; where.exe bash returns no match. The explicit absolute shell path should make that irrelevant, but Codex appears to discard it and silently selects cmd.exe.
The behavior was reproduced with:
- Forward-slash and backslash forms of
C:\Program Files\Git\bin\bash.exe C:\Program Files\Git\usr\bin\bash.exeloginomitted andlogin: false
As a control, an explicit PowerShell path in the same shell field works:
await tools.exec_command({
cmd: "Write-Output SHELL_FIELD_POWERSHELL_OK",
shell: "C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe",
login: false
});
Output:
SHELL_FIELD_POWERSHELL_OK
This breaks repository instructions that require Git Bash syntax and explicitly direct the agent to pass Git Bash through exec_command.shell.
What steps can reproduce the bug?
- Install Codex Desktop and Git for Windows on native Windows.
- Confirm
C:\Program Files\Git\bin\bash.exeexists and can run a.shfile directly. - Ensure Git Bash's
bindirectory is not on the Codex processPATH, sowhere.exe bashreturns no match. Git's normalC:\Program Files\Git\cmddirectory may still be onPATH. - Start a Codex Desktop thread in a Windows-native workspace.
- Ask the agent to execute the first
tools.exec_commandsnippet above, withshellset to the absolute Git Bash path. - Observe that Bash syntax is parsed by
cmd.exeand fails. - Optionally repeat with the PowerShell control. It succeeds, showing that the
shellfield is reaching shell selection but the Git Bash executable path is not being honored.
Reproduction rollout/session IDs:
01a02368-7ce7-7e90-9487-6630fadf44ad(August 21 closest working baseline, embedded CLI0.148.0-alpha.21)01a0128f-01c0-7380-90e5-bd5c2c65a168(August 18 working subagent rollout; parent session01a00eda-0b19-7f92-9ca4-5304a5210b08)01a031d0-e351-7241-80ab-cd8ba21c7709(August 24 original failure; failing turn01a031d0-ed00-7e41-81b5-e0927e37ab6d)01a031d4-7e07-7cf2-8e01-66b0cc07cbbf(August 24 controlled reproduction)
At evidence extraction in the controlled reproduction, the last-turn token usage was 114,174 tokens with a 258,400-token context window (about 44.2%). Reported primary and secondary rate-limit usage was 0%.
What is the expected behavior?
When exec_command.shell identifies an installed and supported shell, Codex should execute the command with that requested shell type.
For the reproduction above, expected output is similar to:
BASH=5.3.15(1)-release
If model-provided executable paths are intentionally not launched for security reasons, Codex should safely discover standard Git for Windows Bash installations or return a clear shell-resolution error. It should not silently fall back to a different shell whose syntax is incompatible with the command.
Additional information
The regression corresponds directly to commit 186b449 / PR #39607, “Resolve model-provided shells by type”. The observed behavioral boundary is embedded CLI 0.148.0-alpha.21 working on August 21 versus 0.149.0-alpha.4.1 failing on August 24; the App package number is not used to identify the responsible core behavior.
In the working 0.148.0-alpha.21 source:
get_shell_pathfirst accepts the supplied path when it is an existing file.get_shell_by_model_provided_pathpasses that path through to shell resolution.
In the failing 0.149.0-alpha.4.1 source:
get_shell_by_model_provided_pathuses the supplied path only to determine a shell type, then rediscovers an executable.- Bash discovery searches for bare
bashand falls back only to/bin/bashand/usr/bin/bash; it has no standard Git for Windows fallback paths. - The Windows ultimate fallback is
cmd.exe.
PR #39607 explains that a model-provided path should select only the shell type and should not determine the executable Codex launches. That security goal is understandable, but on Windows it creates a regression when Git Bash exists at its standard absolute path while bare bash is not on PATH: Bash discovery fails and Codex silently switches to cmd.exe.
Possible fixes that preserve the security goal:
- Add safe Windows Bash discovery for standard Git for Windows locations such as
C:\Program Files\Git\bin\bash.exeandC:\Program Files\Git\usr\bin\bash.exe. - Return an explicit “requested Bash shell is unavailable” error instead of silently falling back to
cmd.exe. - If
shellis intentionally only a shell-type hint, update the tool schema description; it currently describes the field as the shell binary to launch.
I searched existing issues before drafting this report. These are related but appear materially different:
- #13199 broadly reports difficulty running Git Bash commands on Windows with CLI
0.106.0; it predates this regression and does not isolate an explicit absoluteexec_command.shellpath being discarded after PR #39607. - #16579 requests persistent configuration of the default Windows session shell.
- #27474 concerns WSL runner startup and
/bin/bashprocess creation. - #9581 concerns shell-aware command generation and
cmd.exewrapping, not an explicit absoluteshellpath being discarded.
A sanitized JSONL reproduction bundle is available as an attachment. It preserves the original rollout filenames and line numbers for the version metadata, the corroborating success, the failure, and the controlled reproduction without including the full conversations.
The standalone codex --version value is not used as the regression boundary here. Each rollout's own session_meta.cli_version identifies the CLI core actually embedded in Codex Desktop and responsible for that session.
4 Comments
I’d like to work on a narrow fix for this, with implementation and testing performed using Codex under my direction and review.
The proposed approach is to add the standard Git for Windows
bash.exelocations to Windows Bash discovery while preserving the security behaviour from #39607: the model-provided path selects only the shell type and is never executed directly.I’ll include focused
codex-shell-commandregression coverage and verify the case where Git Bash is installed but barebashis absent fromPATH. I’ll report the exact test results in the PR rather than presenting unverified claims.Implementation is ready in my fork: https://github.com/TerminalDev-1/codex/commit/b6bde09c2d9033c29eb63e38e05877704a466140
The change adds Windows-only Bash fallback discovery for:
C:\Program Files\Git\bin\bash.exeC:\Program Files\Git\usr\bin\bash.exeIt preserves the security behaviour from #39607: the model-provided path still selects only the shell type and is not executed directly. I also added focused coverage for selecting an existing fallback when the requested shell is not otherwise discoverable.
Validation:
just fmtjust test -p codex-shell-command— 172/172 tests passedbashabsent fromPATH, both standard Git Bash executables present, and thebin\bash.exeexecutable successfully ran Bash syntax.This was an AI-assisted contribution. I directed and reviewed the work; Codex traced the regression, explained the proposed change before implementation, produced the patch, and ran the formatting and tests. I reviewed the scope, diff, and results and take responsibility for the contribution.
GitHub currently reports that only repository collaborators may open pull requests against
openai/codex, so I cannot submit the prepared cross-fork PR from this account. The comparison is mergeable and contains one commit touching one file. If a maintainer would like the change, it can be cherry-picked from the commit above, or I would be happy to open the PR if granted the required access.Thanks for the detailed report and for the targeted fix in #40328. The proposed addition of the standard Git for Windows paths (
C:\Program Files\Git\bin\bash.exeandC:\Program Files\Git\usr\bin\bash.exe) addresses the most common installation scenario and is a good immediate improvement.However, I think there are a few broader points that might be worth considering alongside or after this fix, to make the behaviour more robust and less surprising for users.
Git for Windows allows users to install to a non‑default location (e.g.,
D:\Tools\Git\bin\bash.exe). If a model provides an absolute path that is valid and exists, but it is not in the hard‑coded fallback list, the same regression will occur—Bash discovery fails and execution falls back tocmd.exe.A more resilient approach would be to treat the supplied path as a candidate when it points to an existing executable file, even if it is not used directly for security reasons. At a minimum, we could check whether the supplied path is executable and, if so, use it as the shell binary (which is what happened before the regression). If the intent is to keep the “type‑only” semantics, then we should at least verify that the supplied path is valid and, if not, surface a clear error instead of silently falling back.
The current behaviour of falling back to
cmd.exewithout warning is very confusing. In the reproduction, the user explicitly asked forbash.exe, but the actual command was run bycmd.exe, producing cryptic errors like-d was unexpected at this time.I would argue that when the requested shell type (e.g.,
bash) cannot be discovered through any of the safe mechanisms, Codex should return a clear error message stating that the requested shell is not available, rather than silently substituting a different shell. This would make the failure obvious and actionable.While Git Bash is the most common, there are other widely used Bash providers on Windows that developers often rely on:
wsl.exerather than a directbash.exepath, so the discovery logic might need special handling.C:\cygwin\bin\bash.exeorC:\cygwin64\bin\bash.exe.C:\msys2\usr\bin\bash.exe).Adding fallback paths for these environments (or at least documenting that they are not currently discovered) could improve compatibility for users who rely on them. Even if we don’t add them immediately, it’s worth noting that the current fix only covers Git Bash, and there may be future requests for these other environments.
The
exec_command.shellfield is currently described as “the shell binary to launch.” Since the implementation now treats it as a type hint rather than an executable path, the description should be updated to reflect that reality. This would set correct expectations for users and model authors.I appreciate that the security considerations behind #39607 are important, and I fully support not blindly executing a model‑provided path. But the current behaviour on Windows introduces a significant regression that can break workflows. The proposed fix is a good first step; I hope we can also address the additional points above to make the experience more reliable and transparent.
It’ll be appreciated if considering this.
Thank you for the detailed reply. I’m glad you took the time to consider the proposed fix and the broader implications.
I’ll definitely take your suggestions into consideration. Supporting non-standard Git installations, returning a clear error instead of silently falling back to
cmd.exe, and clarifying theexec_command.shellschema all sound worth investigating. Cygwin, MSYS2, and WSL may also deserve separate follow-up work because they have different discovery and execution models.For transparency, this is my first time contributing to an open-source project. I work by directing and reviewing Codex rather than writing the implementation by hand, so I genuinely appreciate you engaging constructively with the work and giving me useful technical feedback.
I’d like to keep the initial patch narrowly focused on the standard Git for Windows regression, particularly because accepting arbitrary supplied executable paths would interact with the security boundary introduced in #39607. The additional improvements could then be explored independently without making this first fix significantly harder to review.
Thank you again—I appreciate the thoughtful response.