#!/usr/bin/env node /** * API Security Validator - Enforces inst_013, inst_045 * Scans API endpoints for security requirements */ const fs = require('fs'); const path = require('path'); function checkAPIEndpoint(filePath) { const content = fs.readFileSync(filePath, 'utf8'); const issues = []; const lines = content.split('\n'); lines.forEach((line, idx) => { // Check for API route definitions if (/\.(get|post|put|delete|patch)\s*\(['"](\/api|\/admin)/.test(line)) { const lineNum = idx + 1; // Check for rate limiting in nearby lines const context = lines.slice(Math.max(0, idx-5), idx+5).join('\n'); if (!context.includes('rateLimit') && !context.includes('rate-limit')) { issues.push({ file: filePath, line: lineNum, type: 'missing_rate_limit', severity: 'HIGH', text: line.trim(), message: 'API endpoint missing rate limiting (inst_045)' }); } // Check for authentication if (!context.includes('auth') && !context.includes('requireAuth') && !context.includes('authenticate')) { issues.push({ file: filePath, line: lineNum, type: 'missing_auth', severity: 'HIGH', text: line.trim(), message: 'API endpoint missing authentication (inst_045)' }); } } // Check for sensitive runtime data exposure (inst_013) if (/res\.(send|json)\s*\(.*\b(process\.memoryUsage|process\.cpuUsage|os\.|__dirname|__filename)/.test(line)) { issues.push({ file: filePath, line: idx + 1, type: 'runtime_data_exposure', severity: 'CRITICAL', text: line.trim(), message: 'Exposes sensitive runtime data in API response (inst_013)' }); } }); return issues; } function scanFiles(files) { const allIssues = []; files.forEach(file => { if (!fs.existsSync(file)) return; if (!file.match(/\.(js|ts)$/)) return; if (file.includes('node_modules') || file.includes('test')) return; try { const issues = checkAPIEndpoint(file); allIssues.push(...issues); } catch (err) { // Skip unreadable files } }); return allIssues; } function main() { console.log('\nšŸ”’ API Security Validation (inst_013/045)\n'); const files = process.argv.slice(2); if (files.length === 0) { console.log('Usage: check-api-security.js [file2] ...'); console.log('āœ… No files provided - skipping API security check\n'); process.exit(0); } const issues = scanFiles(files); if (issues.length === 0) { console.log('āœ… API security requirements met\n'); process.exit(0); } console.log(`āš ļø Found ${issues.length} security issue(s):\n`); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); issues.forEach(i => { const icon = i.severity === 'CRITICAL' ? 'šŸ”“' : '🟔'; console.log(`${icon} ${i.file}:${i.line}`); console.log(` ${i.message}`); console.log(` ${i.text.substring(0, 70)}`); console.log(''); }); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); console.log('Fix: Add rate limiting and authentication to all API endpoints\n'); process.exit(1); } main();