From 7af9969e4d4a49e6f7138e6ca3953820034bab48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Cruz?= Date: Thu, 27 Mar 2025 02:32:13 -0600 Subject: [PATCH] chore: allows redacting full objects --- src/diff/diffMaps.ts | 4 +++- src/diff/diffObjects.ts | 4 +++- src/diff/shared.ts | 9 ++++++--- src/test/security.spec.js | 8 ++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/diff/diffMaps.ts b/src/diff/diffMaps.ts index 46a689f..907eee6 100644 --- a/src/diff/diffMaps.ts +++ b/src/diff/diffMaps.ts @@ -6,6 +6,7 @@ import { getObjectChangeResult, getPathHint, maxKeysSecurityCheck, + shouldRedactValue, timeoutSecurityCheck, } from './shared'; @@ -34,6 +35,7 @@ function diffMaps({ timeoutSecurityCheck(startedAt, config); } + const redactable = shouldRedactValue(key, config); const keyInLhs = lhs.has(key); const keyInRhs = rhs.has(key); const lhsValue = keyInLhs ? lhs.get(key) : null; @@ -42,7 +44,7 @@ function diffMaps({ const pathUpdate = hint ? [hint, key] : [key]; const updatedPath = [...path, ...pathUpdate]; - if (isIterable(lhsValue) || isIterable(rhsValue)) { + if (!redactable && (isIterable(lhsValue) || isIterable(rhsValue))) { result.push( ...recursiveDiff({ lhs: lhsValue, diff --git a/src/diff/diffObjects.ts b/src/diff/diffObjects.ts index ad01e42..b08957d 100644 --- a/src/diff/diffObjects.ts +++ b/src/diff/diffObjects.ts @@ -5,6 +5,7 @@ import { buildResult, getObjectChangeResult, maxKeysSecurityCheck, + shouldRedactValue, timeoutSecurityCheck, } from './shared'; @@ -36,13 +37,14 @@ function diffObjects({ timeoutSecurityCheck(startedAt, config); } + const redactable = shouldRedactValue(key, config); const lhsValue = Array.isArray(lhs) ? lhs[key as number] : lhs?.[key]; const rhsValue = Array.isArray(rhs) ? rhs[key as number] : rhs?.[key]; const numericKey = typeof key !== 'symbol' ? Number(key) : NaN; const parsedKey = isNaN(numericKey) ? key : numericKey; const updatedPath = [...path, parsedKey]; - if (isIterable(lhsValue) || isIterable(rhsValue)) { + if (!redactable && (isIterable(lhsValue) || isIterable(rhsValue))) { result.push( ...recursiveDiff({ lhs: lhsValue, diff --git a/src/diff/shared.ts b/src/diff/shared.ts index d1301d1..634f18b 100644 --- a/src/diff/shared.ts +++ b/src/diff/shared.ts @@ -10,10 +10,13 @@ export function includeDiffType(type: ChangeType, config: DiffConfig) { return config.include?.includes?.(type) && !config.exclude?.includes?.(type); } -export function shouldRedactValue(key: any, config: DiffConfig) { - const rawKey = getRawValue(key); +export function shouldRedactValue( + key: string | number | symbol, + config: DiffConfig +) { + if (!isPrimitive(key)) return false; - return config.redactKeys?.includes?.(rawKey); + return config.redactKeys?.includes?.(key.toString()); } export function createReplacer(config: DiffConfig, obj: any) { diff --git a/src/test/security.spec.js b/src/test/security.spec.js index 5d6eae5..d1e83e5 100644 --- a/src/test/security.spec.js +++ b/src/test/security.spec.js @@ -64,6 +64,10 @@ describe('Security checks', () => { const symToken = Symbol('token'); const symSecret = Symbol('secret'); + const redactedObj = { + foo: 'redacted object', + }; + const a = { password: 'abcde', token: 'abcde', @@ -72,7 +76,7 @@ describe('Security checks', () => { [symToken]: 'abcde', [symSecret]: 'abcde', safe: 'safe field', - sensitive: 'secret', + sensitive: redactedObj, // replaces the entire object }; const b = new Map([[a, 'foo']]); @@ -118,7 +122,7 @@ describe('Security checks', () => { type: ChangeType.ADD, str: '"sensitive": "*****",', depth: 1, - path: ['sensitive', { deleted: false, value: 'secret' }], + path: ['sensitive', { deleted: false, value: redactedObj }], }, { type: ChangeType.ADD,