From 4f56cdc4b86d6e78a418d9a249d6bf27d2a66d7a Mon Sep 17 00:00:00 2001 From: Phan Shi Yu Date: Fri, 2 Aug 2024 13:25:59 +0800 Subject: [PATCH 1/2] fix: obfuscation of an array element can lead to undefined error --- src/4.0/obfuscate.ts | 9 ++++++++- src/4.0/traverseAndFlatten.ts | 29 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/4.0/obfuscate.ts b/src/4.0/obfuscate.ts index a6519c3b..29876cb4 100644 --- a/src/4.0/obfuscate.ts +++ b/src/4.0/obfuscate.ts @@ -10,7 +10,14 @@ const obfuscate = (_data: V4WrappedDocument, fields: string[] | string) => { // fields to remove will contain the list of each expanded keys from the fields passed in parameter, it's for instance useful in case of // object obfuscation, where the object itself is not part of the salts, but each individual keys are - const toBeRemovedLeafNodes = traverseAndFlatten(pick(data, fieldsAsArray), ({ path }) => path); + const toBeRemovedLeafNodes = traverseAndFlatten( + pick(data, fieldsAsArray), + ({ path }) => path, + "", + // not picking from an array can lead to unpicked items being left as undefined + // these 'undefined' leaf nodes should be removed and not lead to an exception + true + ); const salts = decodeSalt(data.proof.salts); const obfuscatedData = toBeRemovedLeafNodes.map((field) => { diff --git a/src/4.0/traverseAndFlatten.ts b/src/4.0/traverseAndFlatten.ts index 53a39f49..13aef690 100644 --- a/src/4.0/traverseAndFlatten.ts +++ b/src/4.0/traverseAndFlatten.ts @@ -1,9 +1,13 @@ export type LeafValue = string | number | boolean | null | Record | []; +// we use a symbol just in case of conflicts with what the iteratee returns +const undefinedSym = Symbol("undefined value that should be filtered away"); + function _traverseAndFlatten( data: unknown, iteratee: (data: { value: LeafValue; path: string }) => IterateeValue, - path = "" + path = "", + isRemoveUndefinedLeafNodes = false ): IterateeValue | IterateeValue[] { if (Array.isArray(data)) { // an empty array is considered a leaf node @@ -13,7 +17,7 @@ function _traverseAndFlatten( const results: IterateeValue[] = []; for (let index = 0; index < data.length; index++) { const value = data[index]; - const result = _traverseAndFlatten(value, iteratee, `${path}[${index}]`); + const result = _traverseAndFlatten(value, iteratee, `${path}[${index}]`, isRemoveUndefinedLeafNodes); if (Array.isArray(result)) { results.push(...result); } else { @@ -29,7 +33,12 @@ function _traverseAndFlatten( // an empty object is considered a leaf node if (keys.length === 0) return iteratee({ value: {}, path }); return Object.keys(data).flatMap((key) => - _traverseAndFlatten(data[key as keyof typeof data], iteratee, path ? `${path}.${key}` : key) + _traverseAndFlatten( + data[key as keyof typeof data], + iteratee, + path ? `${path}.${key}` : key, + isRemoveUndefinedLeafNodes + ) ); } @@ -37,6 +46,11 @@ function _traverseAndFlatten( return iteratee({ value: data, path }); } + if (data === undefined && isRemoveUndefinedLeafNodes) { + // mark undefined leaf node with a unique symbol that must be removed later + return undefinedSym as IterateeValue; + } + throw new Error(`Unexpected data '${data}' in '${path}'`); } @@ -44,8 +58,11 @@ function _traverseAndFlatten( export function traverseAndFlatten( data: Record, iteratee: (data: { value: LeafValue; path: string }) => IterateeValue, - path = "" + path = "", + /** by default throw when there are leaf nodes that are undefined, setting this to true will remove them instead */ + isRemoveUndefinedLeafNodes = false ): IterateeValue[] { - const results = _traverseAndFlatten(data, iteratee, path); - return Array.isArray(results) ? results : []; + const results = _traverseAndFlatten(data, iteratee, path, isRemoveUndefinedLeafNodes); + // remove undefined leaf nodes + return Array.isArray(results) ? results.filter((v) => v !== undefinedSym) : []; } From 371f73704c67c59f27bf14764832029bf35f8a9c Mon Sep 17 00:00:00 2001 From: Phan Shi Yu Date: Fri, 2 Aug 2024 13:39:05 +0800 Subject: [PATCH 2/2] fix: typo --- src/4.0/obfuscate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/4.0/obfuscate.ts b/src/4.0/obfuscate.ts index 29876cb4..54bf3843 100644 --- a/src/4.0/obfuscate.ts +++ b/src/4.0/obfuscate.ts @@ -14,7 +14,7 @@ const obfuscate = (_data: V4WrappedDocument, fields: string[] | string) => { pick(data, fieldsAsArray), ({ path }) => path, "", - // not picking from an array can lead to unpicked items being left as undefined + // picking from an array can lead to unpicked items being left as undefined // these 'undefined' leaf nodes should be removed and not lead to an exception true );