Skip to content

feat(ssh): support proxyjump, proxy command, forwardagent#2151

Merged
jschwxrz merged 11 commits into
mainfrom
jona/eng-1030-support-proxyjump-and-forwardagent-in-ssh-connections
May 21, 2026
Merged

feat(ssh): support proxyjump, proxy command, forwardagent#2151
jschwxrz merged 11 commits into
mainfrom
jona/eng-1030-support-proxyjump-and-forwardagent-in-ssh-connections

Conversation

@jschwxrz
Copy link
Copy Markdown
Collaborator

No description provided.

@jschwxrz jschwxrz requested a review from Davidknp May 21, 2026 03:47
…-proxyjump-and-forwardagent-in-ssh-connections

# Conflicts:
#	src/main/core/tasks/provisionTask.ts
@jschwxrz jschwxrz marked this pull request as ready for review May 21, 2026 17:07
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR adds ProxyJump, ProxyCommand, and ForwardAgent support to SSH connections, alongside a major internal restructuring: the SSH config parser, connect-config resolver, connection manager, and test-connection flow have all been split into focused modules and are now dependency-injectable for testing.

  • New proxy transport layer (transports.ts) spawns a child ssh process for ProxyJump/ProxyCommand with strict regex validation of all substitution tokens to prevent shell injection.
  • New resolveSshConnectConfig pipeline assembles ConnectConfig from auth, ForwardAgent, and proxy sources; for alias-backed connections, both ProxyJump and ProxyCommand are sourced exclusively from ssh -G output, while manual connections only support ProxyJump stored in the DB.
  • Renderer form gains an SSH config alias selector plus an expandable Advanced section with ProxyJump and ForwardAgent toggle; alias-backed fields are rendered as read-only and updated via useEffect when the resolved ssh -G data arrives.

Confidence Score: 5/5

The change is safe to merge; proxy transport, auth, and ForwardAgent modules are well-structured with strict input validation and comprehensive test coverage.

All core paths are correctly implemented. The two findings are cosmetic/UX issues in the renderer form that do not affect connection correctness or data integrity.

ssh-connection-form-model.ts (auth-type default) and add-ssh-conn-modal.tsx (name-clear on alias reset) are the only files with actionable feedback.

Important Files Changed

Filename Overview
src/main/core/ssh/transport/transports.ts New file implementing ProxyJump and ProxyCommand transport spawning with strict regex guards on all substitution tokens.
src/main/core/ssh/connect/resolve-ssh-connect-config.ts New core resolver assembling ConnectConfig from auth, ForwardAgent, and proxy sources with correct ProxyCommand > ProxyJump precedence.
src/main/core/ssh/connect/ssh-connect-auth.ts IdentityFilteredAgent now conditionally assigns getStream only when the inner agent supports it, fixing the previously flagged unconditional-getStream hang.
src/renderer/lib/components/add-ssh-conn-modal.tsx UI extended with alias selector, ForwardAgent toggle, and ProxyJump/ProxyCommand display; name field cleared unconditionally on alias-to-manual switch.
src/renderer/lib/components/ssh-connection-form-model.ts suggestedAuthTypeForSshConfigHost falls back to 'agent' even with no agent configured, which can produce a confusing failure.
src/shared/ssh.ts Adds sshConfigAlias, forwardAgent, proxyJump to SshConfig and proxy/forward fields to SshConfigHost; all optional for backward compatibility.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[resolveSshConnectConfig] --> B{alias?}
    B -- yes --> C[resolveSshConfig\nssh -G alias]
    B -- no --> D{authType === agent?}
    D -- yes --> E[resolveManualAgentSshConfig]
    D -- no --> F[agentResolved = undefined]
    C --> G[buildAuthConfig]
    E --> G
    F --> G
    G --> H[applyForwardAgent]
    H --> I{proxyCommand\nfrom SSH config?}
    I -- yes --> J[spawnProxyCommandWithShell]
    I -- no --> K{proxyJump?}
    K -- yes --> L[spawnProxyJump]
    K -- no --> M[direct TCP]
    J --> N[SshConnectResult]
    L --> N
    M --> N
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/renderer/lib/components/ssh-connection-form-model.ts:5-9
When neither `identityAgent` nor `identityFile` is configured for a host, the function returns `'agent'` as the default. A user with no SSH agent running will get an immediate connection failure with a potentially confusing "SSH agent socket not found" error rather than being prompted for a password. Defaulting to `'password'` here is safer for an unconfigured host.

```suggestion
export function suggestedAuthTypeForSshConfigHost(host: SshConfigHost): AuthType {
  if (host.identityAgent) return 'agent';
  if (host.identityFile) return 'key';
  return 'password';
}
```

### Issue 2 of 2
src/renderer/lib/components/add-ssh-conn-modal.tsx:313-326
**Name cleared on alias-to-manual switch in edit mode**

When a user is editing a saved connection that is alias-backed and switches the dropdown back to "Manual connection", `form.setFieldValue('name', '')` clears the connection name unconditionally. If `isEditing` is true the user already has a name they want to keep, and clearing it forces them to retype it before the form can be submitted.

Reviews (2): Last reviewed commit: "fix(ssh): strip unsupported proxy comman..." | Re-trigger Greptile

Comment thread src/main/core/ssh/connect/ssh-connect-auth.ts
Comment thread src/main/core/ssh/transport/transports.ts
@jschwxrz
Copy link
Copy Markdown
Collaborator Author

@greptileai

@jschwxrz jschwxrz merged commit 00a96b8 into main May 21, 2026
1 check passed
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.

2 participants