Skip to content

fix(core): preserve system PATH in Git environment to fix ENOENT (#25034)#26587

Merged
cocosheng-g merged 9 commits into
mainfrom
fix/git-enoent-25034
May 7, 2026
Merged

fix(core): preserve system PATH in Git environment to fix ENOENT (#25034)#26587
cocosheng-g merged 9 commits into
mainfrom
fix/git-enoent-25034

Conversation

@cocosheng-g
Copy link
Copy Markdown
Contributor

Summary

This PR fixes an issue where the Gemini CLI fails to start with spawn git ENOENT on systems with custom Git installations (e.g., in ~/bin). The GitService was stripping the system PATH when initializing the shadow repository environment.

Details

The getShadowRepoEnv method was creating a clean environment object for Git configuration isolation but forgot to include process.env. By merging process.env (and spreading it before our overrides), we restore access to the user's PATH while maintaining the intended isolation of the shadow repo's configuration and identity.

Related Issues

Fixes #25034

How to Validate

  1. Create a dummy directory with a symlinked git binary.
  2. Set a restricted PATH that only includes that directory.
  3. Run npm run start and verify the CLI starts without ENOENT.
  4. Run npm test -w @google/gemini-cli-core -- src/services/gitService.test.ts to verify regression tests.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run

@cocosheng-g cocosheng-g requested a review from a team as a code owner May 6, 2026 14:38
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where the Gemini CLI would fail to locate the Git binary on systems with custom installations. By correctly merging the existing process environment into the shadow repository's environment configuration, the CLI can now properly resolve system paths while maintaining the necessary isolation for Git configuration.

Highlights

  • Environment Variable Preservation: Updated the shadow repository environment configuration to include existing process environment variables, ensuring the system PATH remains accessible.
  • Regression Testing: Added new test cases to verify that system environment variables are preserved while still correctly overriding Git-specific configuration paths.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Size Change: +297 B (0%)

Total Size: 34 MB

Filename Size Change
./bundle/chunk-7DP53QUW.js 0 B -2.78 MB (removed) 🏆
./bundle/chunk-CU65WPCX.js 0 B -3.43 kB (removed) 🏆
./bundle/chunk-F334ZGJX.js 0 B -19.5 kB (removed) 🏆
./bundle/chunk-GFLFE6T6.js 0 B -49.2 kB (removed) 🏆
./bundle/chunk-LTKMPO5I.js 0 B -12.5 kB (removed) 🏆
./bundle/chunk-ULSQK5RQ.js 0 B -3.8 kB (removed) 🏆
./bundle/chunk-VOTFE6OJ.js 0 B -14.8 MB (removed) 🏆
./bundle/chunk-WNHPOQQI.js 0 B -658 kB (removed) 🏆
./bundle/core-CQW7I7GP.js 0 B -48.8 kB (removed) 🏆
./bundle/devtoolsService-GRUSXWI7.js 0 B -28 kB (removed) 🏆
./bundle/gemini-NQRNFRNM.js 0 B -584 kB (removed) 🏆
./bundle/interactiveCli-FKRSGTXQ.js 0 B -1.29 MB (removed) 🏆
./bundle/liteRtServerManager-BIXC7P5O.js 0 B -2.11 kB (removed) 🏆
./bundle/oauth2-provider-LT4O4KOI.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-4XKVUMY3.js 12.5 kB +12.5 kB (new file) 🆕
./bundle/chunk-76JHD64Z.js 3.43 kB +3.43 kB (new file) 🆕
./bundle/chunk-7KYW6TNW.js 49.2 kB +49.2 kB (new file) 🆕
./bundle/chunk-KQ57D6UA.js 14.8 MB +14.8 MB (new file) 🆕
./bundle/chunk-QQ7RVVX2.js 2.78 MB +2.78 MB (new file) 🆕
./bundle/chunk-RDM6E472.js 19.5 kB +19.5 kB (new file) 🆕
./bundle/chunk-UYM6ON5U.js 658 kB +658 kB (new file) 🆕
./bundle/chunk-VYVZ2QY6.js 3.8 kB +3.8 kB (new file) 🆕
./bundle/core-UYTF2NWD.js 48.8 kB +48.8 kB (new file) 🆕
./bundle/devtoolsService-5OYV2VCK.js 28 kB +28 kB (new file) 🆕
./bundle/gemini-T5Z7LBC5.js 584 kB +584 kB (new file) 🆕
./bundle/interactiveCli-F4Q33XAE.js 1.29 MB +1.29 MB (new file) 🆕
./bundle/liteRtServerManager-5D7XD23W.js 2.11 kB +2.11 kB (new file) 🆕
./bundle/oauth2-provider-QMLTJER2.js 9.16 kB +9.16 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/bundled/third_party/index.js 8 MB 0 B
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 0 B
./bundle/chunk-5PS3AYFU.js 1.18 kB 0 B
./bundle/chunk-664ZODQF.js 124 kB 0 B
./bundle/chunk-DAHVX5MI.js 206 kB 0 B
./bundle/chunk-IUUIT4SU.js 56.5 kB 0 B
./bundle/chunk-RJTRUG2J.js 39.8 kB 0 B
./bundle/chunk-VJSUVOZ4.js 1.97 MB 0 B
./bundle/cleanup-W73Q52VV.js 0 B -932 B (removed) 🏆
./bundle/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-T73EYRDX.js 356 B 0 B
./bundle/events-XB7DADIJ.js 418 B 0 B
./bundle/examples/hooks/scripts/on-start.js 188 B 0 B
./bundle/examples/mcp-server/example.js 1.43 kB 0 B
./bundle/gemini.js 5.1 kB 0 B
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB 0 B
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB 0 B
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB 0 B
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB 0 B
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB 0 B
./bundle/memoryDiscovery-NGHTMHWQ.js 980 B 0 B
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 222 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 229 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 13.4 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B
./bundle/src-QVCVGIUX.js 47 kB 0 B
./bundle/start-AWPC6QG3.js 0 B -652 B (removed) 🏆
./bundle/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/cleanup-FECSQYHI.js 932 B +932 B (new file) 🆕
./bundle/start-UKPEGZCG.js 652 B +652 B (new file) 🆕

compressed-size-action

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/core Issues related to User Interface, OS Support, Core Functionality labels May 6, 2026
@cocosheng-g
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the GitService to include the current process environment variables in the shadow repository's environment and adds corresponding unit tests. Feedback identifies a security risk where merging the full process.env could compromise repository isolation, suggesting a sanitized approach instead. Additionally, the new tests violate the style guide by using try...finally blocks for environment stubbing rather than the preferred beforeEach and afterEach hooks.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/services/gitService.ts (61)

security-high high

The inclusion of ...process.env in getShadowRepoEnv allows environment variables to overwrite GIT_DIR and GIT_WORK_TREE, breaking repository isolation. This can lead to the CLI performing git operations on the user's actual repository instead of the internal history repository. Use a sanitized environment for this configuration to prevent extensions from bypassing environment variable controls or overriding security-sensitive settings, limiting it to necessary variables like PATH.

PATH: process.env.PATH,
References
  1. Use a sanitized environment for configurations to prevent bypassing environment variable redaction or exfiltration.
  2. Security-sensitive settings should not use a merge strategy that allows less-trusted configuration scopes to completely override more-trusted scopes.

packages/core/src/services/gitService.test.ts (313-328)

high

This test uses a try...finally block to manage environment variable stubbing and cleanup. This violates the repository style guide (lines 86-88), which specifies that vi.stubEnv should be used in beforeEach and vi.unstubAllEnvs() in afterEach to ensure consistent cleanup and avoid test leakage.

Please refactor the tests to follow this convention (e.g., by using a nested describe block with its own beforeEach for these specific environment tests) and ensure vi.unstubAllEnvs() is added to the top-level afterEach block.

References
  1. Environment Variables: When testing code that depends on environment variables, use vi.stubEnv('NAME', 'value') in beforeEach and vi.unstubAllEnvs() in afterEach. (link)

@cocosheng-g
Copy link
Copy Markdown
Contributor Author

addressed all

@cocosheng-g
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the GitService to include the system PATH in the environment for Git operations and adds unit tests to verify environment variable preservation and isolation. The review feedback indicates that only preserving PATH is too restrictive and recommends using a sanitized environment to include other essential variables while preventing the exfiltration of sensitive data. Additionally, it was noted that the shadow repository implementation should be checked for potential environment variable collisions.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/services/gitService.ts (61)

high

The current implementation only preserves the PATH variable, which is overly restrictive and contradicts the PR description. However, to prevent the exfiltration of sensitive system environment variables, the environment should be sanitized rather than fully spread. Consider using a sanitized environment that includes essential variables like SystemRoot (on Windows) or HOME while redacting sensitive ones, consistent with the repository's security practices for external integrations.

[!IMPORTANT]
If you update the environment, ensure that the shadowGitRepository getter (line 129) is updated to avoid collisions where a user's GIT_DIR or GIT_WORK_TREE might override the shadow repository's settings.

      ...getSanitizedEnv(process.env),
References
  1. Sanitize the environment used for variable expansion to prevent malicious extensions from exfiltrating sensitive system environment variables.

@cocosheng-g
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements environment variable sanitization for the shadow Git repository to prevent sensitive data leakage and ensure consistent behavior. It also adds a comprehensive suite of tests to verify the preservation of safe variables (like PATH and HOME) and the isolation of Git-specific configurations. A security review highlighted that while process.env is now sanitized, variables like GIT_DIR and GIT_WORK_TREE could still leak into the shadow repository's environment if not explicitly overridden, potentially breaking isolation. A suggestion was provided to explicitly unset these variables in the base environment configuration.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/services/gitService.ts (64-71)

security-high high

While merging process.env fixes the PATH issue, it also allows other Git-related environment variables like GIT_DIR and GIT_WORK_TREE to leak into the shadow repository's environment. This can break isolation, especially during setupShadowGitRepository where these variables are not explicitly overridden. To ensure robust isolation and prevent potential security bypasses, these variables should be explicitly unset in the base environment configuration, and the environment should be sanitized to prevent sensitive variable leakage.

    return {
      ...sanitizeEnvironment(
        process.env,
        getSecureSanitizationConfig({ enableEnvironmentVariableRedaction: true }),
      ),
      // Prevent git from using the user's global git config.
      GIT_CONFIG_GLOBAL: gitConfigPath,
      GIT_CONFIG_SYSTEM: systemConfigPath,
      // Ensure user's GIT_DIR/GIT_WORK_TREE don't interfere with shadow repo operations.
      GIT_DIR: undefined,
      GIT_WORK_TREE: undefined,
References
  1. Use a sanitized environment for variable expansion to prevent extensions from bypassing environment variable redaction or exfiltrating sensitive system environment variables.

@cocosheng-g
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces environment variable sanitization and improved isolation for the GitService. It integrates sanitizeEnvironment to redact sensitive data and ensures that GIT_DIR and GIT_WORK_TREE are explicitly managed to prevent inheritance from the user's environment. The update also reorders environment application in shadowGitRepository to prioritize internal settings. Extensive unit tests were added to validate these security measures. I have no feedback to provide.

@cocosheng-g cocosheng-g requested a review from a team as a code owner May 6, 2026 17:53
Comment thread packages/core/src/tools/shellBackgroundTools.integration.test.ts Outdated
@cocosheng-g cocosheng-g added this pull request to the merge queue May 6, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 6, 2026
@cocosheng-g cocosheng-g added this pull request to the merge queue May 6, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 6, 2026
@cocosheng-g cocosheng-g added this pull request to the merge queue May 7, 2026
Merged via the queue into main with commit 49456e4 May 7, 2026
27 checks passed
@cocosheng-g cocosheng-g deleted the fix/git-enoent-25034 branch May 7, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality priority/p2 Important but can be addressed in a future release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gemini CLI fails with locally-compiled Git

2 participants