Skip to content

feat(sandbox): add experimental LXC container sandbox support#20735

Merged
scidomino merged 4 commits intogoogle-gemini:mainfrom
h30s:feat/lxc-sandbox
Mar 4, 2026
Merged

feat(sandbox): add experimental LXC container sandbox support#20735
scidomino merged 4 commits intogoogle-gemini:mainfrom
h30s:feat/lxc-sandbox

Conversation

@h30s
Copy link
Copy Markdown
Contributor

@h30s h30s commented Mar 1, 2026

Summary

Adds experimental Linux-only LXC/LXD-based sandboxing support to Gemini CLI. This enables tools like Snapcraft and Rockcraft that require a full system container with systemd and snapd — services that Docker/Podman cannot provide in standard containers.

The user creates and manages their own LXC container; Gemini runs inside it via lxc exec. The workspace is bind-mounted at the same absolute path. This follows the established sandbox abstraction pattern without requiring a container image.

Details

  • Adds 'lxc' to the SandboxConfig.command union type in packages/core
  • Adds 'lxc' to VALID_SANDBOX_COMMANDS in sandboxConfig.ts (explicit opt-in only via GEMINI_SANDBOX=lxc or sandbox: "lxc" in settings — NOT auto-detected because LXC requires a user-managed, pre-running container)
  • Implements start_lxc_sandbox() in sandbox.ts:
    • Validates container existence and running state via lxc list --format=json
    • Bind-mounts the workspace via lxc config device add (idempotent, random device name for parallel safety)
    • Forwards all relevant environment variables via --env flags to lxc exec
    • Cleans up the mounted device on process exit/signal
  • Repurposes config.image to store the container name (default: "gemini-sandbox", overridable via GEMINI_SANDBOX_IMAGE)
  • Updates docs/cli/sandbox.md with a new LXC section covering setup, quick start, and limitations

Related Issues

Closes #14627

How to Validate

Unit tests (no LXC required):

npm test -w @google/gemini-cli -- src/config/sandboxConfig.test.ts src/utils/sandbox.test.ts

Manual validation (Linux with LXC/LXD):

# Setup
snap install lxd
lxd init --auto
lxc launch ubuntu:24.04 gemini-sandbox

# Enable and run
export GEMINI_SANDBOX=lxc
gemini -p "print hello"

# Verify Gemini ran inside the container
lxc exec gemini-sandbox -- ps aux | grep gemini

# Other scenarios to test:
# - GEMINI_SANDBOX=lxc with container stopped → clear error message
# - GEMINI_SANDBOX_IMAGE=custom-name → uses that container name
# - Already inside sandbox (SANDBOX env set) → skips sandbox

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
@h30s h30s requested review from a team as code owners March 1, 2026 07:06
@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 introduces experimental support for LXC/LXD containers as a sandboxing mechanism within the Gemini CLI. This enhancement addresses the need for full-system container environments, which are crucial for specific tools like Snapcraft and Rockcraft that rely on services like systemd and snapd not typically available in standard Docker or Podman containers. The implementation allows users to leverage their pre-existing and managed LXC containers, with the Gemini CLI executing commands inside them and bind-mounting the workspace for seamless operation.

Highlights

  • LXC/LXD Sandbox Support: Introduced experimental LXC/LXD container sandbox support for Linux, enabling full system containers for tools like Snapcraft and Rockcraft that require systemd and snapd.
  • User-Managed Containers: Implemented a model where users manage their own LXC containers, with Gemini CLI running inside via lxc exec and bind-mounting the workspace at the same absolute path.
  • Configuration and Activation: Updated configuration to allow lxc as a sandbox command, activatable via GEMINI_SANDBOX=lxc environment variable or settings, and repurposed config.image to store the container name.
  • Documentation: Added comprehensive documentation for LXC setup, quick start, and limitations in docs/cli/sandbox.md.
  • Error Handling and Cleanup: Included robust error handling for container existence and status, along with automatic cleanup of bind-mounted devices on process exit.
Changelog
  • docs/cli/sandbox.md
    • Added a new section detailing LXC/LXD sandboxing, including prerequisites, quick setup, custom container naming, and limitations.
    • Updated the GEMINI_SANDBOX environment variable documentation to include lxc as a valid option.
  • packages/cli/src/config/sandboxConfig.test.ts
    • Modified the invalid command error message to include lxc.
    • Added new test cases to verify lxc command detection and error handling when lxc is specified but not found or when GEMINI_SANDBOX=lxc is set.
  • packages/cli/src/config/sandboxConfig.ts
    • Extended VALID_SANDBOX_COMMANDS to include lxc.
    • Added a comment explaining why lxc is not auto-detected.
  • packages/cli/src/utils/sandbox.test.ts
    • Expanded the spawn mock to handle lxc list and lxc config device add commands.
    • Introduced a new test suite for the LXC sandbox, covering successful execution, error handling for failed lxc list, stopped containers, and unfound containers.
  • packages/cli/src/utils/sandbox.ts
    • Implemented the start_lxc_sandbox asynchronous function to manage LXC container interactions, including validation, workspace bind-mounting, environment variable forwarding, and cleanup.
    • Integrated the call to start_lxc_sandbox within the main start_sandbox function when config.command is lxc.
  • packages/core/src/config/config.ts
    • Updated the SandboxConfig interface to include lxc as a possible value for the command property.
Activity
  • The author, h30s, created this pull request to introduce experimental LXC container sandbox support.
  • The pull request includes updates to documentation, new test cases, and core logic for LXC integration.
  • The author has validated the changes on Linux using npm run.
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

This pull request introduces experimental support for LXC/LXD containers as a sandboxing option, which is a great addition for Linux-specific workflows. The implementation follows the existing sandbox pattern, and the changes to configuration, tests, and documentation are thorough. However, I've found a critical command injection vulnerability in the new start_lxc_sandbox function. User-controlled input is used to construct shell commands with execAsync and execSync, which allows for arbitrary command execution. This must be addressed before merging. My review comment provides details on the vulnerability and how to fix it.

@h30s h30s force-pushed the feat/lxc-sandbox branch from b09c218 to a91787e Compare March 1, 2026 07:12
@gemini-cli gemini-cli bot added priority/p2 Important but can be addressed in a future release. area/platform Issues related to Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels Mar 1, 2026
@h30s
Copy link
Copy Markdown
Contributor Author

h30s commented Mar 1, 2026

Hi @scidomino When you’re free, could you please take a look to this PR. No rush thank you very much! 🙏

@scidomino
Copy link
Copy Markdown
Collaborator

@h30s I am no longer reviewing external PRs unless:

  1. The user is assigned to the issue.
  2. The issue is tagged with "help-wanted"
@h30s
Copy link
Copy Markdown
Contributor Author

h30s commented Mar 2, 2026

@scidomino I work on this issue but forgot to comment /assign before opening the PR. After submitting it, someone else added the assignment. The issue is tagged with help wanted, and I have addressed all the requirements. This was an honest mistake kindly consider reviewing the PR.

@scidomino
Copy link
Copy Markdown
Collaborator

@h30s ok. I will review. Please note that we now support "/unassign" so if the reason you didn't assign yourself is that you had already hit your 3 issue limit, know that this is not an issue anymore.

@scidomino
Copy link
Copy Markdown
Collaborator

Thanks for adding this experimental LXC support! The implementation is very well-contained and fits cleanly into the existing sandbox structure.

I noticed a few issues around process lifecycle management and documentation that we should address before merging:

1. Memory Leak & Unnecessary Process Listeners

In packages/cli/src/utils/sandbox.ts, the removeDevice function is created dynamically on each call to start_lxc_sandbox. Because it's a new reference each time, process.off(..., removeDevice) does not remove previous listeners. This will cause a memory leak (and eventually a MaxListenersExceededWarning) in long-running processes like the VS Code Companion.

Additionally, you only need to listen to the 'exit' event. The CLI already handles SIGINT and SIGTERM (via packages/cli/src/utils/cleanup.ts), eventually calling process.exit(), which guarantees the 'exit' event will fire.

Suggestion:

  • Remove the SIGINT and SIGTERM listeners.
  • Add process.off('exit', removeDevice) inside the sandboxProcess.on('close') handler so the listener is cleaned up when the sandbox exits naturally.
  // Remove the workspace device from the container when the process exits.
  const removeDevice = () => {
    try {
      execFileSync('lxc', [
        'config',
        'device',
        'remove',
        containerName,
        deviceName,
      ], { timeout: 2000 }); // See point 2
    } catch {
      // Best-effort cleanup; ignore errors on exit.
    }
  };
  
  // Only listen on 'exit'
  process.on('exit', removeDevice);
  
  // ... later in the close handler ...
  sandboxProcess.on('close', (code, signal) => {
    process.stdin.resume();
    process.off('exit', removeDevice); // Clean up the listener!
    removeDevice();
    // ...

2. execFileSync Hang Risk

Inside removeDevice(), execFileSync('lxc', ...) is called synchronously to unmount the workspace during process termination. If the LXC daemon is unresponsive, this will block the Node.js event loop and hang the process shutdown indefinitely.

Suggestion: Add a timeout to prevent hanging the CLI.

execFileSync('lxc', [...], { timeout: 2000 });

3. Incomplete Schema Documentation

The PR updates the SandboxConfig type and the markdown documentation but misses schemas/settings.schema.json.

Currently, the description for sandbox reads:

"Sandbox execution environment. Set to a boolean to enable or disable the sandbox, or provide a string path to a sandbox profile."

Suggestion: Update the schema description (both description and markdownDescription) in schemas/settings.schema.json to reflect that it also accepts explicit sandbox commands (e.g., "docker", "podman", "lxc").

@h30s
Copy link
Copy Markdown
Contributor Author

h30s commented Mar 3, 2026

Thanks for the review @scidomino! I have addressed the feedback by:

  • Fixing the process listener leak and cleaning up extra handlers in sandbox.ts
  • Adding a 2s timeout to the execFileSync cleanup call
  • Updating schemas/settings.schema.json to include "docker", "podman", and "lxc"

All 12 sandbox unit tests are passing!

@scidomino scidomino enabled auto-merge March 3, 2026 17:22
@scidomino
Copy link
Copy Markdown
Collaborator

@h30s broken lint. Please run npm run preflight before sending us code to review. It'll save you time. It'll save me time.

@h30s
Copy link
Copy Markdown
Contributor Author

h30s commented Mar 3, 2026

@h30s broken lint. Please run npm run preflight before sending us code to review. It'll save you time. It'll save me time.

I’ve run npm run preflight and fixed the lint issues. Not sure why it flagged again since it’s passing locally now, but I’ll double-check.

@scidomino
Copy link
Copy Markdown
Collaborator

@h30s The error message in the checks about say:

Settings JSON schema is out of date. Run npm run schema:settings to regenerate.

auto-merge was automatically disabled March 4, 2026 13:16

Head branch was pushed to by a user without write access

@h30s h30s force-pushed the feat/lxc-sandbox branch from 4f002db to 4af9e25 Compare March 4, 2026 13:16
h30s added 3 commits March 4, 2026 18:58
…ema.json

Updated the sandbox description in settingsSchema.ts to mention explicit
sandbox commands (docker, podman, lxc) and regenerated the JSON schema
via 'npm run schema:settings' to fix CI schema validation.
@h30s h30s force-pushed the feat/lxc-sandbox branch from 4af9e25 to 14b13d4 Compare March 4, 2026 13:29
@h30s
Copy link
Copy Markdown
Contributor Author

h30s commented Mar 4, 2026

@scidomino I’ve regenerated the settings schema and rerun npm run preflight. Everything should be aligned now. PTAL sorry for the inconvenience.

@scidomino scidomino enabled auto-merge March 4, 2026 16:58
auto-merge was automatically disabled March 4, 2026 17:25

Head branch was pushed to by a user without write access

@scidomino scidomino enabled auto-merge March 4, 2026 17:31
@scidomino scidomino added this pull request to the merge queue Mar 4, 2026
Merged via the queue into google-gemini:main with commit 7176609 Mar 4, 2026
26 of 27 checks passed
neeraj-par pushed a commit to neeraj-par/gemini-cli that referenced this pull request Mar 4, 2026
BryanBradfo pushed a commit to BryanBradfo/gemini-cli that referenced this pull request Mar 5, 2026
struckoff pushed a commit to struckoff/gemini-cli that referenced this pull request Mar 6, 2026
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
yashodipmore pushed a commit to yashodipmore/geemi-cli that referenced this pull request Mar 21, 2026
SUNDRAM07 pushed a commit to SUNDRAM07/gemini-cli that referenced this pull request Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/platform Issues related to Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! priority/p2 Important but can be addressed in a future release.

2 participants