0

When executing a bash command in node and passing a dynamic parameter, the standard way to go is to use spawn and avoid escaping. That is:

const filename = 'file with spaces'
spawn('ls', [filename]) // All good, received 'file with spaces'

This is foolproof since filename is passed as a standalone variable to bash.

Now, what happens if I want to do the same through ssh? The following is not an option:

const filename = 'file with spaces'
spawn('ssh', [host, 'ls', filename]) // Wrong!! Received 'file' 'with' 'spaces'

Ssh is accepting ls and filename as vargars. Joining it and executing, which defeats the purpose.

Gabriel Furstenheim
  • 1,941
  • 19
  • 18
  • I think you might need to escape single quotes like `filename = '\'file with spaces\''` – invad0r Feb 13 '20 at 10:34
  • No, that is not good. That will depend a lot on the input, which is dynamic – Gabriel Furstenheim Feb 13 '20 at 13:05
  • Passing a single string (suitably constructed) is your only real option; `ssh` is just taking its arguments and naively joining them into a single string to use with `$SHELL -c` on the remote host anyway. – chepner Feb 13 '20 at 13:47
  • Make a function `quote_me(string)` that puts single quotes around the input and try `spawn('ssh', [host, 'ls', quote_me(filename)])`. – Walter A Feb 13 '20 at 16:04
  • @WalterA escaping characters is super tricky, and there can always be cases where it doesn't work. For example in your case the filename could have quotes in the name – Gabriel Furstenheim Feb 14 '20 at 07:22

1 Answers1

1

One way is to pass the value using base64 which has expected characters and then escape in bash

spawn('ssh', [host, 'ls', `"$(echo ${btoa(filename)} | base64 -d)"`])
Gabriel Furstenheim
  • 1,941
  • 19
  • 18
  • `btoa` doesn't work without a custom function or module in Node, but you can use `Buffer.from(filename).toString("base64")` to accomplish the task. – Nucleon Oct 22 '20 at 18:21