diff --git a/source/server/utils/merge/apply.test.ts b/source/server/utils/merge/apply.test.ts index da11c536..4da64db5 100644 --- a/source/server/utils/merge/apply.test.ts +++ b/source/server/utils/merge/apply.test.ts @@ -42,4 +42,16 @@ describe("merge.apply()", function(){ it("merges special SOURCE_INDEX symbol", function(){ expect(apply({a:{[SOURCE_INDEX]:0}}, {a:{[SOURCE_INDEX]:1}})).to.deep.equal({a:{[SOURCE_INDEX]:1}}); }); + + it("prevents prototype pollution (create object)", function(){ + //This is not a strict + let result:any = apply({}, {a:{__proto__: {isAdmin: true}, tick: 1} as any}); + expect(result.a, `Expected prototype pollution to be filtered internally`).to.not.have.property("isAdmin"); + }); + + it("prevents prototype pollution (update object)", function(){ + let result :any = apply({a: {tick: 0}}, {a:{__proto__: {isAdmin: true}, tick: 1} as any}); + expect(result).to.deep.equal({a:{tick: 1}}); + expect(result.a).to.not.have.property("isAdmin"); + }); }); \ No newline at end of file diff --git a/source/server/utils/merge/apply.ts b/source/server/utils/merge/apply.ts index 196a8396..24c6f42e 100644 --- a/source/server/utils/merge/apply.ts +++ b/source/server/utils/merge/apply.ts @@ -11,7 +11,7 @@ import {Diff, DELETE_KEY, SOURCE_INDEX, withIndex} from "./pointers/types.js"; export default function apply>(into :T, ...diffs :Diff[]):T{ for(const diff of diffs){ if(SOURCE_INDEX in diff) into = withIndex(into, diff[SOURCE_INDEX] as number); - for(const key in diff){ + for(const key of Object.getOwnPropertyNames(diff) as Extract, string>[]){ const value = diff[key] as T[Extract]; if(value === DELETE_KEY){ @@ -21,9 +21,7 @@ export default function apply>(into :T, ...diffs : delete into[key]; } - }else if(typeof value !== "object" //primitive - || typeof into[key] === "undefined" //undefined target - ){ + }else if(typeof value !== "object" /*primitive*/){ into[key] = value; }else if(Array.isArray(value)){ //Replace arrays without looking.