UNPKG

@logtape/redaction

Version:

Redact sensitive data from log messages

75 lines (73 loc) 2.41 kB
//#region src/pattern.ts /** * A redaction pattern for email addresses. * @since 0.10.0 */ const EMAIL_ADDRESS_PATTERN = { pattern: /[\p{L}0-9.!#$%&'*+/=?^_`{|}~-]+@[\p{L}0-9](?:[\p{L}0-9-]{0,61}[\p{L}0-9])?(?:\.[\p{L}0-9](?:[\p{L}0-9-]{0,61}[\p{L}0-9])?)+/gu, replacement: "REDACTED@EMAIL.ADDRESS" }; /** * A redaction pattern for credit card numbers (including American Express). * @since 0.10.0 */ const CREDIT_CARD_NUMBER_PATTERN = { pattern: /(?:\d{4}-){3}\d{4}|(?:\d{4}-){2}\d{6}/g, replacement: "XXXX-XXXX-XXXX-XXXX" }; /** * A redaction pattern for U.S. Social Security numbers. * @since 0.10.0 */ const US_SSN_PATTERN = { pattern: /\d{3}-\d{2}-\d{4}/g, replacement: "XXX-XX-XXXX" }; /** * A redaction pattern for South Korean resident registration numbers * (住民登錄番號). * @since 0.10.0 */ const KR_RRN_PATTERN = { pattern: /\d{6}-\d{7}/g, replacement: "XXXXXX-XXXXXXX" }; /** * A redaction pattern for JSON Web Tokens (JWT). * @since 0.10.0 */ const JWT_PATTERN = { pattern: /eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g, replacement: "[JWT REDACTED]" }; function redactByPattern(formatter, patterns) { for (const { pattern } of patterns) if (!pattern.global) throw new TypeError(`Pattern ${pattern} does not have the global flag set.`); function replaceString(str) { for (const p of patterns) str = typeof p.replacement === "string" ? str.replaceAll(p.pattern, p.replacement) : str.replaceAll(p.pattern, p.replacement); return str; } function replaceObject(object) { if (typeof object === "string") return replaceString(object); else if (Array.isArray(object)) return object.map(replaceObject); else if (typeof object === "object" && object !== null) { if (Object.getPrototypeOf(object) === Object.prototype || Object.getPrototypeOf(object) === null) { const redacted = {}; for (const key in object) redacted[key] = replaceObject(object[key]); return redacted; } } return object; } return (record) => { const output = formatter(record); if (typeof output === "string") return replaceString(output); return output.map(replaceObject); }; } //#endregion exports.CREDIT_CARD_NUMBER_PATTERN = CREDIT_CARD_NUMBER_PATTERN; exports.EMAIL_ADDRESS_PATTERN = EMAIL_ADDRESS_PATTERN; exports.JWT_PATTERN = JWT_PATTERN; exports.KR_RRN_PATTERN = KR_RRN_PATTERN; exports.US_SSN_PATTERN = US_SSN_PATTERN; exports.redactByPattern = redactByPattern;