/** * Sanitization utilities for user input * Prevents XSS attacks by escaping HTML special characters */ /** * Escape HTML special characters to prevent XSS * @param {string} str - String to escape * @returns {string} Escaped string */ const escapeHtml = (str) => { if (typeof str !== "string") { return str; } const htmlEscapeMap = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/", }; return str.replace(/[&<>"'/]/g, (char) => htmlEscapeMap[char]); }; /** * Sanitize object by escaping all string values * @param {Object} obj - Object to sanitize * @returns {Object} Sanitized object */ const sanitizeObject = (obj) => { if (typeof obj !== "object" || obj === null) { return obj; } const sanitized = {}; for (const [key, value] of Object.entries(obj)) { if (typeof value === "string") { sanitized[key] = escapeHtml(value); } else if (typeof value === "object" && value !== null) { sanitized[key] = sanitizeObject(value); } else { sanitized[key] = value; } } return sanitized; }; /** * Strip all HTML tags from a string * @param {string} str - String to strip * @returns {string} String without HTML tags */ const stripHtml = (str) => { if (typeof str !== "string") { return str; } return str.replace(/<[^>]*>/g, ""); }; /** * Validate and sanitize URL * @param {string} url - URL to validate * @returns {string|null} Sanitized URL or null if invalid */ const sanitizeUrl = (url) => { if (typeof url !== "string") { return null; } try { const parsed = new URL(url); // Only allow http and https protocols if (!["http:", "https:"].includes(parsed.protocol)) { return null; } return parsed.toString(); } catch { return null; } }; /** * Sanitize filename for safe storage * @param {string} filename - Filename to sanitize * @returns {string} Sanitized filename */ const sanitizeFilename = (filename) => { if (typeof filename !== "string") { return "file"; } // Remove path separators and null bytes return filename .replace(/[\/\\]/g, "") .replace(/\0/g, "") .replace(/[^a-zA-Z0-9._-]/g, "-") .substring(0, 255); }; module.exports = { escapeHtml, sanitizeObject, stripHtml, sanitizeUrl, sanitizeFilename, };