Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature proposal] Single string input without using the shell #176

Closed
ehmicky opened this issue Feb 25, 2019 · 1 comment · Fixed by #182
Closed

[Feature proposal] Single string input without using the shell #176

ehmicky opened this issue Feb 25, 2019 · 1 comment · Fixed by #182

Comments

@ehmicky
Copy link
Collaborator

ehmicky commented Feb 25, 2019

I can submit a PR for this feature proposal if approved.

I think many users might use execa.shell() or the shell: true option as a way to pass arguments as a single string which feels more intuitive than using one string + one array:

execa.shell('eslint *.js *.yml --ignore-path=.gitignore --fix --cache --format=codeframe --max-warnings=0')
execa('eslint', ['*.js', '*.yml', '--ignore-path=.gitignore', '--fix', '--cache', '--format=codeframe', '--max-warnings=0'])

However those two calls use very different mechanism to execute the command, as the first one relies on system calls and the second one uses a shell interpreter. Using a shell interpreter is:

  • less secure: it allows for command injection by passing arguments like $(rm -rf /) or && rm -rf /
  • less cross-platform: it encourages using shell-specific features such as globbing, single quote escaping or even semicolons which won't work on cmd.exe.
  • slower as it goes through an extra step (the shell interpreter)

Using the shell interpreter can almost always be avoided as almost all shell features can be emulated in Node.js:

  • globbing can be done with libraries like minimatch. Directory recursion can also be used.
  • piping, subcommands, chaining and streams redirection can be done with the std* and input options.
  • escaping/quoting becomes unnecessary.
  • variable expansion can be done with template strings. This includes process.env.
  • passing environment variables can be done with the env option.
  • built-in Bash commands logic can be performed in JavaScript instead.
  • background processes can be done with the detached option.

In order to encourage more secure, cross-platform and faster shell execution, I suggest the following:

  • when the shell option is false, the first argument can be either command (current behavior) or command ...args (new behavior)
  • command ...args is a string delimited by spaces.
  • spaces can be escaped with backslashes: command escaped\ space. Anything else does not need escaping, just like the args array.

What do you think? Again if approved I can submit a PR.

@ehmicky ehmicky changed the title [Feature Proposal] Single string input without using the shell [Feature proposal] Single string input without using the shell Feb 25, 2019
@ehmicky
Copy link
Collaborator Author

ehmicky commented Mar 1, 2019

Done in #182

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant