Skip to content

Commit

Permalink
fix: protect against prototype pollution;
Browse files Browse the repository at this point in the history
- Credit: @arjunshibu
- Reference: 418sec#1
- Closes #16 – no bot accounts
  • Loading branch information
lukeed committed Jan 27, 2021
1 parent 0209190 commit a4b8a93
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export default function (obj, keys, val) {
keys.split && (keys=keys.split('.'));
var i=0, l=keys.length, t=obj, x;
var i=0, l=keys.length, t=obj, x, k;
for (; i < l; ++i) {
x = t[keys[i]];
t = t[keys[i]] = (i === l - 1 ? val : (x != null ? x : (!!~keys[i+1].indexOf('.') || !(+keys[i+1] > -1)) ? {} : []));
k = keys[i];
if (k == '__proto__' || k == 'constructor' || k == 'prototype') continue;
x = t[k];
t = t[k] = (i === l - 1 ? val : (x != null ? x : (!!~keys[i+1].indexOf('.') || !(+keys[i+1] > -1)) ? {} : []));
}
}
60 changes: 60 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,63 @@ preserves('should not throw when refusing to convert `0` into object', () => {
});

preserves.run();

// ---

const pollution = suite('pollution');

pollution('should protect against "__proto__" assignment', () => {
let input = { abc: 123 };
let before = input.__proto__;
dset(input, '__proto__.hello', 123);

assert.equal(input.__proto__, before);
assert.equal(input, {
abc: 123,
hello: 123
});

assert.is.not({}.hello, 123);
assert.is.not((new Object).hello, 123);
assert.is.not(Object.create(null).hello, 123);
});

pollution('should protect against "__proto__" assignment :: nested', () => {
let input = { abc: 123 };
let before = input.__proto__;
dset(input, ['xyz', '__proto__', 'hello'], 123);

assert.equal(input.__proto__, before);
assert.equal(input, {
abc: 123,
xyz: {
hello: 123
}
});

assert.is({}.hello, undefined);
assert.is(input.hello, undefined);
assert.is((new Object).hello, undefined);
assert.is(Object.create(null).hello, undefined);
});

pollution('should ignore "prototype" assignment', () => {
let input = { a: 123 };
dset(input, 'a.prototype.hello', 'world');

assert.is(input.a.prototype, undefined);
assert.is.not(input.a.hello, 'world');
assert.equal(input, { a: 123 });
});

pollution('should ignore "constructor" assignment', () => {
let input = { a: 123 };
let before = input.a.constructor;

dset(input, 'a.constructor', 'world');
assert.equal(input.a.constructor, before);
assert.equal(input, { a: 123 });
assert.equal(before, Number);
});

pollution.run();

0 comments on commit a4b8a93

Please sign in to comment.