fix(ssh): preserve argv boundaries for multi-arg remote commands - #1060
Merged
Conversation
ssh(1) concatenates every remote-command word with single spaces into one string and hands it to the remote login shell, so argv boundaries never survived the trip: railway ssh -s api sh -c 'redis-cli -a "$PW" PING && echo ok' reached the remote shell as sh -c redis-cli -a "$PW" PING && echo ok giving sh -c only 'redis-cli' as its script (the quoted string leaked into $0/$1 and a stray '&& echo ok' command). Shell-quote each word (shlex::try_quote) when the caller passed more than one, so the remote re-split reproduces the caller's argv exactly — docker/kubectl exec semantics. A single word keeps passing through raw: it IS the remote shell line, today's documented usage, and quoting it would collapse the whole line into one command word. Applies at run_native_ssh_with_opts, so railway ssh and railway sandbox both get it; railway code passes a single prebuilt word and is unaffected. Round-trip unit tests included (join + shlex::split must reproduce the original argv).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
railway ssh svc sh -c 'redis-cli -a "$PW" PING && echo ok'never worked: ssh(1) concatenates every remote-command word with single spaces into one string for the remote login shell, so argv boundaries don't survive —sh -creceived onlyredis-clias its script, the quoted string leaked into$0/$1, and&& echo okran as a second command.What
Shell-quote each remote-command word (
shlex::try_quote) when the caller passed more than one, so the remote shell's re-split reproduces the caller's argv exactly —docker exec/kubectl execsemantics. A single word keeps passing through raw: it IS the remote shell line (today's documented usage, e.g.railway ssh 'complex | pipeline'), and quoting it would collapse the whole line into one command word.Applied at
run_native_ssh_with_opts, the choke point —railway sshandrailway sandboxboth get it;railway codepasses a single prebuilt word and is unaffected (all callers audited).Verification
shlex::splitmust reproduce the original argv (quotes, spaces,$,;|, empty words).cargo test: 932 passed.sh -c redis-cli ...).Same-class issue left out of scope:
run_tmux_sessioninterpolates the session name unquoted intotmux new-session -A -s {}.