/** * Unit Tests for Security Scanner * Tests vulnerability detection and security pattern matching */ import { SecurityScanner } from '../../../src/lib/quality-validator/analyzers/securityScanner'; import { logger } from '../../../src/lib/quality-validator/utils/logger'; import { createTempDir, cleanupTempDir, createTestFile } from '../../test-utils'; describe('SecurityScanner', () => { let scanner: SecurityScanner; let tempDir: string; beforeEach(() => { scanner = new SecurityScanner(); tempDir = createTempDir(); logger.configure({ verbose: false, useColors: false }); }); afterEach(() => { cleanupTempDir(tempDir); }); describe('analyze', () => { it('should analyze security and return result', async () => { const filePath = createTestFile(tempDir, 'src/app.ts', 'const x = 1;'); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/app.ts']); expect(result).toBeDefined(); expect(result.category).toBe('security'); expect(typeof result.score).toBe('number'); expect(result.status).toMatch(/pass|fail|warning/); expect(Array.isArray(result.findings)).toBe(true); expect(result.metrics).toBeDefined(); expect(typeof result.executionTime).toBe('number'); } finally { process.chdir(originalCwd); } }); it('should handle empty file list', async () => { const result = await scanner.analyze([]); expect(result).toBeDefined(); expect(result.category).toBe('security'); expect(typeof result.score).toBe('number'); }); }); describe('Hard-coded Secret Detection', () => { it('should detect hard-coded password', async () => { createTestFile(tempDir, 'src/config.ts', "const password = 'secret123';"); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/config.ts']); const metrics = result.metrics as any; expect(metrics.codePatterns).toBeDefined(); } finally { process.chdir(originalCwd); } }); it('should detect hard-coded API key', async () => { createTestFile(tempDir, 'src/api.ts', "const apiKey = 'sk_test_12345';"); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/api.ts']); const metrics = result.metrics as any; expect(metrics.codePatterns).toBeDefined(); } finally { process.chdir(originalCwd); } }); it('should detect hard-coded token', async () => { createTestFile(tempDir, 'src/auth.ts', "const token = 'eyJhbGc...';"); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/auth.ts']); const metrics = result.metrics as any; expect(metrics.codePatterns).toBeDefined(); } finally { process.chdir(originalCwd); } }); it('should not flag environment variable references as secrets', async () => { createTestFile( tempDir, 'src/safe.ts', "const apiKey = process.env.API_KEY;" ); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/safe.ts']); expect(result).toBeDefined(); } finally { process.chdir(originalCwd); } }); }); describe('XSS Risk Detection', () => { it('should detect dangerouslySetInnerHTML', async () => { createTestFile( tempDir, 'src/components/Html.tsx', '
' ); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/components/Html.tsx']); const metrics = result.metrics as any; expect(metrics.codePatterns.length).toBeGreaterThanOrEqual(0); } finally { process.chdir(originalCwd); } }); it('should detect innerHTML assignment', async () => { createTestFile( tempDir, 'src/utils/dom.ts', "element.innerHTML = userInput;" ); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/utils/dom.ts']); const metrics = result.metrics as any; expect(metrics.codePatterns).toBeDefined(); } finally { process.chdir(originalCwd); } }); it('should detect eval() usage', async () => { createTestFile(tempDir, 'src/unsafe.ts', 'eval(userCode);'); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/unsafe.ts']); const metrics = result.metrics as any; expect(metrics.codePatterns.length).toBeGreaterThanOrEqual(0); } finally { process.chdir(originalCwd); } }); }); describe('Performance Issue Detection', () => { it('should detect inline function definitions in JSX', async () => { createTestFile( tempDir, 'src/components/Button.tsx', '' ); const originalCwd = process.cwd(); process.chdir(tempDir); try { const result = await scanner.analyze(['src/components/Button.tsx']); const metrics = result.metrics as any; expect(metrics.performanceIssues).toBeDefined(); } finally { process.chdir(originalCwd); } }); it('should detect missing keys in lists', async () => { createTestFile( tempDir, 'src/components/List.tsx', 'items.map((item) =>