diff --git a/src/functions/merge.js b/src/functions/merge.js index 131256b3e..0e69f40e4 100644 --- a/src/functions/merge.js +++ b/src/functions/merge.js @@ -23,7 +23,8 @@ function _merge(target, source) { for (var key in source) { if ( !Object.prototype.hasOwnProperty.call(source, key) || - key === '__proto__' + key === '__proto__' || + key === 'constructor' ) { continue; } diff --git a/test/spec/algoliasearch.helper/constructor.js b/test/spec/algoliasearch.helper/constructor.js new file mode 100644 index 000000000..22f3103ce --- /dev/null +++ b/test/spec/algoliasearch.helper/constructor.js @@ -0,0 +1,13 @@ +'use strict'; + +var algoliasearchHelper = require('../../../index'); + +test('not vulnerable to prototype pollution', () => { + try { + algoliasearchHelper({}, '', {constructor: {prototype: {test: 123}}}); + } catch (e) { + // even if it throws an error, we need to be sure no vulnerability happens + } + + expect({}.test).toBeUndefined(); +}); diff --git a/test/spec/functions/merge.js b/test/spec/functions/merge.js index 64b92c32c..242009324 100644 --- a/test/spec/functions/merge.js +++ b/test/spec/functions/merge.js @@ -183,3 +183,15 @@ it('does not pollute the prototype', () => { expect({}.polluted).toBe(undefined); }); + +it('does not pollute the prototype in error condition', () => { + expect({}.polluted).toBe(undefined); + + try { + merge({}, {'constructor': {'prototype': {'polluted': 'vulnerable to PP'}}}); + } catch (e) { + // ignore + } + + expect({}.polluted).toBe(undefined); +});