[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

Open 💬 1 comment Opened Jun 23, 2026 by OliverTzz98

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 koko component on port 2222
  • Target asset: Linux (Ubuntu), reachable only via the bastion
  • ~/.ssh/config host 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

  1. 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.
  2. Add this host as an SSH connection in the desktop app and start a session.
  3. 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:

  1. SFTP is jailed, not a passthrough to the asset. Over the working shell channel, pwd is /home/<user> and /etc, /home/<user> are visible. Over SFTP on the same connection, pwd is / and both /home/<user> and /etc report "not found" — the SFTP view is koko's SFTP_ROOT jail (contents looked like /tmp). So the app's SFTP put to an absolute asset path cannot resolve → "file does not exist".
  1. TCP/stdio forwarding is disabled. Both ProxyJump and ProxyCommand ssh -W %h:%p <jump> fail with:

``
Stdio forwarding request failed: Session open refused by peer
`
koko does not implement
direct-tcpip`, so there is no ProxyJump/ProxyCommand fallback for this bastion.

  1. The desktop app uses a bundled Node ssh2 client, 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 ssh binary (full OpenSSH parity with ~/.ssh/config, including koko's user@account@ip routing 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:

  1. 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 SFTP put.
  2. Optionally drive the connection via the system ssh binary so all ~/.ssh/config features (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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗