vibesec
Version:
Security scanner for AI-generated code - detects vulnerabilities in vibe-coded projects
229 lines • 10.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StakeholderReporter = void 0;
const types_1 = require("../scanner/core/types");
const security_score_1 = require("../lib/utils/security-score");
class StakeholderReporter {
generate(result) {
const securityScore = (0, security_score_1.calculateSecurityScore)(result);
const benchmark = (0, security_score_1.getBenchmarkComparison)(securityScore.score, result.scan.filesScanned);
const lines = [];
lines.push('═'.repeat(70));
lines.push(' SECURITY ASSESSMENT REPORT');
lines.push('═'.repeat(70));
lines.push('');
lines.push('EXECUTIVE SUMMARY');
lines.push('─'.repeat(70));
lines.push('');
lines.push(`Project: ${this.getProjectName(result.scan.path)}`);
lines.push(`Assessment Date: ${new Date(result.scan.timestamp).toLocaleDateString()}`);
lines.push(`Files Analyzed: ${result.scan.filesScanned}`);
lines.push(`Analysis Duration: ${result.scan.duration.toFixed(1)} seconds`);
lines.push('');
lines.push('SECURITY SCORE');
lines.push('─'.repeat(70));
lines.push('');
lines.push(`Overall Score: ${securityScore.score}/100 (${securityScore.grade})`);
lines.push(`Security Rating: ${securityScore.rating}`);
lines.push('');
lines.push(`Benchmark: ${benchmark}`);
lines.push('');
lines.push('RISK ASSESSMENT');
lines.push('─'.repeat(70));
lines.push('');
lines.push(this.formatRiskAssessment(result, securityScore));
lines.push('');
lines.push('FINDINGS SUMMARY');
lines.push('─'.repeat(70));
lines.push('');
const { bySeverity } = result.summary;
if (result.summary.total === 0) {
lines.push('✓ No security vulnerabilities detected');
lines.push('');
lines.push('The codebase follows security best practices and no');
lines.push('immediate security concerns were identified.');
lines.push('');
}
else {
lines.push(`Total Security Issues: ${result.summary.total}`);
lines.push('');
lines.push('Breakdown by Severity:');
lines.push(` • Critical (Immediate Action): ${bySeverity.critical}`);
lines.push(` • High (This Week): ${bySeverity.high}`);
lines.push(` • Medium (This Month): ${bySeverity.medium}`);
lines.push(` • Low (Best Practice): ${bySeverity.low}`);
lines.push('');
if (bySeverity.critical > 0 || bySeverity.high > 0) {
lines.push('KEY ISSUES REQUIRING ATTENTION');
lines.push('─'.repeat(70));
lines.push('');
lines.push(this.formatKeyIssues(result));
lines.push('');
}
}
lines.push('RECOMMENDATIONS');
lines.push('─'.repeat(70));
lines.push('');
lines.push(securityScore.recommendation);
lines.push('');
if (result.summary.total > 0) {
lines.push('Recommended Actions:');
lines.push(this.formatRecommendedActions(result));
lines.push('');
}
lines.push('BUSINESS IMPACT');
lines.push('─'.repeat(70));
lines.push('');
lines.push(this.formatBusinessImpact(result, securityScore));
lines.push('');
lines.push('═'.repeat(70));
lines.push('Generated by VibeSec Security Scanner');
lines.push(`Report Date: ${new Date().toISOString()}`);
lines.push('═'.repeat(70));
return lines.join('\n');
}
getProjectName(path) {
const parts = path.split('/');
return parts[parts.length - 1] || 'Current Project';
}
formatRiskAssessment(result, securityScore) {
const { bySeverity } = result.summary;
const lines = [];
if (securityScore.score >= 90) {
lines.push('Risk Level: LOW');
lines.push('');
lines.push('The codebase demonstrates strong security practices with');
lines.push('minimal vulnerabilities. Continue monitoring and maintaining');
lines.push('current security standards.');
}
else if (securityScore.score >= 70) {
lines.push('Risk Level: MODERATE');
lines.push('');
lines.push('The codebase has some security concerns that should be');
lines.push('addressed. Prioritize fixing high-severity issues to reduce');
lines.push('potential security risks.');
}
else {
lines.push('Risk Level: HIGH');
lines.push('');
lines.push('The codebase contains significant security vulnerabilities');
lines.push('that require immediate attention. Failure to address these');
lines.push('issues may result in data breaches or security incidents.');
}
if (bySeverity.critical > 0) {
lines.push('');
lines.push(`⚠️ CRITICAL: ${bySeverity.critical} critical issue${bySeverity.critical > 1 ? 's' : ''} require immediate remediation.`);
}
return lines.join('\n');
}
formatKeyIssues(result) {
const keyFindings = result.findings
.filter((f) => f.severity === types_1.Severity.CRITICAL || f.severity === types_1.Severity.HIGH)
.slice(0, 5);
const lines = [];
keyFindings.forEach((finding, idx) => {
lines.push(`${idx + 1}. ${finding.title}`);
lines.push(` Severity: ${finding.severity.toUpperCase()}`);
lines.push(` Location: ${finding.location.file}`);
lines.push(` Impact: ${this.getBusinessImpact(finding)}`);
lines.push('');
});
if (result.findings.length > 5) {
lines.push(`... and ${result.findings.length - 5} additional issue${result.findings.length - 5 > 1 ? 's' : ''}`);
}
return lines.join('\n');
}
formatRecommendedActions(result) {
const { bySeverity } = result.summary;
const lines = [];
let actionNumber = 1;
if (bySeverity.critical > 0) {
lines.push(` ${actionNumber}. Fix ${bySeverity.critical} critical issue${bySeverity.critical > 1 ? 's' : ''} within 24 hours`);
actionNumber++;
}
if (bySeverity.high > 0) {
lines.push(` ${actionNumber}. Address ${bySeverity.high} high-severity issue${bySeverity.high > 1 ? 's' : ''} within 7 days`);
actionNumber++;
}
if (bySeverity.medium > 0) {
lines.push(` ${actionNumber}. Schedule remediation of ${bySeverity.medium} medium-severity issue${bySeverity.medium > 1 ? 's' : ''}`);
actionNumber++;
}
lines.push(` ${actionNumber}. Conduct follow-up scan after remediation to verify fixes`);
actionNumber++;
lines.push(` ${actionNumber}. Implement regular security scanning in development workflow`);
return lines.join('\n');
}
formatBusinessImpact(result, securityScore) {
const { bySeverity } = result.summary;
const lines = [];
if (result.summary.total === 0) {
lines.push('Positive Impact:');
lines.push(' • Low risk of security incidents');
lines.push(' • Reduced liability and compliance concerns');
lines.push(' • Enhanced customer trust and brand reputation');
lines.push(' • Lower potential costs from security breaches');
return lines.join('\n');
}
lines.push('Potential Risks if Unaddressed:');
if (bySeverity.critical > 0) {
lines.push(' • HIGH RISK: Potential for immediate security breach');
lines.push(' • Financial exposure from data theft or service disruption');
lines.push(' • Regulatory compliance violations and fines');
lines.push(' • Reputational damage and loss of customer trust');
}
else if (bySeverity.high > 0) {
lines.push(' • MODERATE RISK: Vulnerabilities exploitable by attackers');
lines.push(' • Potential for data exposure or unauthorized access');
lines.push(' • Compliance concerns depending on industry');
lines.push(' • Increased attack surface');
}
else {
lines.push(' • LOW RISK: Minor security improvements recommended');
lines.push(' • Adherence to security best practices');
lines.push(' • Reduced future technical debt');
}
lines.push('');
lines.push('Cost of Remediation:');
const estimatedHours = this.estimateRemediationHours(result);
lines.push(` Estimated engineering time: ${estimatedHours.min}-${estimatedHours.max} hours`);
return lines.join('\n');
}
getBusinessImpact(finding) {
const impacts = {
secrets: 'Unauthorized access to systems and services',
injection: 'Database compromise and data theft',
'sql-injection': 'Complete database access and data manipulation',
xss: 'User account compromise and phishing attacks',
auth: 'Unauthorized access to protected resources',
'command-injection': 'Complete system takeover',
default: 'Security vulnerability exploitation',
};
const categoryKey = finding.category.toLowerCase();
const ruleKey = finding.rule.toLowerCase();
return impacts[ruleKey] || impacts[categoryKey] || impacts['default'];
}
estimateRemediationHours(result) {
const { bySeverity } = result.summary;
const timePerIssue = {
critical: { min: 0.5, max: 2 },
high: { min: 0.3, max: 1 },
medium: { min: 0.2, max: 0.5 },
low: { min: 0.1, max: 0.3 },
};
const minHours = bySeverity.critical * timePerIssue.critical.min +
bySeverity.high * timePerIssue.high.min +
bySeverity.medium * timePerIssue.medium.min +
bySeverity.low * timePerIssue.low.min;
const maxHours = bySeverity.critical * timePerIssue.critical.max +
bySeverity.high * timePerIssue.high.max +
bySeverity.medium * timePerIssue.medium.max +
bySeverity.low * timePerIssue.low.max;
return {
min: Math.ceil(minHours),
max: Math.ceil(maxHours),
};
}
}
exports.StakeholderReporter = StakeholderReporter;
//# sourceMappingURL=stakeholder.js.map