[Unfinished] NodeJS Quirks

An anonymous object is an object that does not have to be explicitly referred to, i.e it is created and destroyed in the same line, rather than saved as a type. child_process.fork() takes three parameters (1 required; 2 optional), being (modulePath[, args][, options]) . args must be a list of string arguments and options must be an Object.
In the following case, { stdio: ['ignore', 'pipe', 'pipe', 'ipc'] } is an anonymous object being passed as options.
const { execSync, fork } = require('child_process');
let proc = fork('child.js', [], {
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
});
This means that when proc is executed, an anonymous object is created. All objects have a "blueprint" that they follow, which can be modified. The following line of code modifies the prototype of the constructor, resulting in a change to the "blueprint" of future objects (prototype pollution):
({})['constructor']['prototype']['execArgv'] = ['ls'];
Note: ['constructor']['prototype'] is equivalent to ['__proto__']
As a result, all objects created will now have an execArgv property. When { stdio: ['ignore', 'pipe', 'pipe', 'ipc'] } is executed, it actually creates { stdio: ['ignore', 'pipe', 'pipe', 'ipc'], execArgv: ['ls] } , with the execArgv: ['ls'] part being "invisible"--you won't see it, even if you set a variable to the object:
execArgv being an "invisible" part of variable a
Now, the real danger occurs when prototype pollution is possible due to--most commonly--unsafe merging of objects. Read more about prototype pollution due to merge({}, source) , how to abuse it, and how to mitigate it here: https://snyk.io/vuln/SNYK-JS-MERGE-1040469.
Copy link