(obj, recursionDepth = 0, maxDepth = 5, seen = new WeakSet())
| 22 | } |
| 23 | |
| 24 | export function redactSensitiveFields(obj, recursionDepth = 0, maxDepth = 5, seen = new WeakSet()) { |
| 25 | if (recursionDepth > maxDepth) { |
| 26 | // Prevent infinite recursion on circular objects or excessively deep structures |
| 27 | return 'REDACTED_TOO_DEEP' |
| 28 | } |
| 29 | if (obj === null || typeof obj !== 'object') { |
| 30 | return obj |
| 31 | } |
| 32 | |
| 33 | if (seen.has(obj)) { |
| 34 | return 'REDACTED_CIRCULAR_REFERENCE' |
| 35 | } |
| 36 | seen.add(obj) |
| 37 | |
| 38 | if (Array.isArray(obj)) { |
| 39 | const redactedArray = [] |
| 40 | for (let i = 0; i < obj.length; i++) { |
| 41 | const item = obj[i] |
| 42 | if (item !== null && typeof item === 'object') { |
| 43 | redactedArray[i] = redactSensitiveFields(item, recursionDepth + 1, maxDepth, seen) |
| 44 | } else { |
| 45 | redactedArray[i] = item |
| 46 | } |
| 47 | } |
| 48 | return redactedArray |
| 49 | } |
| 50 | |
| 51 | const redactedObj = {} |
| 52 | for (const key in obj) { |
| 53 | if (Object.prototype.hasOwnProperty.call(obj, key)) { |
| 54 | const lowerKey = key.toLowerCase() |
| 55 | let isKeySensitive = isPromptOrSelectionLikeKey(lowerKey) |
| 56 | if (!isKeySensitive) { |
| 57 | for (const keyword of SENSITIVE_KEYWORDS) { |
| 58 | if (lowerKey.includes(keyword)) { |
| 59 | isKeySensitive = true |
| 60 | break |
| 61 | } |
| 62 | } |
| 63 | } |
| 64 | if (isKeySensitive) { |
| 65 | redactedObj[key] = 'REDACTED' |
| 66 | } else if (obj[key] !== null && typeof obj[key] === 'object') { |
| 67 | redactedObj[key] = redactSensitiveFields(obj[key], recursionDepth + 1, maxDepth, seen) |
| 68 | } else { |
| 69 | redactedObj[key] = obj[key] |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | return redactedObj |
| 74 | } |
no test coverage detected