Windows regression: explicit Git Bash `exec_command.shell` falls back to `cmd.exe`

Open 💬 4 comments Opened Aug 24, 2026 by Lambholl

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.exe
  • login omitted and login: 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?

  1. Install Codex Desktop and Git for Windows on native Windows.
  2. Confirm C:\Program Files\Git\bin\bash.exe exists and can run a .sh file directly.
  3. Ensure Git Bash's bin directory is not on the Codex process PATH, so where.exe bash returns no match. Git's normal C:\Program Files\Git\cmd directory may still be on PATH.
  4. Start a Codex Desktop thread in a Windows-native workspace.
  5. Ask the agent to execute the first tools.exec_command snippet above, with shell set to the absolute Git Bash path.
  6. Observe that Bash syntax is parsed by cmd.exe and fails.
  7. Optionally repeat with the PowerShell control. It succeeds, showing that the shell field 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 CLI 0.148.0-alpha.21)
  • 01a0128f-01c0-7380-90e5-bd5c2c65a168 (August 18 working subagent rollout; parent session 01a00eda-0b19-7f92-9ca4-5304a5210b08)
  • 01a031d0-e351-7241-80ab-cd8ba21c7709 (August 24 original failure; failing turn 01a031d0-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:

In the failing 0.149.0-alpha.4.1 source:

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:

  1. Add safe Windows Bash discovery for standard Git for Windows locations such as C:\Program Files\Git\bin\bash.exe and C:\Program Files\Git\usr\bin\bash.exe.
  2. Return an explicit “requested Bash shell is unavailable” error instead of silently falling back to cmd.exe.
  3. If shell is 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 absolute exec_command.shell path being discarded after PR #39607.
  • #16579 requests persistent configuration of the default Windows session shell.
  • #27474 concerns WSL runner startup and /bin/bash process creation.
  • #9581 concerns shell-aware command generation and cmd.exe wrapping, not an explicit absolute shell path 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.

View original on GitHub ↗

4 Comments

TerminalDev-1 · 3 days ago

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.exe locations 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-command regression coverage and verify the case where Git Bash is installed but bare bash is absent from PATH. I’ll report the exact test results in the PR rather than presenting unverified claims.

TerminalDev-1 · 3 days ago

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.exe
  • C:\Program Files\Git\usr\bin\bash.exe

It 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 fmt
  • just test -p codex-shell-command — 172/172 tests passed
  • Windows smoke environment matched the report: bare bash absent from PATH, both standard Git Bash executables present, and the bin\bash.exe executable 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.

Lambholl · 3 days ago
Implementation is ready in my fork: TerminalDev-1@b6bde09 The change adds Windows-only Bash fallback discovery for: C:\Program Files\Git\bin\bash.exe C:\Program Files\Git\usr\bin\bash.exe It 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 fmt just test -p codex-shell-command — 172/172 tests passed * Windows smoke environment matched the report: bare bash absent from PATH, both standard Git Bash executables present, and the bin\bash.exe executable 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.exe and C:\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.

  1. User‑customised installation paths

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 to cmd.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.

  1. Explicit error when the requested shell type is unavailable

The current behaviour of falling back to cmd.exe without warning is very confusing. In the reproduction, the user explicitly asked for bash.exe, but the actual command was run by cmd.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.

  1. Other popular Bash environments on Windows

While Git Bash is the most common, there are other widely used Bash providers on Windows that developers often rely on:

  • WSL – with over 5 million monthly active users (per recent reports), WSL is a very popular choice. However, WSL’s Bash is typically invoked via wsl.exe rather than a direct bash.exe path, so the discovery logic might need special handling.
  • Cygwin – often installed at C:\cygwin\bin\bash.exe or C:\cygwin64\bin\bash.exe.
  • MSYS2 – the underlying runtime for Git Bash, but also available as a standalone installation (e.g., 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.

  1. Update the tool schema description

The exec_command.shell field 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.

TerminalDev-1 · 3 days ago

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 the exec_command.shell schema 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.