[BUG] Desktop SSH remote fails ("Failed to upload file: file does not exist") through JumpServer/Koko bastion — server bootstrap uses SFTP upload; VS Code Remote-SSH works via exec channel
Summary
The desktop app's SSH remote session fails to connect through a JumpServer / Koko bastion with:
[error] [RemoteServerController] Connection failed: Failed to upload file: file does not exist
The interactive shell connection itself works perfectly (it reaches the target asset). The failure is in the server-binary bootstrap step, which uploads the remote server via the SFTP subsystem. JumpServer's koko proxy jails SFTP to a configured SFTP_ROOT (e.g. /tmp) and does not expose the asset's real filesystem, so the absolute upload path (e.g. /home/<user>/...) doesn't exist in the SFTP view → "file does not exist".
VS Code Remote-SSH connects to the same asset through the same bastion without issue, because it bootstraps its server over the SSH exec channel (remote self-download / tar-over-stdin) rather than SFTP. This strongly suggests the desktop app should adopt the same exec-channel bootstrap mechanism.
Environment
- Claude desktop app: 1.15200.0
- OS (client): macOS 14 (Darwin 24.6.0)
- Bastion: JumpServer (open-source PAM), SSH endpoint served by the
kokocomponent on port 2222 - Target asset: Linux (Ubuntu), reachable only via the bastion
~/.ssh/confighost that works for shell:
````
Host devhost
HostName jump.example.com
User alice@ubuntu@10.0.0.42 # koko direct-login routing: <jms_user>@<account>@<asset_ip>
Port 2222
Steps to reproduce
- Stand up (or use) a JumpServer/Koko bastion that fronts a Linux asset. Connect via koko's direct-login username syntax
user@account@asset_ip. - Add this host as an SSH connection in the desktop app and start a session.
- Connection fails with
Failed to upload file: file does not exist.
Root-cause analysis (with evidence)
Koko is an application-layer SSH proxy (not OpenSSH), which breaks every transport the desktop app relies on for bootstrap:
- SFTP is jailed, not a passthrough to the asset. Over the working shell channel,
pwdis/home/<user>and/etc,/home/<user>are visible. Over SFTP on the same connection,pwdis/and both/home/<user>and/etcreport "not found" — the SFTP view is koko'sSFTP_ROOTjail (contents looked like/tmp). So the app's SFTPputto an absolute asset path cannot resolve → "file does not exist".
- TCP/stdio forwarding is disabled. Both
ProxyJumpandProxyCommand ssh -W %h:%p <jump>fail with:
```
Stdio forwarding request failed: Session open refused by peer
direct-tcpip`, so there is no ProxyJump/ProxyCommand fallback for this bastion.
koko does not implement
- The desktop app uses a bundled Node
ssh2client, which (per #40967) does not support ProxyJump on macOS and reimplements config resolution. So even the documented "use ProxyCommand instead of ProxyJump" workaround is unavailable here.
Net: the only transport koko permits is the interactive shell/exec channel + its own (jailed) SFTP. The app's bootstrap needs SFTP-to-asset, which koko never provides.
Why VS Code Remote-SSH works through the same bastion
Confirmed on the target asset: ~/.vscode-server/ exists and contains multiple Stable-<commit> server installs. VS Code:
- shells out to the system
sshbinary (full OpenSSH parity with~/.ssh/config, including koko'suser@account@iprouting trick), and - bootstraps its server over the exec channel — the remote host downloads the server itself via its own
curl/wget, or VS Code streams a tarball over stdin (… | tar -xz). No SFTP, no port forwarding.
The asset has outbound HTTPS and curl/wget/tar, so a remote self-download bootstrap would succeed for the desktop app too.
Suggested fix
Bootstrap the remote server without SFTP and without TCP forwarding, mirroring VS Code Remote-SSH:
- Run a bootstrap script over the exec channel; have the remote host download the server binary itself (curl/wget), or stream the binary over the exec channel's stdin (
base64/tar), instead of an SFTPput. - Optionally drive the connection via the system
sshbinary so all~/.ssh/configfeatures (ProxyJump, ProxyCommand, ControlMaster, app-layer-proxy username routing) work transparently.
Either change would make the desktop app work through application-layer PAM bastions like JumpServer/Koko, Teleport, etc., which are common in enterprise environments.
Related (closed) issues
- #40967 — ProxyJump not supported on Windows/Mac; ProxyCommand issues. (Closed.)
- #44838 — requires ProxyCommand instead of ProxyJump (closed as duplicate of #40967).
These cover the ProxyJump/ProxyCommand angle; this issue is a distinct root cause — the SFTP-based server bootstrap failing against a jailed-SFTP / no-forwarding PAM bastion, where VS Code's exec-channel bootstrap succeeds.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗