/** * Tests for input sanitization functionality in security-utils * * Critical sanitization functions that prevent XSS and other attacks. */ import './security-utils-setup' import { escapeHtml, sanitizeText, sanitizeUrl } from '@/lib/security-utils' import { DANGEROUS_URLS, INVALID_URL_FORMATS, SQL_INJECTION_VECTORS, VALID_URLS } from './security-utils-setup' describe('Input Sanitization', () => { describe('escapeHtml', () => { it('escapes basic HTML characters', () => { const input = '
Hello & "World"
' const expected = '<div>Hello & "World"</div>' expect(escapeHtml(input)).toBe(expected) }) it('handles empty string', () => { expect(escapeHtml('')).toBe('') }) it('handles string with no HTML characters', () => { const input = 'Hello World' expect(escapeHtml(input)).toBe(input) }) it('escapes single quotes', () => { const input = "It's a test" const expected = 'It's a test' expect(escapeHtml(input)).toBe(expected) }) it('escapes forward slashes', () => { const input = '' const expected = '</script>' expect(escapeHtml(input)).toBe(expected) }) it('prevents XSS attacks', () => { // Test specific dangerous vectors that should be escaped const dangerous = ['', ''] dangerous.forEach(vector => { const escaped = escapeHtml(vector) expect(escaped).not.toContain(' World' const result = sanitizeText(input) expect(result).not.toContain('') expect(result).toContain('Hello') expect(result).toContain('World') // Script content should be removed for security expect(result).not.toContain('alert("xss")') }) it('removes style tags', () => { const input = 'Text with styling' const result = sanitizeText(input) expect(result).not.toContain('') expect(result).toContain('Text with') expect(result).toContain('styling') // Style content should be removed for security expect(result).not.toContain('body{background:red}') }) it('removes iframe tags', () => { const input = 'Text with frame' const result = sanitizeText(input) expect(result).not.toContain('') expect(result).toContain('Text with') expect(result).toContain('frame') // Iframe content should be removed for security expect(result).not.toContain('evil.com') }) it('strips all HTML tags but preserves text content', () => { const input = 'Text with bold and italic' const result = sanitizeText(input) expect(result).not.toContain('') expect(result).not.toContain('') expect(result).toContain('bold') expect(result).toContain('italic') }) it('removes dangerous event handlers', () => { const input = '

Click me

' const result = sanitizeText(input) expect(result).not.toContain('onclick') expect(result).not.toContain('

') expect(result).toContain('Click me') expect(result).not.toContain('alert(1)') }) it('sanitizes dangerous XSS vectors', () => { // Test vectors that should have dangerous HTML removed const htmlVectors = [ '', '', '' ] htmlVectors.forEach(vector => { const sanitized = sanitizeText(vector) expect(sanitized).not.toContain('') expect(sanitized).not.toContain(' { SQL_INJECTION_VECTORS.forEach(vector => { const sanitized = sanitizeText(vector) // Should not crash and should return some cleaned version expect(typeof sanitized).toBe('string') }) }) it('preserves line breaks', () => { const input = 'Line 1\nLine 2\nLine 3' const result = sanitizeText(input) expect(result).toContain('\n') }) it('handles empty input', () => { expect(sanitizeText('')).toBe('') }) it('handles very long input', () => { const longInput = `${'a'.repeat(10000)}` const result = sanitizeText(longInput) expect(result).not.toContain(' { it('accepts valid HTTPS URLs', () => { VALID_URLS.forEach(url => { expect(sanitizeUrl(url)).toBe(url) }) }) it('throws error for invalid URL format', () => { INVALID_URL_FORMATS.forEach(url => { expect(() => sanitizeUrl(url)).toThrow('Invalid URL format') }) }) it('blocks dangerous protocols', () => { DANGEROUS_URLS.forEach(url => { expect(() => sanitizeUrl(url)).toThrow() }) }) it('trims whitespace from URLs', () => { const url = ' https://example.com ' expect(sanitizeUrl(url)).toBe('https://example.com') }) it('is case-insensitive for protocol checking', () => { const testCases = [ 'JavaScript:alert(1)', 'DATA:text/html,', 'VBSCRIPT:msgbox', 'FILE:///etc/passwd' ] testCases.forEach(url => { expect(() => sanitizeUrl(url)).toThrow() }) }) it('handles URLs with query parameters', () => { const url = 'https://example.com/search?q=test&category=security' expect(sanitizeUrl(url)).toBe(url) }) it('handles URLs with fragments', () => { const url = 'https://example.com/page#section1' expect(sanitizeUrl(url)).toBe(url) }) it('rejects URLs with invalid characters', () => { // Test individual URLs to see which ones actually throw expect(() => sanitizeUrl('https://example.com/