UNPKG

endpoint-sentinel

Version:

User-friendly security scanner with interactive setup that scales from beginner to expert

338 lines 15.6 kB
"use strict"; /** * CLI Output Utilities * Rich terminal output with progress indicators and formatting */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateFilenameFromUrl = generateFilenameFromUrl; exports.displayBanner = displayBanner; exports.displayProgress = displayProgress; exports.displayResults = displayResults; exports.displayError = displayError; exports.displayWarning = displayWarning; exports.displaySuccess = displaySuccess; const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); /** * Generate a safe filename from a URL */ function generateFilenameFromUrl(url) { try { const urlObj = new URL(url); // Create base filename from hostname let filename = urlObj.hostname.replace(/[^a-zA-Z0-9.-]/g, '-'); // Add path if it's not just root if (urlObj.pathname && urlObj.pathname !== '/') { const pathPart = urlObj.pathname .replace(/^\/+|\/+$/g, '') // Remove leading/trailing slashes .replace(/[^a-zA-Z0-9.-]/g, '-') // Replace invalid chars .replace(/-+/g, '-') // Collapse multiple dashes .substring(0, 50); // Limit length if (pathPart) { filename += `_${pathPart}`; } } // Add timestamp to make unique and prevent conflicts const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0]; return `${filename}_${timestamp}.json`; } catch (error) { // Fallback for invalid URLs const safeName = url.replace(/[^a-zA-Z0-9]/g, '-').replace(/-+/g, '-'); const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0]; return `scan_${safeName}_${timestamp}.json`; } } /** * Progress spinner utilities */ function displayBanner() { // Line 1 - ENDPOINT - Normal start, glare begins at center (around the D) console.log(chalk_1.default.blue.bold('███████╗███╗ ██╗██████╗ ') + chalk_1.default.cyan.bold('██████╗ ██████╗ ██╗███╗ ██╗████████╗')); // Line 2 - Glare moves left from center D console.log(chalk_1.default.blue.bold('██╔════╝████╗ ██║██╔══██╗') + chalk_1.default.cyan.bold('██╔══██╗██╔═══██╗██║████╗ ██║╚══██╔══╝')); // Line 3 - Glare continues diagonal down-left console.log(chalk_1.default.blue.bold('█████╗ ██╔██╗ ██║') + chalk_1.default.cyan.bold('██║ ██║██████╔╝██║ ██║██║██╔██╗ ██║ ██║ ')); // Line 4 - Glare moving more left console.log(chalk_1.default.blue.bold('██╔══╝ ') + chalk_1.default.cyan.bold('██║╚██╗██║██║ ██║██╔═══╝ ██║ ██║██║██║╚██╗██║ ██║ ')); // Line 5 - Glare reaches left side console.log(chalk_1.default.cyan.bold('███████╗██║ ╚████║██████╔╝██║ ╚██████╔╝██║██║ ╚████║ ██║ ')); // Line 6 - Separator console.log(chalk_1.default.blue.bold('╚══════╝╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ')); console.log(' '); // Line 8 - SENTINEL - Glare continues diagonal pattern (more on left) console.log(chalk_1.default.cyan.bold('███████╗███████╗███╗ ██╗████████╗██╗███╗ ██╗') + chalk_1.default.blue.bold('███████╗██╗ ')); // Line 9 - Glare reducing as it goes down-left console.log(chalk_1.default.cyan.bold('██╔════╝██╔════╝████╗ ██║╚══██╔══╝██║████╗ ██║') + chalk_1.default.blue.bold('██╔════╝██║ ')); // Line 10 - Glare more focused on left console.log(chalk_1.default.cyan.bold('███████╗█████╗ ██╔██╗ ██║ ██║ ██║') + chalk_1.default.blue.bold('██╔██╗ ██║█████╗ ██║ ')); // Line 11 - Glare mostly on left side console.log(chalk_1.default.cyan.bold('╚════██║██╔══╝ ██║╚██╗██║ ██║ ') + chalk_1.default.blue.bold('██║██║╚██╗██║██╔══╝ ██║ ')); // Line 12 - Final line - glare ends on left console.log(chalk_1.default.cyan.bold('███████║███████╗██║ ╚████║ ██║ ') + chalk_1.default.blue.bold('██║██║ ╚████║███████╗███████╗')); // Line 13 - Bottom console.log(chalk_1.default.blue.bold('╚══════╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝')); console.log(chalk_1.default.red.bold('\n🛡️ ADVANCED SECURITY RECONNAISSANCE TOOLKIT')); console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); console.log(chalk_1.default.cyan(' Intelligent endpoint discovery • Vulnerability assessment • Security analysis')); console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n')); } function displayProgress() { const messages = [ '🔍 Initializing security scan...', '🌐 Establishing connection...', '🕷️ Discovering endpoints...', '🔐 Analyzing authentication...', '🛡️ Checking security headers...', '📊 Generating report...' ]; let messageIndex = 0; const spinner = (0, ora_1.default)(messages[0]).start(); const interval = setInterval(() => { messageIndex = (messageIndex + 1) % messages.length; spinner.text = messages[messageIndex] || '🔍 Processing...'; }, 2000); const originalStop = spinner.stop.bind(spinner); spinner.stop = () => { clearInterval(interval); return originalStop(); }; return spinner; } /** * Displays scan results with formatting and automatic JSON output */ async function displayResults(results, format = 'console', outputFile) { // Always create a JSON file - either custom name or auto-generated let jsonFileName; if (outputFile) { jsonFileName = outputFile; } else { jsonFileName = generateFilenameFromUrl(results.target); } switch (format.toLowerCase()) { case 'json': await displayJsonResults(results, jsonFileName); break; case 'csv': await displayCsvResults(results, outputFile); // Also create JSON for consistency await displayJsonResults(results, jsonFileName); break; case 'console': default: displayConsoleResults(results); // Always create JSON file for analysis await displayJsonResults(results, jsonFileName); break; } } /** * Displays results in console format with colors and formatting */ function displayConsoleResults(results) { console.log(chalk_1.default.green.bold('\n🎯 SCAN COMPLETED SUCCESSFULLY\n')); // Summary stats console.log(chalk_1.default.blue('📊 SCAN SUMMARY')); console.log(` Target: ${chalk_1.default.white(results.target)}`); console.log(` Duration: ${chalk_1.default.white(Math.round(results.duration / 1000))}s`); console.log(` Endpoints: ${chalk_1.default.white(results.endpointsDiscovered)}`); console.log(` Findings: ${chalk_1.default.white(results.findings.length)}`); if (results.summary) { const summary = results.summary; if (summary.criticalFindings > 0) { console.log(` ${chalk_1.default.red.bold('Critical')}: ${chalk_1.default.red(summary.criticalFindings)}`); } if (summary.highFindings > 0) { console.log(` ${chalk_1.default.red('High')}: ${chalk_1.default.red(summary.highFindings)}`); } if (summary.mediumFindings > 0) { console.log(` ${chalk_1.default.yellow('Medium')}: ${chalk_1.default.yellow(summary.mediumFindings)}`); } if (summary.lowFindings > 0) { console.log(` ${chalk_1.default.blue('Low')}: ${chalk_1.default.blue(summary.lowFindings)}`); } if (summary.infoFindings > 0) { console.log(` ${chalk_1.default.gray('Info')}: ${chalk_1.default.gray(summary.infoFindings)}`); } } // Sample findings if (results.findings.length > 0) { console.log(chalk_1.default.blue('\n🔍 TOP FINDINGS')); const topFindings = results.findings .sort((a, b) => { const severityOrder = { critical: 5, high: 4, medium: 3, low: 2, info: 1 }; return (severityOrder[b.severity] || 0) - (severityOrder[a.severity] || 0); }) .slice(0, 5); topFindings.forEach((finding, index) => { const severityColor = { critical: chalk_1.default.red.bold, high: chalk_1.default.red, medium: chalk_1.default.yellow, low: chalk_1.default.blue, info: chalk_1.default.gray }[finding.severity] || chalk_1.default.gray; console.log(`\n${index + 1}. ${severityColor(finding.severity.toUpperCase())} - ${finding.title}`); console.log(` ${chalk_1.default.gray('Endpoint:')} ${finding.endpoint}`); console.log(` ${chalk_1.default.gray('Impact:')} ${finding.description}`); }); if (results.findings.length > 5) { console.log(chalk_1.default.gray(`\n ... and ${results.findings.length - 5} more findings`)); } } displayFooter(); } /** * Displays findings section with severity-based coloring */ /** * Groups findings by severity level */ /** * Displays a group of findings for a specific severity */ /** * Gets color function for severity level */ /** * Gets icon for severity level */ /** * Displays performance metrics */ /** * Displays footer with recommendations */ function displayFooter() { console.log(chalk_1.default.gray('\n📄 Detailed results saved to JSON file for analysis')); console.log(chalk_1.default.gray('🛡️ Review findings and apply recommended remediations')); console.log(chalk_1.default.gray('⚡ For help: es --help\n')); } /** * Saves results in JSON format */ async function displayJsonResults(results, outputFile) { const jsonOutput = JSON.stringify(results, null, 2); if (outputFile) { const resolvedPath = path.resolve(outputFile); const dir = path.dirname(resolvedPath); // Ensure directory exists if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(resolvedPath, jsonOutput, 'utf-8'); console.log(chalk_1.default.green(`📄 Results saved to: ${resolvedPath}`)); } else { console.log(jsonOutput); } } /** * Saves results in CSV format */ async function displayCsvResults(results, outputFile) { const csvHeader = 'endpoint,type,severity,confidence,title,description,remediation\n'; const csvRows = results.findings.map(finding => { const escapeCsv = (text) => `"${text.replace(/"/g, '""')}"`; return [ escapeCsv(finding.endpoint), escapeCsv(finding.type), escapeCsv(finding.severity), escapeCsv(finding.confidence), escapeCsv(finding.title), escapeCsv(finding.description), escapeCsv(finding.remediation) ].join(','); }).join('\n'); const csvOutput = csvHeader + csvRows; if (outputFile) { const resolvedPath = path.resolve(outputFile); const dir = path.dirname(resolvedPath); // Ensure directory exists if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(resolvedPath, csvOutput, 'utf-8'); console.log(chalk_1.default.green(`📊 CSV results saved to: ${resolvedPath}`)); } else { console.log(csvOutput); } } /** * Displays error message with formatting */ function displayError(message, error) { console.log(chalk_1.default.red.bold('❌ ERROR')); console.log(chalk_1.default.red(` ${message}`)); if (error && error.message) { console.log(chalk_1.default.gray(` Details: ${error.message}`)); } } /** * Displays warning message */ function displayWarning(message) { console.log(chalk_1.default.yellow.bold('⚠️ WARNING')); console.log(chalk_1.default.yellow(message)); console.log(''); } /** * Displays success message */ function displaySuccess(message) { console.log(chalk_1.default.green.bold('✅ SUCCESS')); console.log(chalk_1.default.green(message)); console.log(''); } //# sourceMappingURL=output.js.map