From bf30b75d51be04f6c1f884561a223226c890f01b Mon Sep 17 00:00:00 2001 From: Andrei Tatar Date: Tue, 19 Mar 2024 06:57:29 +0200 Subject: [PATCH] simple fix for prototype pollution --- src/update-state.test.ts | 9 +++++++++ src/update-state.ts | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/update-state.test.ts b/src/update-state.test.ts index 654bfe8..c869728 100644 --- a/src/update-state.test.ts +++ b/src/update-state.test.ts @@ -222,5 +222,14 @@ describe('updateState', () => { }], }); }); + + it('should not update via prototype props', () => { + var BAD_JSON = JSON.parse('{"__proto__":{"polluted":true}}') + + const { hasChanges } = updateState(BAD_JSON, {}) + + expect(hasChanges).to.be.false; + expect((Object.prototype as any).polluted).to.be.undefined; + }); }); diff --git a/src/update-state.ts b/src/update-state.ts index ead8d61..eeaeb6a 100644 --- a/src/update-state.ts +++ b/src/update-state.ts @@ -16,6 +16,9 @@ const arrayItemKeyMap = new Map([ ['currentSensorStateData', 'name'], ]); +// https://github.com/andrei-tatar/nora-firebase-common/issues/9 +const ignoreKeys: any[] = ['__proto__', 'constructor', 'prototype']; + function updateArrayState(update: any[], state: any[], path = ''): boolean { let hasChanges = false; @@ -51,6 +54,8 @@ function updateStateInternal(update: any, state: any, path = ''): boolean { let hasChanges = false; for (const [key, newValue] of entries(update)) { + if (ignoreKeys.includes(key)) { continue; } + const oldValue = state[key]; const newType = typeof newValue; const oldType = typeof oldValue;