diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 4d942075712..7494b96e9ea 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -149,6 +149,10 @@ class ProcessWrap : public HandleWrap { if (!stdios->Get(context, i).ToLocal(&val)) { return Nothing(); } + if (!val->IsObject()) { + THROW_ERR_INVALID_ARG_TYPE(env, "options.stdio elements must be objects"); + return Nothing(); + } Local stdio = val.As(); Local type; if (!stdio->Get(context, env->type_string()).ToLocal(&type)) { diff --git a/test/parallel/test-child-process-array-prototype-pollution.js b/test/parallel/test-child-process-array-prototype-pollution.js new file mode 100644 index 00000000000..1f4c8eb581e --- /dev/null +++ b/test/parallel/test-child-process-array-prototype-pollution.js @@ -0,0 +1,19 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { exec } = require('child_process'); + +Object.defineProperty(Array.prototype, '2', { set: function () {} }); + +// child_process.exec() used to crash due to missing Array properties from prototype pollution. +// It should now throw a TypeError from C++ ProcessWrap::ParseStdioOptions instead of a fatal error. +assert.throws( + () => { + exec('echo 1'); + }, + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: /options\.stdio elements must be objects/ + } +);