@@ -112,14 +112,19 @@ func (o sshConfigOptions) equal(other sshConfigOptions) bool {
112112}
113113
114114func (o sshConfigOptions ) writeToBuffer (buf * bytes.Buffer ) error {
115- escapedCoderBinary , err := sshConfigExecEscape (o .coderBinaryPath , o .forceUnixSeparators )
115+ escapedCoderBinaryProxy , err := sshConfigProxyCommandEscape (o .coderBinaryPath , o .forceUnixSeparators )
116116 if err != nil {
117- return xerrors .Errorf ("escape coder binary for ssh failed: %w" , err )
117+ return xerrors .Errorf ("escape coder binary for ProxyCommand failed: %w" , err )
118118 }
119119
120- escapedGlobalConfig , err := sshConfigExecEscape (o .globalConfigPath , o . forceUnixSeparators )
120+ escapedCoderBinaryMatchExec , err := sshConfigMatchExecEscape (o .coderBinaryPath )
121121 if err != nil {
122- return xerrors .Errorf ("escape global config for ssh failed: %w" , err )
122+ return xerrors .Errorf ("escape coder binary for Match exec failed: %w" , err )
123+ }
124+
125+ escapedGlobalConfig , err := sshConfigProxyCommandEscape (o .globalConfigPath , o .forceUnixSeparators )
126+ if err != nil {
127+ return xerrors .Errorf ("escape global config for ProxyCommand failed: %w" , err )
123128 }
124129
125130 rootFlags := fmt .Sprintf ("--global-config %s" , escapedGlobalConfig )
@@ -155,7 +160,7 @@ func (o sshConfigOptions) writeToBuffer(buf *bytes.Buffer) error {
155160 _ , _ = buf .WriteString ("\t " )
156161 _ , _ = fmt .Fprintf (buf ,
157162 "ProxyCommand %s %s ssh --stdio%s --ssh-host-prefix %s %%h" ,
158- escapedCoderBinary , rootFlags , flags , o .userHostPrefix ,
163+ escapedCoderBinaryProxy , rootFlags , flags , o .userHostPrefix ,
159164 )
160165 _ , _ = buf .WriteString ("\n " )
161166 }
@@ -174,11 +179,11 @@ func (o sshConfigOptions) writeToBuffer(buf *bytes.Buffer) error {
174179 // the ^^ options should always apply, but we only want to use the proxy command if Coder Connect is not running.
175180 if ! o .skipProxyCommand {
176181 _ , _ = fmt .Fprintf (buf , "\n Match host *.%s !exec \" %s connect exists %%h\" \n " ,
177- o .hostnameSuffix , escapedCoderBinary )
182+ o .hostnameSuffix , escapedCoderBinaryMatchExec )
178183 _ , _ = buf .WriteString ("\t " )
179184 _ , _ = fmt .Fprintf (buf ,
180185 "ProxyCommand %s %s ssh --stdio%s --hostname-suffix %s %%h" ,
181- escapedCoderBinary , rootFlags , flags , o .hostnameSuffix ,
186+ escapedCoderBinaryProxy , rootFlags , flags , o .hostnameSuffix ,
182187 )
183188 _ , _ = buf .WriteString ("\n " )
184189 }
@@ -759,7 +764,8 @@ func sshConfigSplitOnCoderSection(data []byte) (before, section []byte, after []
759764 return data , nil , nil , nil
760765}
761766
762- // sshConfigExecEscape quotes the string if it contains spaces, as per
767+ // sshConfigProxyCommandEscape prepares the path for use in ProxyCommand.
768+ // It quotes the string if it contains spaces, as per
763769// `man 5 ssh_config`. However, OpenSSH uses exec in the users shell to
764770// run the command, and as such the formatting/escape requirements
765771// cannot simply be covered by `fmt.Sprintf("%q", path)`.
@@ -804,7 +810,7 @@ func sshConfigSplitOnCoderSection(data []byte) (before, section []byte, after []
804810// This is a control flag, and that is ok. It is a control flag
805811// based on the OS of the user. Making this a different file is excessive.
806812// nolint:revive
807- func sshConfigExecEscape (path string , forceUnixPath bool ) (string , error ) {
813+ func sshConfigProxyCommandEscape (path string , forceUnixPath bool ) (string , error ) {
808814 if forceUnixPath {
809815 // This is a workaround for #7639, where the filepath separator is
810816 // incorrectly the Windows separator (\) instead of the unix separator (/).
@@ -814,9 +820,9 @@ func sshConfigExecEscape(path string, forceUnixPath bool) (string, error) {
814820 // This is unlikely to ever happen, but newlines are allowed on
815821 // certain filesystems, but cannot be used inside ssh config.
816822 if strings .ContainsAny (path , "\n " ) {
817- return "" , xerrors .Errorf ("invalid path: %s " , path )
823+ return "" , xerrors .Errorf ("invalid path: %q " , path )
818824 }
819- // In the unlikely even that a path contains quotes, they must be
825+ // In the unlikely event that a path contains quotes, they must be
820826 // escaped so that they are not interpreted as shell quotes.
821827 if strings .Contains (path , "\" " ) {
822828 path = strings .ReplaceAll (path , "\" " , "\\ \" " )
0 commit comments