UNPKG

doclyft

Version:

CLI for DocLyft - Interactive documentation generator with hosted documentation support

137 lines (136 loc) 4.45 kB
"use strict"; /** * Data sanitization utilities for security logging and error handling * Prevents sensitive information from being exposed in logs or error messages */ Object.defineProperty(exports, "__esModule", { value: true }); exports.sanitizeObject = sanitizeObject; exports.sanitizeHeaders = sanitizeHeaders; exports.sanitizeResponseData = sanitizeResponseData; exports.sanitizeRequestData = sanitizeRequestData; // List of sensitive field names that should be sanitized const SENSITIVE_FIELDS = [ 'token', 'api_key', 'apikey', 'password', 'secret', 'key', 'github_token', 'authorization', 'bearer', 'x-api-key', 'access_token', 'refresh_token', 'session_id', 'csrf_token' ]; // List of sensitive header names that should be sanitized const SENSITIVE_HEADERS = [ 'authorization', 'x-api-key', 'apikey', 'cookie', 'set-cookie', 'x-auth-token', 'x-access-token', 'bearer', 'api-key' ]; /** * Sanitize an object by replacing sensitive values with masked versions */ function sanitizeObject(obj, depth = 0) { if (depth > 10) return '[Max Depth Reached]'; // Prevent infinite recursion if (obj === null || obj === undefined) return obj; if (typeof obj === 'string') { return sanitizeString(obj); } if (typeof obj !== 'object') return obj; if (Array.isArray(obj)) { return obj.map(item => sanitizeObject(item, depth + 1)); } const sanitized = {}; for (const [key, value] of Object.entries(obj)) { const lowerKey = key.toLowerCase(); if (SENSITIVE_FIELDS.some(field => lowerKey.includes(field))) { sanitized[key] = maskSensitiveValue(value); } else { sanitized[key] = sanitizeObject(value, depth + 1); } } return sanitized; } /** * Sanitize HTTP headers by masking sensitive header values */ function sanitizeHeaders(headers) { if (!headers || typeof headers !== 'object') return headers; const sanitized = {}; for (const [key, value] of Object.entries(headers)) { const lowerKey = key.toLowerCase(); if (SENSITIVE_HEADERS.includes(lowerKey)) { sanitized[key] = maskSensitiveValue(value); } else { sanitized[key] = value; } } return sanitized; } /** * Sanitize response data by removing or masking sensitive information */ function sanitizeResponseData(data) { if (!data) return data; // Handle string responses that might contain sensitive data if (typeof data === 'string') { return sanitizeString(data); } return sanitizeObject(data); } /** * Sanitize request data for logging */ function sanitizeRequestData(data) { if (!data) return data; if (typeof data === 'string') { try { const parsed = JSON.parse(data); return JSON.stringify(sanitizeObject(parsed)); } catch { return sanitizeString(data); } } return sanitizeObject(data); } /** * Mask sensitive values while preserving some information for debugging */ function maskSensitiveValue(value) { if (typeof value !== 'string') { return '[MASKED]'; } if (value.length <= 8) { return '[MASKED]'; } // Show first 4 and last 4 characters for debugging purposes return `${value.substring(0, 4)}...${value.substring(value.length - 4)}`; } /** * Sanitize strings that might contain sensitive information */ function sanitizeString(str) { if (typeof str !== 'string') return str; // Replace potential tokens or API keys with masked versions const tokenPatterns = [ /ghp_[a-zA-Z0-9]{36}/g, // GitHub personal access tokens /gho_[a-zA-Z0-9]{36}/g, // GitHub OAuth tokens /ghu_[a-zA-Z0-9]{36}/g, // GitHub user tokens /ghs_[a-zA-Z0-9]{36}/g, // GitHub server tokens /ghr_[a-zA-Z0-9]{76}/g, // GitHub refresh tokens /github_pat_[a-zA-Z0-9_]{82}/g, // GitHub fine-grained tokens /dk_prod_[a-zA-Z0-9]{20,}/g, // DocLyft API keys /Bearer\s+[a-zA-Z0-9._-]+/gi, // Bearer tokens ]; let sanitized = str; tokenPatterns.forEach(pattern => { sanitized = sanitized.replace(pattern, (match) => { if (match.length <= 8) return '[MASKED]'; return `${match.substring(0, 8)}...[MASKED]`; }); }); return sanitized; }