mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 15:11:13 -05:00
100 lines
2.4 KiB
TypeScript
100 lines
2.4 KiB
TypeScript
/**
|
|
* Input Sanitization Utilities
|
|
*
|
|
* Provides XSS protection for user-generated content.
|
|
* All user input should be sanitized before rendering to prevent injection attacks.
|
|
*/
|
|
|
|
import DOMPurify from 'dompurify';
|
|
import { logger } from './logger';
|
|
|
|
/**
|
|
* Sanitize HTML content to prevent XSS attacks
|
|
*
|
|
* @param html - Raw HTML string from user input
|
|
* @returns Sanitized HTML safe for rendering
|
|
*/
|
|
export function sanitizeHTML(html: string): string {
|
|
return DOMPurify.sanitize(html, {
|
|
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'u', 'a', 'ul', 'ol', 'li'],
|
|
ALLOWED_ATTR: ['href', 'target', 'rel'],
|
|
ALLOW_DATA_ATTR: false,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sanitize URL to prevent javascript: and data: protocol injection
|
|
*
|
|
* @param url - URL from user input
|
|
* @returns Sanitized URL or '#' if invalid
|
|
*/
|
|
export function sanitizeURL(url: string): string {
|
|
if (!url || typeof url !== 'string') {
|
|
return '#';
|
|
}
|
|
|
|
try {
|
|
const parsed = new URL(url);
|
|
|
|
// Only allow http, https, and mailto protocols
|
|
const allowedProtocols = ['http:', 'https:', 'mailto:'];
|
|
|
|
if (!allowedProtocols.includes(parsed.protocol)) {
|
|
logger.warn('Blocked potentially dangerous URL protocol', { protocol: parsed.protocol });
|
|
return '#';
|
|
}
|
|
|
|
return url;
|
|
} catch {
|
|
// Invalid URL format
|
|
logger.warn('Invalid URL format', { url });
|
|
return '#';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sanitize plain text to prevent any HTML rendering
|
|
* Escapes all HTML entities
|
|
*
|
|
* @param text - Plain text from user input
|
|
* @returns Escaped text safe for rendering
|
|
*/
|
|
export function sanitizePlainText(text: string): string {
|
|
if (!text || typeof text !== 'string') {
|
|
return '';
|
|
}
|
|
|
|
return text
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
.replace(/\//g, '/');
|
|
}
|
|
|
|
/**
|
|
* Check if a string contains potentially dangerous content
|
|
* Used for validation before sanitization
|
|
*
|
|
* @param input - User input to check
|
|
* @returns true if input contains suspicious patterns
|
|
*/
|
|
export function containsSuspiciousContent(input: string): boolean {
|
|
if (!input || typeof input !== 'string') {
|
|
return false;
|
|
}
|
|
|
|
const suspiciousPatterns = [
|
|
/<script/i,
|
|
/javascript:/i,
|
|
/on\w+\s*=/i, // Event handlers like onclick=
|
|
/<iframe/i,
|
|
/<object/i,
|
|
/<embed/i,
|
|
/data:text\/html/i,
|
|
];
|
|
|
|
return suspiciousPatterns.some(pattern => pattern.test(input));
|
|
}
|