diff --git a/src/functions/merge.js b/src/functions/merge.js index b8b95695e..131256b3e 100644 --- a/src/functions/merge.js +++ b/src/functions/merge.js @@ -21,7 +21,10 @@ function _merge(target, source) { } for (var key in source) { - if (!Object.prototype.hasOwnProperty.call(source, key)) { + if ( + !Object.prototype.hasOwnProperty.call(source, key) || + key === '__proto__' + ) { continue; } @@ -32,7 +35,10 @@ function _merge(target, source) { continue; } - if (isObjectOrArrayOrFunction(targetVal) && isObjectOrArrayOrFunction(sourceVal)) { + if ( + isObjectOrArrayOrFunction(targetVal) && + isObjectOrArrayOrFunction(sourceVal) + ) { target[key] = _merge(targetVal, sourceVal); } else { target[key] = clone(sourceVal); diff --git a/test/spec/functions/defaultsPure.js b/test/spec/functions/defaultsPure.js index 93233cc70..8884a0c93 100644 --- a/test/spec/functions/defaultsPure.js +++ b/test/spec/functions/defaultsPure.js @@ -92,3 +92,16 @@ it('should keep the keys order when adding facet refinements', function() { ); expect(Object.keys(actual)).toEqual(['facet1', 'facet2']); }); + +it('does not pollute the prototype', () => { + var payload = JSON.parse('{"__proto__": {"polluted": "vulnerable to PP"}}'); + var subject = {}; + + expect(subject.polluted).toBe(undefined); + + const out = defaults({}, payload); + + expect(out).toEqual({}); + + expect({}.polluted).toBe(undefined); +}); diff --git a/test/spec/functions/intersection.js b/test/spec/functions/intersection.js index 6d83fb04a..b529e84ec 100644 --- a/test/spec/functions/intersection.js +++ b/test/spec/functions/intersection.js @@ -18,4 +18,3 @@ test('it should not produce duplicate primitive values', function() { '2' ]); }); - diff --git a/test/spec/functions/merge.js b/test/spec/functions/merge.js index e7f7015e0..64b92c32c 100644 --- a/test/spec/functions/merge.js +++ b/test/spec/functions/merge.js @@ -170,3 +170,16 @@ it('should not convert strings to arrays when merging arrays of `source`', funct expect(actual).toStrictEqual({a: ['x', 'y', 'z']}); }); + +it('does not pollute the prototype', () => { + var payload = JSON.parse('{"__proto__": {"polluted": "vulnerable to PP"}}'); + var subject = {}; + + expect(subject.polluted).toBe(undefined); + + const out = merge({}, payload); + + expect(out).toEqual({}); + + expect({}.polluted).toBe(undefined); +});