Skip to content

fix: propagate proxy settings to SSH environment#1012

Merged
EhabY merged 6 commits into
mainfrom
fix/eng-2919-proxycommand-proxy-env
Jun 25, 2026
Merged

fix: propagate proxy settings to SSH environment#1012
EhabY merged 6 commits into
mainfrom
fix/eng-2919-proxycommand-proxy-env

Conversation

@EhabY

@EhabY EhabY commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Propagate VS Code's proxy settings to the spawned coder ssh ProxyCommand so connections work behind a proxy. The coder CLI has no proxy flag; it reads HTTP_PROXY/HTTPS_PROXY/NO_PROXY from its environment like any Go HTTP client, so the job is getting those variables into that process.

  • HTTP_PROXY/HTTPS_PROXY from http.proxy (trimmed; blank ignored).
  • NO_PROXY from coder.proxyBypass, falling back to http.noProxy. Bypass matching is left to the CLI's Go NO_PROXY parser, so it applies per-connection to whatever host the CLI dials.
  • Watch these settings to prompt for a reload when the SSH proxy environment changes.

A single applySshEnvironment call applies the env via two mechanisms, covering both Remote-SSH modes:

  • process.env: inherited by ssh spawned as a child process (useLocalServer=true).
  • EnvironmentVariableCollection: inherited by ssh spawned in a terminal (useLocalServer=false), which can't see process.env.

Both run unconditionally, since the spawn path isn't reliably predictable from the setting and neither mechanism covers the other's mode. The collection only touches local terminals, so workspace terminals are unaffected. We mutate the environment instead of writing the SSH config, keeping credentialed URLs off disk and windows independent.

Testing

  • pnpm lint
  • pnpm typecheck
  • pnpm test

Manual testing matrix

Verified the proxy variables reach the spawned coder ssh ProxyCommand by injecting a marker through each mechanism and reading the live ssh process's environment (an ssh wrapper via remote.SSH.path dumping env).

Editor Remote-SSH mode Reaches ssh? Via
VS Code (MS) useLocalServer=true process.env
VS Code (MS) useLocalServer=false EnvironmentVariableCollection
Cursor / Antigravity / Devin / VSCodium default process.env (local-server path)

Notes:

  • useLocalServer=false runs the connection ssh as the shell of a hidden terminal, so it inherits the terminal environment (the collection), not the extension host's process.env. Modifying process.env does not reach terminals; the collection is the documented mechanism (microsoft/vscode#88718).
  • Remote-SSH also runs an ssh -V capability probe spawned directly by the extension host, which always shows process.env regardless of mode. Check the real connection process (the -D ... bash one), not the probe.

Closes #1010

@linear-code

linear-code Bot commented Jun 17, 2026

Copy link
Copy Markdown

ENG-2919

@EhabY EhabY self-assigned this Jun 17, 2026
@EhabY EhabY force-pushed the fix/eng-2919-proxycommand-proxy-env branch 3 times, most recently from db5ca20 to da8f590 Compare June 18, 2026 13:08
@EhabY EhabY requested a review from code-asher June 22, 2026 13:40
Comment thread src/core/dismissibleNotifier.ts Outdated
Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/environment.ts Outdated
: "";

return {
...(proxy ? { HTTP_PROXY: proxy, HTTPS_PROXY: proxy } : {}),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it right to set both http_proxy and https_proxy? If the user set http_proxy I imagine we should not set it on https_proxy, and maybe vice versa. idk why someone would have Coder on an http URL though, other than for maybe testing.

@EhabY EhabY Jun 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's only one source here: VS Code's core http.proxy, which it applies to all traffic regardless of scheme. No separate http/https values to split apart, so we just fan it out to both

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http.proxy is only populated if the user fills it out right? The plugin also supports the environment variables http_proxy and https_proxy (and others) but not sure if VS Code will populate the http.proxy setting if these are set.

Looks like we are only passing http.proxy and coder.proxyBypass || http.noProxy. Instead we should copy everything used in proxy.ts (or break it out to share in some way).

That includes the setting, and the environment variablesnpm_config_http_proxy, npm_config_https_proxy, http_proxy, https_proxy, npm_config_proxy, and all_proxy (both lowercase and uppercase), then for no proxy we have the settings plus npm_config_no_proxy and no_proxy environment variables (both lowercase and uppercase).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right but for the local server case those would already be inherited anyway 🤔 Would it make sense to add them for the non-local server case? Unless VS Code already preserves them.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tested actually and in both cases all env variables are inherited still, it's just that useLocalServer=false does not inherit from the current process.env. In that case, we do not need to handle env variables, only the setting -> env variable

Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/remote.ts Outdated
Comment thread src/remote/remote.ts Outdated
EhabY added 3 commits June 24, 2026 14:43
Set HTTP_PROXY/HTTPS_PROXY/NO_PROXY on the extension host's process.env
from VS Code's http.proxy / coder.proxyBypass / http.noProxy so the
spawned `coder ssh` ProxyCommand inherits them. Mutating process.env
avoids writing a credentialed proxy URL to the SSH config and keeps
multiple windows onto the same workspace independent.

Watch the proxy settings so the user is prompted to reload when SSH
proxy behavior changes.
When a proxy applies to the deployment but remote.SSH.useLocalServer is off,
the spawned SSH connection won't inherit the proxy env. Surface a dismissable
warning offering to enable the local server, via a reusable
showDismissibleNotification helper.
Move showDismissibleNotification from util into a DismissibleNotifier
class under core: it holds globalState and constrains keys to a known
DismissibleNotificationKey set, wired through ServiceContainer.

Rename applySshProxyEnvironment to applySshEnvironment, generalize its
doc to "SSH-related environment variables", keep the internal env type
unexported, and order the file public-API first.

Make the useLocalServer warning a blocking warning modal so the setting
is written (via the jsonc settings util, not cfg.update) before ssh
spawns, which lets it apply without a window reload.
@EhabY EhabY force-pushed the fix/eng-2919-proxycommand-proxy-env branch from df5620b to c025edc Compare June 24, 2026 12:15
@EhabY EhabY force-pushed the fix/eng-2919-proxycommand-proxy-env branch from c025edc to 2da64c3 Compare June 24, 2026 13:10
@EhabY EhabY requested a review from code-asher June 24, 2026 13:13
Remote-SSH with `useLocalServer=false` spawns ssh in a terminal, which does
not inherit the extension host's process.env, so the proxy never reached it.
Also apply the proxy via VS Code's EnvironmentVariableCollection, which the
terminal-spawned ssh inherits; process.env still covers the local-server
(child-process) path. `applySshEnvironment` now applies both.

Drop `warnIfProxyEnvNotInherited` and the `DismissibleNotifier` it relied on:
the proxy now reaches ssh in both modes, so nagging users to enable the local
server is obsolete.

@code-asher code-asher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find on the terminal env!

Comment thread src/remote/environment.ts Outdated
Comment thread src/remote/environment.ts
@EhabY EhabY merged commit c62d3c1 into main Jun 25, 2026
13 checks passed
@EhabY EhabY deleted the fix/eng-2919-proxycommand-proxy-env branch June 25, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ProxyCommand for the SSH tunnel does not receive http.proxy

2 participants