/** * Centralized input sanitization utilities for preventing XSS attacks. * Used at server-side input boundaries before storing or rendering user content. */ /** * Escape HTML special characters to prevent XSS. * Use for plain text fields that should never contain HTML. */ export function escapeHtml(str: string): string { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } /** * Sanitize rich text by stripping dangerous HTML tags while preserving safe formatting. * Allows: p, br, strong, em, ul, ol, li, h1-h6, a (with href only), blockquote, code, pre * Strips: script, style, iframe, object, embed, form, input, on* attributes */ export function sanitizeRichText(html: string): string { // Remove script tags and their contents let cleaned = html.replace(/)<[^<]*)*<\/script>/gi, ''); // Remove style tags and their contents cleaned = cleaned.replace(/)<[^<]*)*<\/style>/gi, ''); // Remove iframe, object, embed, form, input tags cleaned = cleaned.replace(/<\/?(?:iframe|object|embed|form|input|textarea|select|button)\b[^>]*>/gi, ''); // Remove all on* event handlers (onclick, onerror, onload, etc.) cleaned = cleaned.replace(/\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]*)/gi, ''); // Remove javascript: protocol from href/src attributes cleaned = cleaned.replace(/(href|src|action)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi, '$1=""'); // Remove data: protocol (except data:image for inline images) cleaned = cleaned.replace(/(href|src|action)\s*=\s*(?:"data:(?!image)[^"]*"|'data:(?!image)[^']*')/gi, '$1=""'); return cleaned; } /** * Sanitize a URL to prevent javascript: and data: protocol injection. * Returns the URL if safe, or empty string if potentially malicious. */ export function sanitizeUrl(url: string): string { const trimmed = url.trim(); // Block javascript: protocol (case-insensitive, handles whitespace/encoding tricks) if (/^\s*javascript\s*:/i.test(trimmed)) return ''; // Block data: protocol (except data:image) if (/^\s*data\s*:(?!image\/)/i.test(trimmed)) return ''; // Block vbscript: protocol if (/^\s*vbscript\s*:/i.test(trimmed)) return ''; return trimmed; } /** * Sanitize a plain text string for safe storage. * Trims whitespace and limits length. */ export function sanitizeText(str: string, maxLength: number = 10000): string { return str.trim().substring(0, maxLength); }