-1

I want to call a command line application from a web app built with node.js. I want to pass it some data in a parameter.

If the data to be passed has some quote characters, it throws an error because the shell can't parse the parameters correctly.

Is there any better approach than writing the data to a file and passing the file's name?

Charles Duffy
  • 235,655
  • 34
  • 305
  • 356
bevanb
  • 7,113
  • 7
  • 47
  • 85
  • Can you give a specific example of what command you are calling and what data you are passing in? Ideally you can just escape the invalid characters prior to running the command. What server side language are you using to execute the command? The language might already handle this type of problem for you. – jrasm91 May 19 '18 at 02:14
  • @Jason updated, thanks. – bevanb May 19 '18 at 02:17
  • @bevanb, if you're using node, you should use one of the `child_process.exec*` functions that allows your arguments to be passed as a list of strings, not a shell command -- that way there's no shell involved whatsoever, so you don't need to do any quoting or escaping in the first place. See [`child_process.execFile()`](https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback) as an example, particularly with the `string[]` argument list. – Charles Duffy May 19 '18 at 02:35
  • @charlesDuffy I'm actually using Rails and executing a node script. Thanks for the tip though. The question was unclear. – bevanb May 19 '18 at 03:04
  • 1
    Ahh. Ruby has its own mechanism to do a proper array/list-based execv. See the `[env, [cmdname, argv0], arg1, ..., opts]` usage modes in https://docs.ruby-lang.org/en/2.0.0/Open3.html – Charles Duffy May 19 '18 at 03:57
  • @bevanb, ...would you mind opening a new question? This one already has an answer on the premise that you were trying to do this from node (which *was* a reasonable inference -- there was, and still is, no mention of Rails in the question itself). – Charles Duffy May 19 '18 at 15:18

2 Answers2

1

You should never rely on escaping unknown input going to a shell parameter - there will almost always be some edge-case that you haven't thought of that allows the user to execute arbitrary code on your server.

Node has support for calling a command and passing each argument separately, with no escaping required. This is the safest way to do it:

const { spawn } = require('child_process');
// Note that the arguments are in an array, not using string interpolation
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

The documentation is here

Will Richardson
  • 7,012
  • 6
  • 39
  • 50
  • Hmm. I would be tempted to close this question as a duplicate of https://stackoverflow.com/questions/1779858/how-do-i-escape-a-string-for-a-shell-command-in-node, but the answers there are almost universally far worse than this one. – Charles Duffy May 19 '18 at 02:38
  • Yeah, the accepted answer doesn't give a good example and the rest are home-brewed escaping functions that may or may not work . – Will Richardson May 19 '18 at 02:40
  • 1
    Perhaps you might migrate the answer over there? That question does *need* a high-quality answer, after all, and it's better to have a single canonical instance for each question... even if it's going to take a while to overcome the number of votes that the bad answers there presently enjoy. :/ – Charles Duffy May 19 '18 at 02:43
  • [Doing my part to increase code quality](https://stackoverflow.com/a/50424976/692410) – Will Richardson May 19 '18 at 11:52
-1

I would suggest that you escape single quotes ( \' ) using a regex or replace function in your server-side language. Again, I don't know what that is.

jrasm91
  • 166
  • 1
  • 8
  • 1
    If a question doesn't have enough details to allow a clear and specific answer, that question should be closed, not answered. See https://stackoverflow.com/help/how-to-answer, specifically the section "Answer Well-Asked Questions". – Charles Duffy May 19 '18 at 02:31