Menu

#40 provision_auth: setEnv broken for non-Claude providers on macOS and Windows SSH

closed
nobody
None
2026-04-08
2026-04-01
Anonymous
No

Originally created by: kumaakh

Summary

provision_auth with api_key parameter fails to make the key visible to subsequent execute_prompt / execute_command calls on all three platforms (macOS, Windows, Linux). The env var is written to shell profiles that are never sourced in non-interactive SSH sessions.

Found during multi-provider testing with Gemini CLI on macOS (192.168.1.13), Windows (192.168.1.25), and Linux (192.168.1.102).

Root Cause

setEnv() in the OS command layer writes to the wrong shell profiles per platform:

macOS (src/os/macos.ts:20-29)

Writes to .bashrc, .zshrc, .profile — but not .zshenv.
macOS defaults to zsh. SSH non-interactive sessions (ssh user@host 'command') only source ~/.zshenv, not ~/.zshrc or ~/.profile. So any env var set via provision_auth is invisible to fleet commands.

Windows (src/os/windows.ts)

Writes bash-style export VAR=val >> ~/.bashrc commands — but Windows OpenSSH server runs PowerShell, not bash. These profiles are never read. The correct approach is [System.Environment]::SetEnvironmentVariable("NAME", "VALUE", "User") and/or writing to the PowerShell $PROFILE.

Linux (src/os/linux.ts)

Writes to .bashrc and .profile — but non-interactive SSH sessions on many Linux systems (e.g. Ubuntu) do not source any user dotfiles. Confirmed: env vars set in .bashrc and .profile are not visible via env | grep GEMINI in SSH command execution. /etc/environment is the only file read, but requires root. ~/.ssh/rc runs in a subshell so exports don't propagate.

Broader design issue

The problem is not just setEnv() — it's that buildAgentPromptCommand() and execute_command don't inject provisioned env vars into the command. Even if setEnv() writes to every possible dotfile, non-interactive SSH sessions may not source any of them depending on OS and SSH server configuration.

Recommended fix: Rather than relying on shell profiles, fleet should store provisioned env vars in its own member config and inject them (e.g. export GEMINI_API_KEY="..." &&) into every command built by buildAgentPromptCommand(), similar to how CLAUDE_PATH already injects export PATH="$HOME/.local/bin:$PATH" &&.

This would make auth work reliably regardless of which dotfiles the SSH session sources.

Reproduction

  1. Register a remote Gemini member on any platform
  2. provision_auth with api_key — reports success
  3. execute_prompt with any prompt — fails with:

    Please set an Auth method in your ~/.gemini/settings.json or specify one of the following environment variables before running: GEMINI_API_KEY

Workarounds used during testing

Platform Workaround
macOS echo 'export GEMINI_API_KEY="..."' >> ~/.zshenv
Windows [System.Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "...", "User")
Linux Inline export GEMINI_API_KEY="..." && before gemini command

Additional findings

  • Gemini CLI requires Node 22+: Node 20 causes silent failures (exit 0, no output). Node 18 crashes with SyntaxError: Invalid regular expression flags. Fleet's update_agent_cli or install docs should note this.
  • Gemini CLI settings.json does NOT support API keys: Despite the error message suggesting "set an Auth method in your settings.json", only env vars work for API key auth. Tested apiKey, auth.apiKey, GEMINI_API_KEY as JSON keys — all rejected.
  • CLAUDE_PATH is Claude-specific (src/os/linux.ts:6): Only adds ~/.local/bin to PATH. Works for Gemini if the user installs gemini there, but the constant name and intent are provider-specific. Consider renaming to CLI_PATH and including common npm global paths.

Related

Tickets: #26
Tickets: #27
Tickets: #35
Tickets: #38

Discussion

  • Anonymous

    Anonymous - 2026-04-02

    Originally posted by: kumaakh

    Bug: OOB API key terminal doesn't support paste

    Found during integration testing. The OOB terminal window that opens for API key entry does not support clipboard paste (Ctrl+V / right-click paste). API keys are long random strings that cannot be typed manually — paste is essential.

    The SSH password OOB may have the same limitation but it's less noticeable since passwords can be typed from memory.

    Fix needed: The terminal input mode must allow paste. Check if the input is using raw/secure mode that blocks paste, and switch to a mode that allows it while still hiding the input (like read -s with paste support).

     
  • Anonymous

    Anonymous - 2026-04-08

    Originally posted by: kumaakh

    Fixed: src/utils/auth-env.ts implements buildAuthEnvPrefix() which decrypts provisioned env vars and injects them inline before every command (export VAR=val && on Linux/macOS; $env:VAR='val'; on Windows). Used in execute-prompt.ts:122 and execute-command.ts:133. No longer relies on shell profiles that non-interactive SSH sessions don't source.

     
  • Anonymous

    Anonymous - 2026-04-08

    Ticket changed by: kumaakh

    • status: open --> closed
     

Log in to post a comment.

MongoDB Logo MongoDB