Skip to content

fix(cli): explain missing API key when .env is skipped in untrusted folders#20048

Closed
nsalerni wants to merge 12 commits intogoogle-gemini:mainfrom
nsalerni:issues-20005
Closed

fix(cli): explain missing API key when .env is skipped in untrusted folders#20048
nsalerni wants to merge 12 commits intogoogle-gemini:mainfrom
nsalerni:issues-20005

Conversation

@nsalerni
Copy link
Copy Markdown
Contributor

Summary

Improve the Gemini API key auth error in untrusted workspaces by explaining when a .env file was found but intentionally not loaded due to folder trust.

This fixes a misleading UX where users are told GEMINI_API_KEY is missing without any indication that the workspace trust policy blocked .env loading.

Details

  • validateAuthMethod() now appends a trust-specific hint when all of the following are true:
    • auth mode is USE_GEMINI
    • GEMINI_API_KEY is missing
    • a .env file was found
    • .env loading was skipped because the workspace is untrusted
  • loadEnvironment() now returns lightweight metadata (envFilePath, trust result, sandbox state, skippedDueToTrust) while preserving existing behavior.
  • Added/updated unit tests for:
    • untrusted workspace with .env present (hint shown)
    • untrusted workspace with no .env (no hint shown)

Design choice:

  • Kept the change scoped to messaging only (no trust-policy or auth behavior changes).
  • Used the repo’s current trust UX wording (/permissions trust) instead of introducing a new command reference.

Related Issues

Fixes #20005

How to Validate

  1. Run targeted tests:

    • npm --prefix packages/cli test -- src/config/auth.test.ts
    • Expected: tests pass, including new untrusted .env messaging coverage.
  2. Run CLI package typecheck:

    • npm --prefix packages/cli run typecheck -- --pretty false
    • Expected: no type errors.
  3. Manual behavior check (optional, local):

    • Configure folder trust feature and mark a workspace as untrusted.
    • Put GEMINI_API_KEY=... only in that workspace .env.
    • Run the CLI with Gemini API auth selected.
    • Expected: existing missing API key error plus a note explaining .env was not loaded because the folder is untrusted and suggesting /permissions trust.
  4. Edge case check:

    • Remove/rename .env and repeat.
    • Expected: only the original missing API key error (no trust-specific note).

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
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

If you want, I can also tailor the checklist to exactly what you personally validated (e.g. check MacOS > npm run only).

…olders

- append a trust-specific hint to the Gemini API key auth error when a .env file is found but not loaded due to folder trust
- return env-load metadata from loadEnvironment() so auth validation can distinguish trust-skips from normal missing env vars
- add auth tests covering untrusted workspace .env present/absent cases

Fixes google-gemini#20005
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @nsalerni, 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 enhances the user experience by providing clearer feedback when the Gemini API key is not found, specifically addressing cases where a .env file containing the key might have been present but was not loaded due to the workspace being untrusted. This change prevents misleading error messages and guides users on how to resolve the issue by trusting their workspace.

Highlights

  • Improved Error Messaging: The CLI now provides a more informative error message when the Gemini API key is missing because a .env file was not loaded due to an untrusted workspace.
  • Enhanced Environment Loading Metadata: The loadEnvironment() function now returns detailed metadata, including whether a .env file was found, the trust status of the workspace, sandbox state, and if .env loading was skipped due to trust policies.
  • New Helper Function for Error Hints: A new utility function, withUntrustedEnvHint, was introduced to conditionally append trust-specific guidance to error messages based on the environment loading result.
  • Comprehensive Unit Tests: New unit tests were added to cover scenarios where .env files are present in untrusted workspaces (expecting a hint) and where no .env file is found (expecting no hint).
Changelog
  • packages/cli/src/config/auth.test.ts
    • Imported loadEnvironment for mocking purposes.
    • Updated the mock for loadSettings to return a plain object for merged.
    • Added a default mock implementation for loadEnvironment in beforeEach to simulate a trusted environment.
    • Introduced new test cases to verify the presence or absence of trust guidance in error messages based on workspace trust and .env file existence.
  • packages/cli/src/config/auth.ts
    • Defined new constants GEMINI_API_KEY_ERROR and UNTRUSTED_ENV_HINT for standardized error messages.
    • Implemented withUntrustedEnvHint function to append trust-related information to error messages conditionally.
    • Modified validateAuthMethod to capture the return value of loadEnvironment and use it to enhance the Gemini API key missing error message.
  • packages/cli/src/config/settings.ts
    • Imported the TrustResult type for improved type safety.
    • Changed the return type of loadEnvironment from void to an object containing detailed environment loading metadata.
    • Updated loadEnvironment to return early with skippedDueToTrust: true if the workspace is untrusted and not sandboxed.
    • Ensured loadEnvironment consistently returns the new metadata object, indicating whether the .env was loaded or skipped.
Activity
  • Added/updated tests for the changes.
  • Validated on MacOS using npm run and npx.
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 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 counter productive. 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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.

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

The pull request successfully improves the user experience by providing a clear explanation when a .env file is skipped due to workspace trust policies. The implementation is robust, correctly handling cases where the workspace is sandboxed (allowing whitelisted variables) versus when it is completely untrusted. The logic for appending the hint is precise and avoids false positives. The changes to loadEnvironment to return metadata are well-integrated and the unit tests provide good coverage for the new behavior. No high or critical issues were identified.

@nsalerni nsalerni marked this pull request as ready for review February 23, 2026 18:38
@nsalerni nsalerni requested a review from a team as a code owner February 23, 2026 18:38
Updated the change to avoid redundant settings reloads in `validateAuthMethod()`:
- `validateAuthMethod()` now accepts injected `envLoadResult` / `settings`
- `loadSettings()` now preserves the initial `loadEnvironment()` metadata on `LoadedSettings` (`initialEnvLoadResult`)
- the main callers (`gemini.tsx`, `validateNonInterActiveAuth`, `AppContainer`, `useAuth`) now pass the already-computed metadata instead of forcing a fresh `loadSettings()` call

This keeps the UX fix for `google-gemini#20005` while avoiding the extra sync config reads / directory walk in the common paths.

Additionally, added a unit test asserting `validateAuthMethod()` does not call `loadSettings()` when `envLoadResult` is injected.
@KumarADITHYA123
Copy link
Copy Markdown
Contributor

Hey @nsalerni, fantastic execution on this!

When I filed the original issue detailing the trust boundary gap, avoiding that redundant
loadSettings
trap during the auth validation loop was exactly the performance optimization I was hoping we could nail down. You routed it perfectly.

Thanks for jumping in and getting this patched so quickly!

@KumarADITHYA123
Copy link
Copy Markdown
Contributor

Following up on this after doing a deeper technical scan of the diff just to ensure everything is watertight before it merges!

I noticed a couple of minor structural gaps in the implementation that might be worth addressing (either here or in a fast-follow PR):

Snapshot Sync gap: The LoadedSettings constructor was updated to accept initialEnvLoadResult, but the LoadedSettingsSnapshot interface (around line 305) was not updated to include it. Any system relying on snapshot serialization is going to drop that new state.

Test Coverage Gap: The options bag resolution path (options.settings injected without options.envLoadResult) does not have a direct unit test asserting that loadSettings() is bypassed.

Global Mock Shift: Mocking loadEnvironment globally in the beforeEach block of auth.test.ts is slightly risky; earlier tests in the file might have been implicitly relying on the real un-mocked function behavior.

Just a heads-up for @galz10 and @nsalerni! Besides those minor lifecycle and test coverage points, the core parameter injection logic looks rock solid.

- Added `initialEnvLoadResult` to `LoadedSettingsSnapshot` and included it in `computeSnapshot()` so snapshot consumers don’t lose that state.
- Added a unit test for the `validateAuthMethod(..., { settings })` path to confirm `loadSettings()` is not called when `settings` is injected.
@nsalerni
Copy link
Copy Markdown
Contributor Author

@KumarADITHYA123 thanks for the follow-up. I've addressed the first two points:

  • Added initialEnvLoadResult to LoadedSettingsSnapshot and included it in computeSnapshot() so snapshot consumers don’t lose that state.
  • Added a unit test for the validateAuthMethod(..., { settings }) path to confirm loadSettings() is not called when settings is injected.

On your last point, there is no shift from real to fake in beforeEach; the function is fake in all tests. auth.test.ts already does a module-level settings.js', ...), which means loadEnvironment is mocked for every test in the file from the start. The beforeEach is only setting the default return value of an already-mocked function, not changing real behavior to mocked behavior mid-file.

@nsalerni nsalerni requested a review from galz10 February 24, 2026 14:53
@nsalerni
Copy link
Copy Markdown
Contributor Author

nsalerni commented Feb 24, 2026

@galz10 I've requested an updated review (and merge if it looks good) based on the few minor updates.

@KumarADITHYA123
Copy link
Copy Markdown
Contributor

Verified - snapshot fix and test coverage additions look correct.

The Point 3 explanation makes sense (vi.mock hoists at the module level), so earlier tests were isolated.

Regarding the one CI failure: The Mac 22.x failure looks flaky since it passes identically on Mac 20.x and 24.x. nsalerni, you might just need to re-trigger that specific job.

LGTM from my side!

@galz10 I've verified the architectural updates from my previous review. This is unblocked and looks ready for your re-approval whenever you have a moment.

@gemini-cli
Copy link
Copy Markdown
Contributor

gemini-cli bot commented Mar 15, 2026

Hi there! Thank you for your interest in contributing to Gemini CLI.

To ensure we maintain high code quality and focus on our prioritized roadmap, we have updated our contribution policy (see Discussion #17383).

We only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'. All other community pull requests are subject to closure after 14 days if they do not align with our current focus areas. For this reason, we strongly recommend that contributors only submit pull requests against issues explicitly labeled as 'help-wanted'.

This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding and for being part of our community!

@gemini-cli gemini-cli bot closed this Mar 15, 2026
@nsalerni
Copy link
Copy Markdown
Contributor Author

nsalerni commented Mar 17, 2026

@google-gemini/gemini-cli-maintainers friendly ping for a review.

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.

Silent .env omission in untrusted workspaces causes misleading auth error

3 participants