From 3a6d2cb02a4b049cfd0e2257a9611cfb74067459 Mon Sep 17 00:00:00 2001 From: arjunshibu Date: Thu, 28 Jan 2021 13:11:15 +0530 Subject: [PATCH] Security fix for Prototype Pollution --- src/nestedObjectAssign.js | 6 +++++- test/nestedObjectAssign.spec.js | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/nestedObjectAssign.js b/src/nestedObjectAssign.js index 2358fab..8bda54b 100644 --- a/src/nestedObjectAssign.js +++ b/src/nestedObjectAssign.js @@ -9,7 +9,7 @@ export default function nestedObjectAssign(target, ...sources){ if (isObject(target) && isObject(source)){ for (const key in source){ - if (isObject(source[key])){ + if (isObject(source[key]) && !isPrototypePolluted(key)){ if (!target[key]) { Object.assign(target, {[key]: {}}); } @@ -28,4 +28,8 @@ export default function nestedObjectAssign(target, ...sources){ } return nestedObjectAssign(target, ...sources); +} + +function isPrototypePolluted(key){ + return /__proto__|constructor|prototype/.test(key); } \ No newline at end of file diff --git a/test/nestedObjectAssign.spec.js b/test/nestedObjectAssign.spec.js index ef9ec8a..ea0c524 100644 --- a/test/nestedObjectAssign.spec.js +++ b/test/nestedObjectAssign.spec.js @@ -69,4 +69,10 @@ describe('Given an instance of nestedObjectAssign', function() { expect(JSON.stringify(nestedObjectAssign({}, mockData.default, mockData.first, mockData.second))).to.be.equal(JSON.stringify(expectedData)); }); }); + describe('when I give malicious payload', function() { + it('it should not pollute object prototype', () => { + nestedObjectAssign({}, JSON.parse('{"__proto__": {"polluted": true}}')); + expect({}.polluted).to.be.equal(undefined); + }); + }); }); \ No newline at end of file