UNPKG

@redocly/respect-core

Version:
101 lines 3.79 kB
import { deepCopy } from '../../utils/deep-copy.js'; export const POTENTIALLY_SECRET_FIELDS = [ 'token', 'access_token', 'id_token', 'password', 'client_secret', ]; export function maskSecrets(target, secretsSet) { const maskValue = (value, secret) => { return value.replace(secret, '*'.repeat(8)); }; if (typeof target === 'string') { let maskedString = target; secretsSet.forEach((secret) => { maskedString = maskedString.split(secret).join('*'.repeat(8)); }); return maskedString; } const masked = deepCopy(target); const maskIfContainsSecret = (value) => { let maskedValue = value; for (const secret of secretsSet) { if (maskedValue.includes(secret)) { maskedValue = maskValue(maskedValue, secret); } } return maskedValue; }; const maskRecursive = (current) => { for (const key in current) { if (typeof current[key] === 'string') { current[key] = maskIfContainsSecret(current[key]); } else if (typeof current[key] === 'object' && current[key] !== null) { // Skip special objects that should not be modified if (!(current[key] instanceof File) && !(current[key] instanceof ArrayBuffer) && !(current[key] instanceof Blob) && !(current[key] instanceof FormData) && !(current[key] instanceof Date) && !(current[key] instanceof RegExp) && !(current[key] instanceof Map) && !(current[key] instanceof Set) && !(current[key] instanceof URL) && !(current[key] instanceof Error)) { maskRecursive(current[key]); } } } }; maskRecursive(masked); return masked; } export function containsSecret(value, secretsSet) { return Array.from(secretsSet).some((secret) => value.includes(secret)); } export function findPotentiallySecretObjectFields(obj, tokenKeys = POTENTIALLY_SECRET_FIELDS) { const foundTokens = []; if (!obj || typeof obj !== 'object') { return foundTokens; } const searchInObject = (currentObj) => { if (!currentObj || typeof currentObj !== 'object') { return; } if (Array.isArray(currentObj)) { for (const item of currentObj) { searchInObject(item); } return; } for (const key in currentObj) { const value = currentObj[key]; // Check if the key matches any of the token keys (case-insensitive) if (tokenKeys.some((tokenKey) => tokenKey.toLowerCase() === key.toLowerCase())) { if (typeof value === 'string' && value.trim()) { foundTokens.push(value); } } if (typeof value === 'string' && value.trim()) { for (const tokenKey of tokenKeys) { const match = value.match(new RegExp(`${tokenKey}=([^;\\s]+)`, 'i')); const [, secretValue] = match || []; if (secretValue) { foundTokens.push(secretValue); } } } if (value && typeof value === 'object') { searchInObject(value); } } }; searchInObject(obj); return foundTokens; } export function conditionallyMaskSecrets({ value, noSecretsMasking, secretsSet, }) { return noSecretsMasking ? value : maskSecrets(value, secretsSet); } //# sourceMappingURL=mask-secrets.js.map