Skip to content

Commit

Permalink
Protect against Object prototype contamination (#4)
Browse files Browse the repository at this point in the history
* Added tests demonstrating the vulnerability

* Protect against Object prototype contamination

Reported in hackerone #310446, original discovery in #309391
  • Loading branch information
Prestaul authored and selfcontained committed Mar 3, 2018
1 parent d9ae4da commit ed27b7e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
8 changes: 6 additions & 2 deletions lib/deap.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ module.exports = {
mergeShallow: merge
};

function getProp(obj, p) {
return p === '__proto__' ? undefined : obj[p];
}

function clone(val) {
switch(typeOf(val)) {
case 'object':
Expand Down Expand Up @@ -54,7 +58,7 @@ function extend(a, b /*, [b2..n] */) {
function deepExtend(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
Object.keys(b).forEach(function(p) {
if(typeOf(b[p]) === 'object' && typeOf(a[p]) === 'object')
if(typeOf(getProp(b, p)) === 'object' && typeOf(a[p]) === 'object')
deepExtend(a[p], b[p]);
else
a[p] = deepClone(b[p]);
Expand Down Expand Up @@ -108,7 +112,7 @@ function deepMerge(a, b /*, [b2..n] */) {
var ap, bp, ta, tb;
Object.keys(b).forEach(function(p) {
ap = a[p];
bp = b[p];
bp = getProp(b, p);
ta = typeOf(ap);
tb = typeOf(bp);
if(tb === 'object' && ta === 'object')
Expand Down
11 changes: 11 additions & 0 deletions test/extend.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,15 @@ describe('deep extend', function() {
assert.notStrictEqual(result.nested[0].nested, result.nested[1]);
});

// Vulnerability reported via hacker1: https://hackerone.com/reports/310446
it('should not modify Object prototype (hacker1 #310446)', function() {
var a = { foo: 'bar' },
b = JSON.parse('{ "__proto__": { "evilBad": "DANGER!!!" } }');

var result = deepExtend(a, b);

assert.isUndefined({}.evilBad);
assert.isUndefined(Object.prototype.evilBad);
});

});
10 changes: 10 additions & 0 deletions test/merge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,14 @@ describe('deep merge', function() {
assert.notStrictEqual(result.nested[0], deeper);
});

// Vulnerability reported via hacker1: https://hackerone.com/reports/310446
it('should not modify Object prototype (hacker1 #310446)', function() {
var a = { foo: 'bar' },
b = JSON.parse('{ "__proto__": { "evilBad": "DANGER!!!" } }');

var result = deepMerge(a, b);

assert.isUndefined({}.evilBad);
assert.isUndefined(Object.prototype.evilBad);
});
});

0 comments on commit ed27b7e

Please sign in to comment.