UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

260 lines 11.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateRiskRating = calculateRiskRating; exports.formatCVSSScore = formatCVSSScore; exports.formatSeverityBadge = formatSeverityBadge; exports.generateRiskMatrix = generateRiskMatrix; exports.generateSecurityRiskReport = generateSecurityRiskReport; exports.explainCVSSVector = explainCVSSVector; const chalk_1 = __importDefault(require("chalk")); /** * Calculates a risk rating based on impact and likelihood * @param impact Impact rating * @param likelihood Likelihood rating * @returns Risk rating (critical, high, medium, low, info) */ function calculateRiskRating(impact, likelihood) { // Convert string ratings to numerical values for calculation const impactValue = impactToValue(impact); const likelihoodValue = likelihoodToValue(likelihood); // Calculate risk score on a scale of 1-25 const score = impactValue * likelihoodValue; // Map score to risk rating if (score >= 20) return 'critical'; if (score >= 12) return 'high'; if (score >= 6) return 'medium'; if (score >= 3) return 'low'; return 'info'; } /** * Maps impact level to a numerical value (1-5) */ function impactToValue(impact) { switch (impact) { case 'critical': return 5; case 'high': return 4; case 'medium': return 3; case 'low': return 2; case 'info': return 1; default: return 1; } } /** * Maps likelihood level to a numerical value (1-5) */ function likelihoodToValue(likelihood) { switch (likelihood) { case 'very-high': return 5; case 'high': return 4; case 'medium': return 3; case 'low': return 2; case 'very-low': return 1; default: return 1; } } /** * Formats a CVSS score with color based on severity * @param score CVSS score (0.0-10.0) * @returns Colored string representation */ function formatCVSSScore(score) { if (score >= 9.0) return chalk_1.default.bgRed.white(` ${score.toFixed(1)} Critical `); if (score >= 7.0) return chalk_1.default.bgRed(` ${score.toFixed(1)} High `); if (score >= 4.0) return chalk_1.default.bgYellow.black(` ${score.toFixed(1)} Medium `); if (score >= 0.1) return chalk_1.default.bgGreen.black(` ${score.toFixed(1)} Low `); return chalk_1.default.bgBlue.white(` ${score.toFixed(1)} Info `); } /** * Generates a colored security risk badge based on severity * @param severity Risk severity * @returns Colored badge string */ function formatSeverityBadge(severity) { switch (severity.toLowerCase()) { case 'critical': return chalk_1.default.bgRed.white(' CRITICAL '); case 'high': return chalk_1.default.bgRed(' HIGH '); case 'medium': return chalk_1.default.bgYellow.black(' MEDIUM '); case 'low': return chalk_1.default.bgGreen.black(' LOW '); case 'info': return chalk_1.default.bgBlue.white(' INFO '); default: return chalk_1.default.gray(` ${severity.toUpperCase()} `); } } /** * Creates a visual risk matrix representation * @returns ASCII risk matrix as a string */ function generateRiskMatrix() { const matrix = [ '╔════════════════╤══════════════════════════════════════════╗', '║ │ LIKELIHOOD ║', '║ ├──────┬──────┬────────┬─────────┬────────╢', '║ IMPACT │ V.LOW│ LOW │ MEDIUM │ HIGH │ V.HIGH ║', '╟────────────────┼──────┼──────┼────────┼─────────┼────────╢', `║ CRITICAL │${chalk_1.default.bgGreen.black(' MED ')}${chalk_1.default.bgYellow.black(' HIGH ')}${chalk_1.default.bgRed(' HIGH ')}${chalk_1.default.bgRed.white(' CRIT ')}${chalk_1.default.bgRed.white(' CRIT ')}║`, `║ HIGH │${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgYellow.black(' MED ')}${chalk_1.default.bgYellow.black(' HIGH ')}${chalk_1.default.bgRed(' HIGH ')}${chalk_1.default.bgRed.white(' CRIT ')}║`, `║ MEDIUM │${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgYellow.black(' MED ')}${chalk_1.default.bgYellow.black(' HIGH ')}${chalk_1.default.bgRed(' HIGH ')}║`, `║ LOW │${chalk_1.default.bgBlue.white(' INFO ')}${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgYellow.black(' MED ')}${chalk_1.default.bgYellow.black(' MED ')}║`, `║ INFO │${chalk_1.default.bgBlue.white(' INFO ')}${chalk_1.default.bgBlue.white(' INFO ')}${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgGreen.black(' LOW ')}${chalk_1.default.bgGreen.black(' LOW ')}║`, '╚════════════════╧══════╧══════╧════════╧═════════╧════════╝', ].join('\n'); return matrix; } /** * Generates a detailed risk report for a list of security checklist items * @param items Array of security checklist items * @returns Formatted risk report as a string */ function generateSecurityRiskReport(items) { // Only include security items with risk scores const securityItems = items.filter(item => item.category === 'Security' && item.riskScore); if (securityItems.length === 0) { return chalk_1.default.green('No security issues found with risk scores.'); } // Sort by risk score (highest first) securityItems.sort((a, b) => { const scoreA = a.riskScore?.score || 0; const scoreB = b.riskScore?.score || 0; return scoreB - scoreA; }); let report = chalk_1.default.bold('\n🔒 SECURITY RISK REPORT\n\n'); // Add risk matrix report += generateRiskMatrix() + '\n\n'; // Summary section const criticalCount = securityItems.filter(item => item.severity === 'critical').length; const highCount = securityItems.filter(item => item.severity === 'high').length; const mediumCount = securityItems.filter(item => item.severity === 'medium').length; const lowCount = securityItems.filter(item => item.severity === 'low').length; const infoCount = securityItems.filter(item => item.severity === 'info').length; report += chalk_1.default.bold('SUMMARY:\n'); report += `${formatSeverityBadge('critical')} ${criticalCount} issues\n`; report += `${formatSeverityBadge('high')} ${highCount} issues\n`; report += `${formatSeverityBadge('medium')} ${mediumCount} issues\n`; report += `${formatSeverityBadge('low')} ${lowCount} issues\n`; report += `${formatSeverityBadge('info')} ${infoCount} issues\n\n`; // Detailed findings report += chalk_1.default.bold('TOP RISKS:\n\n'); securityItems.slice(0, 5).forEach((item, index) => { const score = item.riskScore?.score || 0; const references = item.references || []; const remediation = item.remediation; report += `${index + 1}. ${chalk_1.default.bold(item.title)} ${formatCVSSScore(score)}\n`; report += ` ${chalk_1.default.gray('ID:')} ${item.id}\n`; report += ` ${chalk_1.default.gray('File:')} ${item.file || 'Unknown'}\n`; report += ` ${chalk_1.default.gray('Description:')} ${item.description}\n`; if (references.length > 0) { const ref = references[0]; report += ` ${chalk_1.default.gray('Reference:')} ${ref.cwe || ''} ${ref.owasp || ''}\n`; } if (remediation) { report += ` ${chalk_1.default.gray('Remediation:')} ${remediation.description}\n`; if (remediation.codeExample) { report += ` ${chalk_1.default.gray('Example:')} ${chalk_1.default.green(remediation.codeExample)}\n`; } report += ` ${chalk_1.default.gray('Priority:')} ${remediation.priority || 'medium'}\n`; } report += '\n'; }); return report; } /** * Converts a CVSS vector string to a human-readable explanation * @param vector CVSS vector string (e.g., "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N") * @returns Human-readable explanation */ function explainCVSSVector(vector) { if (!vector.includes('/')) return 'Invalid CVSS vector format'; const parts = vector.split('/'); let explanation = ''; for (const part of parts) { if (!part.includes(':')) continue; const [key, value] = part.split(':'); switch (key) { case 'AV': explanation += `Attack Vector: ${explainAttackVector(value)}\n`; break; case 'AC': explanation += `Attack Complexity: ${explainAttackComplexity(value)}\n`; break; case 'PR': explanation += `Privileges Required: ${explainPrivilegesRequired(value)}\n`; break; case 'UI': explanation += `User Interaction: ${explainUserInteraction(value)}\n`; break; case 'S': explanation += `Scope: ${explainScope(value)}\n`; break; case 'C': explanation += `Confidentiality Impact: ${explainImpact(value)}\n`; break; case 'I': explanation += `Integrity Impact: ${explainImpact(value)}\n`; break; case 'A': explanation += `Availability Impact: ${explainImpact(value)}\n`; break; } } return explanation; } // Helper functions for CVSS vector explanation function explainAttackVector(value) { switch (value) { case 'N': return 'Network (Remotely exploitable)'; case 'A': return 'Adjacent Network (Adjacent access required)'; case 'L': return 'Local (Local access required)'; case 'P': return 'Physical (Physical access required)'; default: return value; } } function explainAttackComplexity(value) { switch (value) { case 'L': return 'Low (No specialized conditions needed)'; case 'H': return 'High (Specialized conditions required)'; default: return value; } } function explainPrivilegesRequired(value) { switch (value) { case 'N': return 'None (No privileges required)'; case 'L': return 'Low (Low level privileges required)'; case 'H': return 'High (High level privileges required)'; default: return value; } } function explainUserInteraction(value) { switch (value) { case 'N': return 'None (No user interaction required)'; case 'R': return 'Required (User interaction required)'; default: return value; } } function explainScope(value) { switch (value) { case 'U': return 'Unchanged (Vulnerability impacts only the vulnerable component)'; case 'C': return 'Changed (Vulnerability can affect resources beyond the vulnerable component)'; default: return value; } } function explainImpact(value) { switch (value) { case 'N': return 'None'; case 'L': return 'Low'; case 'H': return 'High'; default: return value; } } //# sourceMappingURL=securityRiskUtils.js.map