Problem Statement
Currently, the openshell snap uses the ssh-keys interface to get access to the host's ssh binary, which is used for sandbox connect/exec/forward. However, ssh-keys is a privileged interface which also grants access to the public and private ssh keys on the host. As such, it requires manual connection in order to be used.
This weakens the security sandbox of the snap, and hurts the UX of installing it.
Proposed Design
We should be able to vendor the ssh binary within the openshell snap, thus isolating it from the host environment and improve the installation UX.
Snapcraft provides a simple means of staging packages into the snap from the ubuntu releases corresponding to the base (currently core24, so Ubuntu 24.04). So let's do that with the package providing the ssh binary (openssh-client).
This should be safe because:
- OpenShell never uses host SSH credentials
- Every ssh invocation in the codebase passes
StrictHostKeyChecking=no, UserKnownHostsFile=/dev/null, and GlobalKnownHostsFile=/dev/null (crates/openshell-cli/src/ssh.rs:148-167, crates/openshell-tui/src/lib.rs:921/1082/1529)
- No
~/.ssh/id_* private keys, ~/.ssh/known_hosts, or authorized_keys are ever consulted
- The sandbox SSH daemon (
russh in openshell-supervisor-process) generates an ephemeral ED25519 host key per boot and authenticates a bearer token relayed over a Unix socket -- it does not use host credentials
- The
ProxyCommand is self-contained
- The
ProxyCommand invokes the openshell binary's own ssh-proxy subcommand (openshell-core/src/forward.rs:786-801), which is a pure-Rust gRPC proxy to the gateway -- it does not shell out to ssh
- So the outer ssh client only needs to reach the
ProxyCommand; no host SSH infrastructure is required
russh is fully independent
- The sandbox supervisor (openshell-supervisor-process/src/ssh.rs) and the gateway client (openshell-server/src/grpc/sandbox.rs) use the
russh crate, and does not depend on the ssh binary or the ssh-keys interface
~/.ssh/config is only for OpenShell-managed aliases
install_ssh_config (crates/openshell-cli/src/ssh.rs:1570-1587) writes Include + Host openshell-<name> blocks pointing at the OpenShell ProxyCommand
resolve_ssh_hostname (crates/openshell-bootstrap/src/metadata.rs:153-194) runs ssh -G only to resolve OpenShell-registered aliases
- Neither reads host-defined SSH config for credentials, host keys, or external hosts -- the config is entirely OpenShell-authored metadata
- Under snap confinement,
~/.ssh/config resolves to snap-private space
- With the default
HOME=$SNAP_USER_DATA (~/snap/openshell/current), the bundled ssh reads/writes ~/.ssh/config inside the snap's private data directory — writable without ssh-keys, invisible to the host, and preserved across refreshes by snapd
- The OpenShell-managed config file lives at
$XDG_CONFIG_HOME/openshell/ssh_config ($SNAP_USER_COMMON/.config/openshell/ssh_config), also snap-private
- The ssh-keys interface provided no unique capability
- The interface granted read access to
~/.ssh/ dotfiles -- which OpenShell never reads (no keys, no known_hosts) -- and access to the host /usr/bin/ssh binary
- Vendoring
openssh-client into the snap (priming only usr/bin/ssh) replaces the binary dependency
- The dynamic library dependencies (
libcrypto.so.3, libz.so.1, libselinux.so.1, libkrb5.so.3, etc.) are all satisfied by the core24 base snap, which ships the same Ubuntu 24.04 archive versions.
Alternatives Considered
The only downside I see of vendoring the ssh binary and saving the ssh configuration inside the snap is that external tools (e.g. VSCode remote-ssh) can no longer auto-discover Host openshell-<name> blocks in the host ~/.ssh/config. Instead, users may run openshell sandbox ssh-config <name> and paste the output into their host ssh config.
Agent Investigation
No response
Checklist
Problem Statement
Currently, the
openshellsnap uses thessh-keysinterface to get access to the host'ssshbinary, which is used forsandbox connect/exec/forward. However,ssh-keysis a privileged interface which also grants access to the public and private ssh keys on the host. As such, it requires manual connection in order to be used.This weakens the security sandbox of the snap, and hurts the UX of installing it.
Proposed Design
We should be able to vendor the
sshbinary within theopenshellsnap, thus isolating it from the host environment and improve the installation UX.Snapcraft provides a simple means of staging packages into the snap from the ubuntu releases corresponding to the base (currently
core24, so Ubuntu 24.04). So let's do that with the package providing thesshbinary (openssh-client).This should be safe because:
StrictHostKeyChecking=no,UserKnownHostsFile=/dev/null, andGlobalKnownHostsFile=/dev/null(crates/openshell-cli/src/ssh.rs:148-167, crates/openshell-tui/src/lib.rs:921/1082/1529)~/.ssh/id_*private keys,~/.ssh/known_hosts, orauthorized_keysare ever consultedrusshinopenshell-supervisor-process) generates an ephemeral ED25519 host key per boot and authenticates a bearer token relayed over a Unix socket -- it does not use host credentialsProxyCommandis self-containedProxyCommandinvokes the openshell binary's ownssh-proxysubcommand (openshell-core/src/forward.rs:786-801), which is a pure-Rust gRPC proxy to the gateway -- it does not shell out tosshProxyCommand; no host SSH infrastructure is requiredrusshis fully independentrussh crate, and does not depend on thesshbinary or thessh-keysinterface~/.ssh/configis only for OpenShell-managed aliasesinstall_ssh_config(crates/openshell-cli/src/ssh.rs:1570-1587) writesInclude+Host openshell-<name>blocks pointing at the OpenShellProxyCommandresolve_ssh_hostname(crates/openshell-bootstrap/src/metadata.rs:153-194) runsssh -Gonly to resolve OpenShell-registered aliases~/.ssh/configresolves to snap-private spaceHOME=$SNAP_USER_DATA(~/snap/openshell/current), the bundled ssh reads/writes~/.ssh/configinside the snap's private data directory — writable withoutssh-keys, invisible to the host, and preserved across refreshes by snapd$XDG_CONFIG_HOME/openshell/ssh_config($SNAP_USER_COMMON/.config/openshell/ssh_config), also snap-private~/.ssh/dotfiles -- which OpenShell never reads (no keys, noknown_hosts) -- and access to the host/usr/bin/sshbinaryopenssh-clientinto the snap (priming onlyusr/bin/ssh) replaces the binary dependencylibcrypto.so.3,libz.so.1,libselinux.so.1,libkrb5.so.3, etc.) are all satisfied by thecore24base snap, which ships the same Ubuntu 24.04 archive versions.Alternatives Considered
The only downside I see of vendoring the
sshbinary and saving the ssh configuration inside the snap is that external tools (e.g. VSCode remote-ssh) can no longer auto-discoverHost openshell-<name>blocks in the host~/.ssh/config. Instead, users may runopenshell sandbox ssh-config <name>and paste the output into their host ssh config.Agent Investigation
No response
Checklist