You install Gemini CLI on a managed laptop, run your first prompt, and get back something like UNABLE_TO_GET_ISSUER_CERT_LOCALLY or unable to get local issuer certificate. Nothing is wrong with your install. Your company's firewall is decrypting and re-encrypting your HTTPS traffic for inspection, presenting its own root CA on every connection — and Node.js, which Gemini CLI runs on, doesn't trust that CA. The same class of problem hits Google Antigravity, because it's a VS Code/Electron fork running Node under the hood.
This is the enterprise networking guide I wish I'd had: the TLS fix, proxy variables, Vertex AI auth for headless use, sandbox cert injection, and the platform-specific bugs that will eat an afternoon if you don't know about them.
The root cause: TLS interception
Corporate proxies like Zscaler and Netskope perform TLS interception. They terminate your TLS session, inspect the plaintext, then re-encrypt with a certificate signed by an internal CA. Your OS trust store usually has that CA — but Node.js ships its own bundled CA list and ignores the OS store by default. So the browser works and Gemini CLI doesn't.
There's a clean order of remediation.
# 1. Try the OS trust store first (corporate CA is usually already there)
export NODE_USE_SYSTEM_CA=1
# 2. If that doesn't work, point Node at the corporate root CA (PEM format)
export NODE_EXTRA_CA_CERTS=/path/to/your/corporate-ca.crt
NODE_USE_SYSTEM_CA=1 tells Node to read the operating system's native certificate store, which is the lowest-maintenance fix because IT has typically already pushed the CA there. The caveat: Node's support for the Windows system store has a long history (see nodejs/node #51537), so whether it works depends on your installed Node version. If it doesn't, fall back to NODE_EXTRA_CA_CERTS. You can set both — Node will then trust its bundled CAs, the system CAs, and your extra file simultaneously. If you have multiple internal CAs, concatenate them into a single PEM file.
Do not reach for
NODE_TLS_REJECT_UNAUTHORIZED=0. It disables certificate validation for the entire process — every connection, not just your proxy — and reopens you to man-in-the-middle attacks. Trust the specific CA instead.
Setting the CA on each platform
# macOS / Linux (shell rc or per-session)
export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.crt
# Windows PowerShell — current session
$env:NODE_EXTRA_CA_CERTS="C:\certs\CorpRootCA.pem"
# Windows — persist machine-wide
[Environment]::SetEnvironmentVariable("NODE_EXTRA_CA_CERTS","C:\certs\CorpRootCA.pem","Machine")
One gotcha worth verifying per-tool: across Node-based AI tools, NODE_EXTRA_CA_CERTS is honored on some connection paths but not others. Cline's issue #8816, for instance, reports it being ignored for API calls because that path uses an HTTP client or undici fetch route that doesn't read the Node CA store the same way. Don't assume it's wired up everywhere — test the actual failing operation.
Proxy environment variables
Gemini CLI reads the standard proxy variables, and a PR added ALL_PROXY/all_proxy support too:
export HTTPS_PROXY=http://user:p%40ss@proxy.corp:8080
export HTTP_PROXY=http://user:p%40ss@proxy.corp:8080
export NO_PROXY=localhost,127.0.0.1
Two things bite people here.
Percent-encode credentials. A password of p@ss must be written p%40ss in the URL. Unencoded @, :, and / break URL parsing.
Always exclude localhost. Local MCP servers run on 127.0.0.1; if the proxy captures that traffic you'll see fetch failed / Connection closed. Putting localhost,127.0.0.1 in NO_PROXY fixes most MCP issues. Be aware the CLI's proxy handling has had bugs: PR #4100 switched to EnvHttpProxyAgent to correctly honor env settings, issue #23372 reported the local-bypass not recognizing env variables, and issue #3340 requested a NO_PROXY-for-localhost behavior so MCP servers aren't proxied. If your version misbehaves, those are the threads to check.
Beyond env vars, Gemini CLI also exposes a proxy field in settings.json and a --proxy flag. Precedence: --proxy > settings.json proxy > environment variables.
Authentication behind the proxy
OAuth browser login is the recommended flow for individuals, but it's the most fragile behind a TLS-inspecting proxy. A confirmed failure mode is:
Failed to exchange authorization code for tokens: request to
https://oauth2.googleapis.com/token failed, reason: self-signed
certificate in certificate chain
That's the same CA-trust problem — fix it by trusting the proxy CA at the OS level and via NODE_EXTRA_CA_CERTS. There's also a nasty UX bug (issue #2300): after OAuth fails the login screen can hang, blocking you from switching to API-key auth or even pressing Ctrl+C, forcing you to force-close the terminal.
For enterprise and CI, skip OAuth and use Vertex AI. The auth methods Gemini CLI supports:
| Method | Key variables | Best for |
|---|---|---|
| OAuth (Google login) | — | Individuals, interactive |
| Gemini API key | GEMINI_API_KEY | Quick personal use |
| Vertex via ADC | gcloud auth application-default login, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION | Interactive enterprise |
| Vertex via service account | GOOGLE_APPLICATION_CREDENTIALS | CI/CD, headless |
| Vertex via GCP API key | GOOGLE_API_KEY | Vertex with a key |
For all Vertex modes set GOOGLE_GENAI_USE_VERTEXAI=true. The docs explicitly recommend the service-account JSON key (GOOGLE_APPLICATION_CREDENTIALS) for non-interactive environments, CI/CD, or where the org restricts user-based ADC or API-key creation; the account needs the Vertex AI User role (roles/aiplatform.user). If you use ADC, unset GOOGLE_API_KEY and GEMINI_API_KEY first, or the CLI may grab a key instead of ADC. Admins can also constrain available models with the org policy vertexai.allowedModels.
The sandbox: where env vars disappear
Gemini CLI can run the agent in a sandbox via GEMINI_SANDBOX, which accepts true | docker | podman | sandbox-exec | runsc | lxc (sandbox-exec is macOS Seatbelt, runsc is gVisor, lxc is experimental Linux). Here's the gotcha that catches everyone behind a proxy:
The sandbox documentation does not describe how NODE_EXTRA_CA_CERTS, the CA file, or proxy variables get into the container. They don't, automatically. Env vars and cert files you set on the host are not present inside the container, so your carefully configured TLS trust evaporates the moment work moves into the sandbox. You have to inject them manually — SANDBOX_FLAGS lets you pass extra docker/podman arguments to mount the cert and forward the env var:
export SANDBOX_FLAGS="--security-opt label=disable"
SANDBOX_SET_UID_GID controls host UID/GID mapping on Linux. And if you want to restrict what the agent reaches, GEMINI_SANDBOX_PROXY_COMMAND runs a proxy alongside the sandbox — the shipped example proxy listens on port 8877 and only allows HTTPS CONNECT tunnels to an ALLOWED_DOMAINS allowlist (e.g. example.com, googleapis.com) on port 443, denying everything else. That's a clean egress-allowlist pattern for locking down an agent. If the goal is to keep model traffic off the TLS-inspected path entirely, another option is a local-first, OpenAI-compatible gateway like Wide Area AI, which routes inference to your own on-prem hardware first and only fails over to cloud providers when local nodes are unavailable — any tool that lets you set an OpenAI base URL can point at it, sidestepping much of the proxy-and-cert dance for requests served locally.
The WSL Docker trap
If you're on WSL 2 with native Docker Engine (no Docker Desktop), the Docker sandbox can silently fail to activate (issue #2345). The status bar shows no sandbox instead of sandbox (docker) and the CLI falls back to no-sandbox mode even with {"sandbox":"docker"} set and the daemon running. The likely cause is how the CLI discovers the Docker socket (/var/run/docker.sock) in non-Docker-Desktop WSL setups. No official workaround is documented — assume Docker Desktop is the supported path on Windows/WSL for now.
Antigravity specifics
Antigravity is a standalone agentic IDE built as a heavily modified VS Code fork (reportedly drawing on Windsurf/Codeium's codebase, itself a VS Code fork). Because it's Electron/Node, the same NODE_EXTRA_CA_CERTS applies. A community proxy guide recommends: set HTTPS_PROXY/HTTP_PROXY/NO_PROXY (always include localhost and 127.0.0.1), percent-encode credentials, point NODE_EXTRA_CA_CERTS at the corporate root CA PEM, and trust the CA at both OS and Node level for Zscaler/Netskope. Same warning applies: never use NODE_TLS_REJECT_UNAUTHORIZED=0.
A suggested FQDN-based firewall allowlist (Google rotates IPs, so allowlist by name):
| Domain | Purpose |
|---|---|
antigravity.google | Auth / surfaces |
accounts.google.com, oauth2.googleapis.com | Sign-in |
generativelanguage.googleapis.com | Gemini API |
*.googleusercontent.com | Assets |
storage.googleapis.com | Model delivery |
Diagnose proxy reachability with curl -x "$HTTPS_PROXY" -I https://generativelanguage.googleapis.com/. A 403 Forbidden on generativelanguage.googleapis.com usually means the domain is blocked. As covered in the FAQ, login loops behind proxies have been reported as Windows-specific even with no-bump allowlisting, with no confirmed fix.
One security note for hardening: Antigravity has a browser-URL allowlist stored as a local text file initialized with just localhost, prompting an "always allow" on non-allowlisted navigation. Google has classified data exfiltration via allowlisted URLs (e.g. webhook.site appearing in defaults) as intended behavior — so audit that allowlist if you care about exfiltration paths.
Bottom line
The single biggest issue is TLS interception, and the fix order is consistent across both tools: try NODE_USE_SYSTEM_CA=1, then NODE_EXTRA_CA_CERTS pointing at your corporate root CA PEM — never NODE_TLS_REJECT_UNAUTHORIZED=0. Set proxy variables with percent-encoded credentials and localhost,127.0.0.1 in NO_PROXY to keep MCP traffic local. For anything headless or CI, use Vertex AI with a service-account key rather than OAuth. Remember the sandbox doesn't inherit your host's certs or proxy vars — inject them, and treat Docker Desktop as the supported WSL path. When something still breaks, the layer underneath both tools is Node.js, so the Node.js enterprise network configuration guide is the authoritative reference. These tools move fast; verify the specific failing operation rather than assuming a global fix took hold.