Skip to main content
Home/Blog/Gemini CLI & Antigravity on Corporate Networks: SSL/TLS, Proxies, and Gotchas
IT Operations

Gemini CLI & Antigravity on Corporate Networks: SSL/TLS, Proxies, and Gotchas

A practical guide to running Gemini CLI and Google Antigravity behind corporate TLS-inspecting proxies — NODE_EXTRA_CA_CERTS, proxy env vars, Vertex AI auth, sandbox cert injection, and the WSL/login bugs that bite enterprise users.

By Sean

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:

MethodKey variablesBest for
OAuth (Google login)Individuals, interactive
Gemini API keyGEMINI_API_KEYQuick personal use
Vertex via ADCgcloud auth application-default login, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATIONInteractive enterprise
Vertex via service accountGOOGLE_APPLICATION_CREDENTIALSCI/CD, headless
Vertex via GCP API keyGOOGLE_API_KEYVertex 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):

DomainPurpose
antigravity.googleAuth / surfaces
accounts.google.com, oauth2.googleapis.comSign-in
generativelanguage.googleapis.comGemini API
*.googleusercontent.comAssets
storage.googleapis.comModel 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.

Frequently Asked Questions

Find answers to common questions

Both errors mean Node.js doesn't trust the certificate your TLS-inspecting proxy (Zscaler, Netskope, etc.) presents. First try NODE_USE_SYSTEM_CA=1 so Node reads the OS trust store where your corporate CA is often already installed. If that doesn't work, set NODE_EXTRA_CA_CERTS to the absolute path of your corporate root CA in PEM format, e.g. export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.crt. The same fix resolves OAuth token-exchange failures against oauth2.googleapis.com.

Try NODE_USE_SYSTEM_CA=1 first — it tells Node to use the operating system's native certificate store, where IT has usually already deployed the corporate CA, so no file management is needed. If your Node version doesn't honor the system store (notably an issue on older Node on Windows), fall back to NODE_EXTRA_CA_CERTS pointing at the PEM file. You can set both; Node will trust its bundled CAs, the system CAs, and your extra file together.

Gemini CLI respects the standard HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables, and a PR also added ALL_PROXY/all_proxy. There is also a proxy field in settings.json and a --proxy CLI flag. Precedence is: --proxy overrides settings.json proxy, which overrides the environment variables. Always include localhost,127.0.0.1 in NO_PROXY so local MCP servers aren't routed through the proxy.

Put credentials in the proxy URL and percent-encode any special characters in the password. For example, a password of p@ss becomes p%40ss, giving a URL like http://user:p%40ss@proxy.corp:8080. Failing to encode @, :, /, and similar characters is a common reason authenticated-proxy URLs silently fail to parse.

Set GOOGLE_GENAI_USE_VERTEXAI=true, then point GOOGLE_APPLICATION_CREDENTIALS at a service-account JSON key file. The service account needs the Vertex AI User role (roles/aiplatform.user). The official docs explicitly recommend this method for non-interactive, CI/CD, or headless environments, or where the org restricts user-based ADC and API-key creation. For interactive ADC instead, use gcloud auth application-default login plus GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION — and unset any GOOGLE_API_KEY/GEMINI_API_KEY first so the CLI doesn't grab a key instead of ADC.

The most common cause is the proxy capturing localhost traffic — your MCP server runs on 127.0.0.1 but the CLI tries to reach it through the corporate proxy. Add localhost,127.0.0.1 to NO_PROXY. Other causes are transport misconfiguration (url vs httpUrl, stdio vs url) and PATH/env stripping under Homebrew or nvm on macOS. Debug with the Debug Console (Ctrl+O) and /mcp reload.

No. NODE_TLS_REJECT_UNAUTHORIZED=0 disables all TLS certificate validation for the entire process, which removes protection against man-in-the-middle attacks on every connection — not just your proxy. Trust the specific corporate CA via NODE_EXTRA_CA_CERTS (and at the OS level) instead. Community proxy guides explicitly warn against the reject-unauthorized override for this reason.

Reported login loops persist even after allowlisting google.com, googleapis.com, gvt1.com, and open-vsx.org with SSL no-bump (no TLS interception). Symptoms include a missing 'state key' (the login process is killed before the OAuth token returns), repeated sign-in despite the browser showing you authenticated, and errors like connect ECONNREFUSED 127.0.0.1:35310. In the reported thread the problem was Windows-specific while macOS and Linux worked; no confirmed fix was documented. Since Antigravity is a VS Code/Electron (Node) fork, set NODE_EXTRA_CA_CERTS and your proxy vars, and check the logs at ~/Library/Logs/Antigravity/main.log (macOS) or ~/.config/Antigravity/logs/main.log (Linux).

Let's turn this knowledge into action

Our experts can help you apply these insights to your specific situation. No sales pitch — just a technical conversation.