mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
child_process: deprecate passing args to spawn and execFile
Accepting `args` gives the false impression that the args are escaped while really they are just concatenated. This makes it easy to introduce bugs and security vulnerabilities. PR-URL: https://github.com/nodejs/node/pull/57199 Fixes: https://github.com/nodejs/node/issues/57143 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
8b2098f9c8
commit
1b5b019de1
|
|
@ -3859,13 +3859,16 @@ deprecated, as their values are guaranteed to be identical to that of `process.f
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/57199
|
||||||
|
description: Runtime deprecation.
|
||||||
- version:
|
- version:
|
||||||
- REPLACEME
|
- REPLACEME
|
||||||
pr-url: https://github.com/nodejs/node/pull/57389
|
pr-url: https://github.com/nodejs/node/pull/57389
|
||||||
description: Documentation-only deprecation.
|
description: Documentation-only deprecation.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Type: Documentation-only
|
Type: Runtime
|
||||||
|
|
||||||
When an `args` array is passed to [`child_process.execFile`][] or [`child_process.spawn`][] with the option
|
When an `args` array is passed to [`child_process.execFile`][] or [`child_process.spawn`][] with the option
|
||||||
`{ shell: true }`, the values are not escaped, only space-separated, which can lead to shell injection.
|
`{ shell: true }`, the values are not escaped, only space-separated, which can lead to shell injection.
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,7 @@ function copyProcessEnvToEnv(env, name, optionEnv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emittedDEP0190Already = false;
|
||||||
function normalizeSpawnArguments(file, args, options) {
|
function normalizeSpawnArguments(file, args, options) {
|
||||||
validateString(file, 'file');
|
validateString(file, 'file');
|
||||||
validateArgumentNullCheck(file, 'file');
|
validateArgumentNullCheck(file, 'file');
|
||||||
|
|
@ -611,6 +612,14 @@ function normalizeSpawnArguments(file, args, options) {
|
||||||
|
|
||||||
if (options.shell) {
|
if (options.shell) {
|
||||||
validateArgumentNullCheck(options.shell, 'options.shell');
|
validateArgumentNullCheck(options.shell, 'options.shell');
|
||||||
|
if (args.length > 0 && !emittedDEP0190Already) {
|
||||||
|
process.emitWarning(
|
||||||
|
'Passing args to a child process with shell option true can lead to security ' +
|
||||||
|
'vulnerabilities, as the arguments are not escaped, only concatenated.',
|
||||||
|
'DeprecationWarning',
|
||||||
|
'DEP0190');
|
||||||
|
emittedDEP0190Already = true;
|
||||||
|
}
|
||||||
const command = ArrayPrototypeJoin([file, ...args], ' ');
|
const command = ArrayPrototypeJoin([file, ...args], ' ');
|
||||||
// Set the shell, switches, and commands.
|
// Set the shell, switches, and commands.
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ const fixture = fixtures.path('exit.js');
|
||||||
const echoFixture = fixtures.path('echo.js');
|
const echoFixture = fixtures.path('echo.js');
|
||||||
const execOpts = { encoding: 'utf8', shell: true, env: { ...process.env, NODE: process.execPath, FIXTURE: fixture } };
|
const execOpts = { encoding: 'utf8', shell: true, env: { ...process.env, NODE: process.execPath, FIXTURE: fixture } };
|
||||||
|
|
||||||
|
common.expectWarning(
|
||||||
|
'DeprecationWarning',
|
||||||
|
'Passing args to a child process with shell option true can lead to security ' +
|
||||||
|
'vulnerabilities, as the arguments are not escaped, only concatenated.',
|
||||||
|
'DEP0190');
|
||||||
|
|
||||||
{
|
{
|
||||||
execFile(
|
execFile(
|
||||||
process.execPath,
|
process.execPath,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ doesNotExist.on('exit', common.mustCall((code, signal) => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Verify that passing arguments works
|
// Verify that passing arguments works
|
||||||
|
common.expectWarning(
|
||||||
|
'DeprecationWarning',
|
||||||
|
'Passing args to a child process with shell option true can lead to security ' +
|
||||||
|
'vulnerabilities, as the arguments are not escaped, only concatenated.',
|
||||||
|
'DEP0190');
|
||||||
|
|
||||||
const echo = cp.spawn('echo', ['foo'], {
|
const echo = cp.spawn('echo', ['foo'], {
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
shell: true
|
shell: true
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,12 @@ else
|
||||||
assert.strictEqual(doesNotExist.status, 127); // Exit code of /bin/sh
|
assert.strictEqual(doesNotExist.status, 127); // Exit code of /bin/sh
|
||||||
|
|
||||||
// Verify that passing arguments works
|
// Verify that passing arguments works
|
||||||
|
common.expectWarning(
|
||||||
|
'DeprecationWarning',
|
||||||
|
'Passing args to a child process with shell option true can lead to security ' +
|
||||||
|
'vulnerabilities, as the arguments are not escaped, only concatenated.',
|
||||||
|
'DEP0190');
|
||||||
|
|
||||||
internalCp.spawnSync = common.mustCall(function(opts) {
|
internalCp.spawnSync = common.mustCall(function(opts) {
|
||||||
assert.strictEqual(opts.args[opts.args.length - 1].replace(/"/g, ''),
|
assert.strictEqual(opts.args[opts.args.length - 1].replace(/"/g, ''),
|
||||||
'echo foo');
|
'echo foo');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user