In many guides regarding prototype pollution, "merge" functions are listed as potentially vulnerable. But I'm somewhat confused on how this should actually work if a merge function is not recursive. For example this guide lists as a vulnerable function something like
function merge(target, source) {
var output = JSON.parse(target);
for (var key in source) {
output[key] = source[key];
}
return output;
}
However, I cannot see how this would be vulnerable.
Let's simplify a bit:
const output = {}
output[attackerControlledKey] = attackerControlledValue
I cannot find a payload which would actually modify the prototype here. __proto__.isAdmin as attackerControlledKey doesn't work as far as I see.
If it were like
const output = {}
output[attackerControlledFirstKey][attackerControlledSecondKey] = attackerControlledValue
then sure an attacker could set __proto__ as attackerControlledFirstKey and the common examle isAdmin as attackerControlledSecondKey and true as attackerControlledValue
I get that many such merge functions are in fact recursive, like the examples listed here.
But I think if an attacker can only set one key and value without being able to go deeper, then there's no problem. Is this right? Or am I overlooking something?
source, they also controlsource[key], don't they? In your example (that is a slightly different scenario), the attacker could useattackerControlledKey=__proto__andattackerControlledValue={isAdmin: true}output['__proto__']['isAdmin'] = true;works it does not work to dooutput['__proto__'] = { isAdmin:true }. Tested in Node v20.16.0.