-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
child_process: validate options.shell and correctly enforce shell invocation in exec/execSync #54623
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
Conversation
CC @nodejs/child_process @Renegade334 can you shorten the commit message, it's too long to land. Something like |
22673fb
to
ce02538
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #54623 +/- ##
=======================================
Coverage 88.53% 88.54%
=======================================
Files 657 657
Lines 190741 190746 +5
Branches 36607 36605 -2
=======================================
+ Hits 168881 168899 +18
+ Misses 15036 15028 -8
+ Partials 6824 6819 -5
|
ce02538
to
2288c07
Compare
3cf56e3
to
f61299e
Compare
PR is currently blocked from landing due to unreliable CI. Looks like the OSX runner is jammed up. |
@jasnell could this go back to request-ci, now that OS X is more stable? |
- narrow validation type to string (previously de facto not validated) - ensure empty string is coerced to true
f61299e
to
79e548e
Compare
The intention of exec and execSync is that a shell is always invoked to run the provided command, as opposed to execFile, which by default executes the target directly and does not invoke a shell. Unlike its counterparts elsewhere in child_process, exec's
options.shell
is documented as not accepting a boolean, as it's not intended to be possible to disable shell invocation and switch to execFile-like behaviour.exec's
options.shell
is currently handled the following way:normalizeExecArgs()
shell
parameter is not a string, it is coerced to booleantrue
normalizeSpawnArguments()
string|boolean
spawn()
runs a shell; if not, it executes the target directlyThe intention is clearly to force shell invocation with exec/execSync in all cases, but the current implementation has the following problems:
true
, which passes downstream validation innormalizeSpawnArguments()
. In other words, passing an invalid value tooptions.shell
will never raise a validation error.options.shell
set to the empty string:normalizeExecArgs()
normalizeSpawnArguments()
normalizeSpawnArguments()
fails to set up the shellcommand
string:This patch makes two simple changes. Firstly, it validates the shell option sent to exec/execSync as a string. Secondly, it coerces all falsy values to boolean
true
, so will never bypass shell setup. (This makes{ shell: '' }
equivalent to{ shell: undefined }
, which matches how it behaves in the other child_process functions.)