diff --git a/src/utils/CollideUtil.ts b/src/utils/CollideUtil.ts index 581f273..27df8ae 100644 --- a/src/utils/CollideUtil.ts +++ b/src/utils/CollideUtil.ts @@ -25,7 +25,7 @@ export function collide(arg1: any, arg2: any, modifiers?: ICollideModifiers, sta * @param startPath the entry path to start modifier path generation. Default value: $ * @returns collide result */ -export function collideUnsafe(arg1: any, arg2: any, modifiers?: ICollideModifiers, startPath: string = '$'): any { +export function collideUnsafe(arg1: any, arg2: any, modifiers?: ICollideModifiers, startPath = '$'): any { if (arg2 === undefined) { return arg1; } @@ -78,14 +78,15 @@ function collideObjects(obj1: any, obj2: any, path: string, modifiers?: ICollide for (const key of Object.keys(obj2)) { const subPath = path + '.' + key; - - if (obj1[key] === undefined) { - obj1[key] = obj2[key]; - } else { - if (modifiers && modifiers[subPath]) { - obj1[key] = modifiers[subPath](obj1[key], obj2[key]); + if (key !== '__proto__') { + if (obj1[key] === undefined) { + obj1[key] = obj2[key]; } else { - obj1[key] = collideUnsafe(obj1[key], obj2[key], modifiers, subPath); + if (modifiers && modifiers[subPath]) { + obj1[key] = modifiers[subPath](obj1[key], obj2[key]); + } else { + obj1[key] = collideUnsafe(obj1[key], obj2[key], modifiers, subPath); + } } } } diff --git a/test/unit/CollideUtilTestSuite.ts b/test/unit/CollideUtilTestSuite.ts index abd8485..04b297f 100644 --- a/test/unit/CollideUtilTestSuite.ts +++ b/test/unit/CollideUtilTestSuite.ts @@ -62,20 +62,17 @@ class CollideUtilTestSuite { override: 11, }; - collideUnsafe( - obj1, - { - array: [3, 4], - obj: { - b: false, - d: 'd', - e: 1, - n: null, - array: [12, 13, 14], - }, - override: 111, + collideUnsafe(obj1, { + array: [3, 4], + obj: { + b: false, + d: 'd', + e: 1, + n: null, + array: [12, 13, 14], }, - ); + override: 111, + }); assert.deepStrictEqual(obj1, { array: [1, 2, 3, 4], @@ -164,7 +161,7 @@ class CollideUtilTestSuite { '#.custom.obj': (a: any, b: any) => Object.assign(a, b), '#.custom.override': (a: any) => a, }, - '#.custom' + '#.custom', ); assert.deepStrictEqual(result, { @@ -259,4 +256,28 @@ class CollideUtilTestSuite { collide({ a: [1, 2] }, { a: true }); }).to.throw('Unable to collide. Collide value at path $.a is not an array.'); } + + @test() + async testWithPrototypePollution(): Promise { + const collideWith = JSON.parse(`{ + "__proto__": { + "vulnerable": "yes" + }, + "array": [3, 4] + }`); + + console.log(collideWith); + + const result = collide( + { + array: [1, 2], + }, + collideWith, + ); + + assert.ok(!result.vulnerable); + assert.deepStrictEqual(result, { + array: [1, 2, 3, 4], + }); + } }