diff --git a/lodash.js b/lodash.js index cbf3b38487..71353bf7bf 100644 --- a/lodash.js +++ b/lodash.js @@ -3990,6 +3990,10 @@ var key = toKey(path[index]), newValue = value; + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + if (index != lastIndex) { var objValue = nested[key]; newValue = customizer ? customizer(objValue, key, nested) : undefined; diff --git a/test/test.js b/test/test.js index 2bfb54669d..50c3d347ec 100644 --- a/test/test.js +++ b/test/test.js @@ -25787,6 +25787,39 @@ }); }); + // zipObjectDeep prototype pollution + ['__proto__', 'constructor', 'prototype'].forEach(function (keyToTest) { + QUnit.test('zipObjectDeep is not setting ' + keyToTest + ' on global', function (assert) { + assert.expect(1); + + _.zipObjectDeep([keyToTest + '.a'], ['newValue']); + // Can't access plain `a` as it's not defined and test fails + assert.notEqual(root['a'], 'newValue'); + }); + + QUnit.test('zipObjectDeep is not overwriting ' + keyToTest + ' on vars', function (assert) { + assert.expect(3); + + const b = 'oldValue' + _.zipObjectDeep([keyToTest + '.b'], ['newValue']); + assert.equal(b, 'oldValue'); + assert.notEqual(root['b'], 'newValue'); + + // ensure nothing was created + assert.notOk(root['b']); + }); + + QUnit.test('zipObjectDeep is not overwriting global.' + keyToTest, function (assert) { + assert.expect(2); + + _.zipObjectDeep([root + '.' + keyToTest + '.c'], ['newValue']); + assert.notEqual(root['c'], 'newValue'); + + // ensure nothing was created + assert.notOk(root['c']); + }); + }); + /*--------------------------------------------------------------------------*/ QUnit.module('lodash.zipWith');