/** * Validation utilities for form fields * Detects potentially harmful content (XSS patterns) and provides validation rules */ // Patterns that indicate potentially malicious content const DANGEROUS_PATTERNS = [ //i, /<\/script>/i, /javascript:/i, /vbscript:/i, /on\w+\s*=/i, // onclick=, onerror=, onload=, etc. //i, //i, //i, //i, //i, /data:\s*text\/html/i, /expression\s*\(/i, // CSS expression /url\s*\(\s*["']?\s*javascript:/i, ]; /** * Checks if text contains potentially dangerous patterns (XSS) * @param text - The text to check * @returns true if dangerous patterns are found */ export function containsDangerousContent(text: string): boolean { if (!text) return false; return DANGEROUS_PATTERNS.some((pattern) => pattern.test(text)); } /** * Validation function for react-hook-form that checks for XSS patterns * @param fieldName - The human-readable name of the field for error messages * @returns Validation function for react-hook-form */ export function createXSSValidator(fieldName: string) { return (value: string) => { if (containsDangerousContent(value)) { return `${fieldName} contains invalid characters or content. Please remove any special HTML tags or scripts.`; } return true; }; } /** * Standard validation rules with XSS protection for common field types */ export const validationRules = { fullName: { required: { value: true, message: "Full name is required", }, minLength: { value: 2, message: "Full name must be at least 2 characters", }, maxLength: { value: 100, message: "Full name must not exceed 100 characters", }, validate: { noXSS: createXSSValidator("Full name"), }, }, email: { required: { value: true, message: "Email is required", }, pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: "Please enter a valid email address", }, validate: { noXSS: createXSSValidator("Email"), }, }, phone: { required: { value: true, message: "Phone number is required", }, minLength: { value: 10, message: "Phone number must be at least 10 characters", }, maxLength: { value: 20, message: "Phone number must not exceed 20 characters", }, pattern: { value: /^[+\d\s()-]+$/, message: "Please enter a valid phone number (digits, +, spaces, parentheses, and dashes only)", }, }, message: { required: { value: true, message: "Message is required", }, minLength: { value: 10, message: "Message must be at least 10 characters", }, maxLength: { value: 1000, message: "Message must not exceed 1000 characters", }, validate: { noXSS: createXSSValidator("Message"), }, }, companyName: { maxLength: { value: 200, message: "Company name must not exceed 200 characters", }, validate: { noXSS: createXSSValidator("Company name"), }, }, }; /** * Creates validation rules for a field with optional XSS check * @param fieldName - Human-readable field name * @param isRequired - Whether the field is required * @param additionalRules - Additional validation rules to merge */ export function createFieldValidation( fieldName: string, isRequired: boolean = false, additionalRules: Record = {} ) { const rules: Record = { validate: { noXSS: createXSSValidator(fieldName), }, ...additionalRules, }; if (isRequired) { rules.required = `${fieldName} is required`; } return rules; }