diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 748f14a283f05f..1e557aa3a7f237 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -427,6 +427,16 @@ ChildProcess.prototype.spawn = function(options) { for (i = 0; i < stdio.length; i++) { const stream = stdio[i]; + // Never trust the user input/runtime + // It is possile that the user mutated the stdio array, + // so we need to validate the stream object before using it before it lands + // native layer. + // Refs: https://github.com/nodejs/node/issues/55932 + if (!stream) { + process.nextTick(onErrorNT, this, UV_EINVAL); + return UV_EINVAL; + } + if (stream.type === 'ignore') continue; if (stream.ipc) { diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 27a294eb384960..04542f05e01238 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -122,6 +122,17 @@ class ProcessWrap : public HandleWrap { for (uint32_t i = 0; i < len; i++) { Local stdio = stdios->Get(context, i).ToLocalChecked().As(); + + // Never trust the user's input. + // If for some reason the stdio object is not an object, we will + // create a new object with the type set to 'ignore'. + // Refs: https://github.com/nodejs/node/issues/55932 + if (!stdio->IsObject()) { + stdio = Object::New(env->isolate()); + stdio->Set(context, env->type_string(), env->ignore_string()) + .FromJust(); + } + Local type = stdio->Get(context, env->type_string()).ToLocalChecked();