diff --git a/lib/child_process.js b/lib/child_process.js index 3fb21f755be3d7..36f4db23378a59 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -196,7 +196,12 @@ function normalizeExecArgs(command, options, callback) { // Make a shallow copy so we don't clobber the user's options object. options = { __proto__: null, ...options }; - options.shell = typeof options.shell === 'string' ? options.shell : true; + + // Validate the shell, if present, and ensure a truthy value. + if (options.shell != null) { + validateString(options.shell, 'options.shell'); + } + options.shell ||= true; return { file: command, diff --git a/test/parallel/test-child-process-exec-any-shells-windows.js b/test/parallel/test-child-process-exec-any-shells-windows.js index 5c34bc77308cc3..10d37259a4021c 100644 --- a/test/parallel/test-child-process-exec-any-shells-windows.js +++ b/test/parallel/test-child-process-exec-any-shells-windows.js @@ -33,7 +33,7 @@ const testCopy = (shellName, shellPath) => { const system32 = `${process.env.SystemRoot}\\System32`; // Test CMD -test(true); +test(); test('cmd'); testCopy('cmd.exe', `${system32}\\cmd.exe`); test('cmd.exe'); diff --git a/test/parallel/test-child-process-exec-enforce-shell.js b/test/parallel/test-child-process-exec-enforce-shell.js new file mode 100644 index 00000000000000..83c080037c0ae0 --- /dev/null +++ b/test/parallel/test-child-process-exec-enforce-shell.js @@ -0,0 +1,23 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { exec, execSync } = require('child_process'); + +const invalidArgTypeError = { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError' +}; + +exec('echo should-be-passed-as-argument', { shell: '' }, common.mustSucceed((stdout, stderr) => { + assert.match(stdout, /should-be-passed-as-argument/); + assert.ok(!stderr); +})); + +{ + const ret = execSync('echo should-be-passed-as-argument', { encoding: 'utf-8', shell: '' }); + assert.match(ret, /should-be-passed-as-argument/); +} + +for (const fn of [exec, execSync]) { + assert.throws(() => fn('should-throw-on-boolean-shell-option', { shell: false }), invalidArgTypeError); +}