Skip to content

feat(sandbox): resolve custom seatbelt profiles from $HOME/.gemini first#25427

Merged
scidomino merged 2 commits intogoogle-gemini:mainfrom
mvanhorn:osc/24991-seatbelt-home-dir
Apr 16, 2026
Merged

feat(sandbox): resolve custom seatbelt profiles from $HOME/.gemini first#25427
scidomino merged 2 commits intogoogle-gemini:mainfrom
mvanhorn:osc/24991-seatbelt-home-dir

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

Summary

Custom (non-builtin) SEATBELT_PROFILE values now resolve from $HOME/.gemini/sandbox-macos-${profile}.sb first, falling back to the existing project-level .gemini/sandbox-macos-${profile}.sb. This lets a user keep one custom profile that works across every workspace, which is what was requested in #24991.

Details

The previous resolution path (in packages/cli/src/utils/sandbox.ts:67-79) did:

  1. Bundled URL for builtin profile names in BUILTIN_SEATBELT_PROFILES
  2. path.join(GEMINI_DIR, 'sandbox-macos-${profile}.sb') for everything else - i.e. only the project's .gemini/

The change keeps step 1 unchanged. For non-builtin profiles, it now checks path.join(homedir(), GEMINI_DIR, fileName) and uses that file when it exists, otherwise falls back to the project-level path. The same FatalSandboxError is thrown if neither location has the file.

This matches the approach proposed in #24991 (comment) by @scidomino:

It would be better to change the code to search the home .gemini folder first before searching the workspace .gemini. That way, you could put a custom profile in one place and have it work with all your workspaces.

@flexponsive (the issue author) confirmed this would solve the problem. Two prior PRs (#25013, #25024) implemented the alternative SEATBELT_PROFILE-as-absolute-path approach and were closed with "we don't want to impl it this way" - so this PR deliberately takes the maintainer-directed path.

homedir and GEMINI_DIR are already imported from @google/gemini-cli-core in this file, mirroring the user-level .gemini lookups elsewhere (e.g. packages/core/src/services/fileKeychain.ts:19, packages/cli/src/config/trustedFolders.ts:30).

Related Issues

Fixes #24991

How to Validate

  1. npm run build --workspace @google/gemini-cli-core && npm run build --workspace @google/gemini-cli-test-utils
  2. npx vitest run packages/cli/src/utils/sandbox.test.ts - 18 tests pass, including two new tests:
    • should resolve custom seatbelt profile from user home directory
    • should fall back to project .gemini directory when user profile is missing
  3. npx prettier --check packages/cli/src/utils/sandbox.ts packages/cli/src/utils/sandbox.test.ts - clean
  4. npx eslint packages/cli/src/utils/sandbox.ts packages/cli/src/utils/sandbox.test.ts - no errors
  5. npm run typecheck --workspace @google/gemini-cli - passes

Manual smoke (macOS):

mkdir -p ~/.gemini
cp /path/to/your/profile.sb ~/.gemini/sandbox-macos-myprofile.sb
SEATBELT_PROFILE=myprofile gemini   # uses ~/.gemini profile

Run from any other workspace and the same profile resolves.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed) - behavior is additive; no doc changes required, but happy to add a note in docs/cli/sandbox.md if you'd prefer.
  • Added/updated tests (if needed)
  • Noted breaking changes (if any) - none; project-local profiles still work, builtin resolution unchanged.
  • Validated on required platforms/methods:
    • MacOS
      • npm run (vitest)
      • npx
      • Docker
      • Podman
      • Seatbelt (the code path under change)
    • Windows (not applicable - macOS-only code path)
    • Linux (not applicable - macOS-only code path)

This contribution was developed with AI assistance (Codex).

Custom (non-builtin) SEATBELT_PROFILE values now resolve from
$HOME/.gemini/sandbox-macos-${profile}.sb when present, falling back to
the existing project-level .gemini/sandbox-macos-${profile}.sb. This
lets users keep a single custom profile that works across every
workspace, as suggested by the maintainer in google-gemini#24991.

Builtin profile resolution is unchanged.

Fixes google-gemini#24991
@mvanhorn mvanhorn requested a review from a team as a code owner April 15, 2026 02:33
@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 enhances the gemini-cli's sandbox profile resolution mechanism for macOS. It introduces a new lookup order for custom seatbelt profiles, prioritizing user-specific configurations stored in the home directory over project-specific ones. This change improves usability by allowing developers to define global custom profiles that apply across all their workspaces, addressing a long-standing user request.

Highlights

  • Custom Seatbelt Profile Resolution: Custom (non-builtin) SEATBELT_PROFILE values now prioritize resolution from $HOME/.gemini/sandbox-macos-${profile}.sb before falling back to the existing project-level .gemini/sandbox-macos-${profile}.sb. This allows users to maintain a single custom profile across multiple workspaces.
  • New Test Cases: Added two new test cases to sandbox.test.ts to validate the new resolution logic: one for resolving from the user home directory and another for falling back to the project directory.
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.

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

This pull request updates the sandbox seatbelt profile resolution logic to check the user's home directory (~/.gemini) before falling back to the project-level directory, and includes new unit tests for these scenarios. Feedback focuses on a potential path traversal vulnerability where the profile environment variable should be sanitized using path.basename() before file path construction. Additionally, the reviewer noted that the new tests violate the repository style guide by modifying process.env directly instead of using vi.stubEnv().

Comment thread packages/cli/src/utils/sandbox.ts Outdated
Comment thread packages/cli/src/utils/sandbox.test.ts Outdated
Comment thread packages/cli/src/utils/sandbox.test.ts Outdated
@gemini-cli gemini-cli bot added area/core Issues related to User Interface, OS Support, Core Functionality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels Apr 15, 2026
@scidomino
Copy link
Copy Markdown
Collaborator

Please address all the gemini comments and mark them "resolved" when you are done.

- Apply path.basename() to SEATBELT_PROFILE before constructing the
  profile filename, preventing path traversal via directory separators
  or .. in the env var.
- Switch the two new sandbox tests to vi.stubEnv()/vi.unstubAllEnvs()
  to match the repo's testing convention (per gemini-code-assist
  feedback and existing usage in envVarResolver.test.ts and others).

Addresses gemini-code-assist review on google-gemini#25427.
@mvanhorn
Copy link
Copy Markdown
Contributor Author

@scidomino addressed all three in 8d919e9 - path.basename() on SEATBELT_PROFILE to prevent traversal, and vi.stubEnv() in both new tests with vi.unstubAllEnvs() in afterEach. Tests + lint + typecheck all pass.

@scidomino scidomino enabled auto-merge April 16, 2026 21:29
@wissamblue69-dotcom
Copy link
Copy Markdown

Summary

Custom (non-builtin) SEATBELT_PROFILE values now resolve from $HOME/.gemini/sandbox-macos-${profile}.sb first, falling back to the existing project-level .gemini/sandbox-macos-${profile}.sb. This lets a user keep one custom profile that works across every workspace, which is what was requested in #24991.

Details

The previous resolution path (in packages/cli/src/utils/sandbox.ts:67-79) did:

  1. Bundled URL for builtin profile names in BUILTIN_SEATBELT_PROFILES
  2. path.join(GEMINI_DIR, 'sandbox-macos-${profile}.sb') for everything else - i.e. only the project's .gemini/

The change keeps step 1 unchanged. For non-builtin profiles, it now checks path.join(homedir(), GEMINI_DIR, fileName) and uses that file when it exists, otherwise falls back to the project-level path. The same FatalSandboxError is thrown if neither location has the file.

This matches the approach proposed in #24991 (comment) by @scidomino:

It would be better to change the code to search the home .gemini folder first before searching the workspace .gemini. That way, you could put a custom profile in one place and have it work with all your workspaces.

@flexponsive (the issue author) confirmed this would solve the problem. Two prior PRs (#25013, #25024) implemented the alternative SEATBELT_PROFILE-as-absolute-path approach and were closed with "we don't want to impl it this way" - so this PR deliberately takes the maintainer-directed path.

homedir and GEMINI_DIR are already imported from @google/gemini-cli-core in this file, mirroring the user-level .gemini lookups elsewhere (e.g. packages/core/src/services/fileKeychain.ts:19, packages/cli/src/config/trustedFolders.ts:30).

Related Issues

Fixes #24991

How to Validate

  1. npm run build --workspace @google/gemini-cli-core && npm run build --workspace @google/gemini-cli-test-utils
  2. npx vitest run packages/cli/src/utils/sandbox.test.ts - 18 tests pass, including two new tests:
    • should resolve custom seatbelt profile from user home directory
    • should fall back to project .gemini directory when user profile is missing
  3. npx prettier --check packages/cli/src/utils/sandbox.ts packages/cli/src/utils/sandbox.test.ts - clean
  4. npx eslint packages/cli/src/utils/sandbox.ts packages/cli/src/utils/sandbox.test.ts - no errors
  5. npm run typecheck --workspace @google/gemini-cli - passes

Manual smoke (macOS):

mkdir -p ~/.gemini
cp /path/to/your/profile.sb ~/.gemini/sandbox-macos-myprofile.sb
SEATBELT_PROFILE=myprofile gemini   # uses ~/.gemini profile

Run from any other workspace and the same profile resolves.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed) - behavior is additive; no doc changes required, but happy to add a note in docs/cli/sandbox.md if you'd prefer.
  • Added/updated tests (if needed)
  • Noted breaking changes (if any) - none; project-local profiles still work, builtin resolution unchanged.
  • Validated on required platforms/methods:
    • MacOS
      • npm run (vitest)
      • npx
      • Docker
      • Podman
      • Seatbelt (the code path under change)
    • Windows (not applicable - macOS-only code path)
    • Linux (not applicable - macOS-only code path)

This contribution was developed with AI assistance (Codex).

@scidomino scidomino added this pull request to the merge queue Apr 16, 2026
Merged via the queue into google-gemini:main with commit 63e4bb9 Apr 16, 2026
27 checks passed
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 help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support custom seatbelt profiles in ~/.gemini

3 participants