UNPKG

pury

Version:

đŸ›Ąī¸ AI-powered security scanner with advanced threat detection, dual reporting system (detailed & summary), and comprehensive code analysis

316 lines â€ĸ 15.6 kB
import { Severity } from '../types/index.js'; export class MarkdownReporter { async output(report) { return this.generateMarkdownReport(report); } async writeToFile(report, filePath) { const fs = await import('fs/promises'); const path = await import('path'); // Ensure directory exists await fs.mkdir(path.dirname(filePath), { recursive: true }); const markdown = this.generateMarkdownReport(report); await fs.writeFile(filePath, markdown, 'utf8'); } generateMarkdownReport(report) { const lines = []; // Header with enhanced scientific presentation lines.push('# đŸ›Ąī¸ PuryAI Security Analysis Report'); lines.push(''); lines.push('> **Comprehensive Security Assessment & Risk Analysis**'); lines.push('> '); lines.push('> *Advanced AI-Powered Static Code Analysis with Multi-Layer Detection*'); lines.push(''); lines.push('---'); lines.push(''); // Executive Summary lines.push('## 📋 Executive Summary'); lines.push(''); const riskLevel = this.calculateOverallRiskLevel(report.summary.severityCount); const riskScore = this.calculateRiskScore(report.summary.severityCount, report.summary.filesScanned); lines.push(`**Overall Risk Assessment:** ${riskLevel} (Score: ${riskScore}/100)`); lines.push(`**Analysis Scope:** ${report.summary.filesScanned} files analyzed`); lines.push(`**Total Findings:** ${report.summary.threatsFound} security and quality issues identified`); lines.push(''); // Detailed Metrics lines.push('## 📊 Quantitative Analysis'); lines.push(''); // Enhanced metrics table const scanRate = report.summary.filesScanned > 0 ? (report.summary.filesScanned / (report.summary.scanDuration / 1000)).toFixed(2) : '0'; const avgIssuesPerFile = report.summary.filesScanned > 0 ? (report.summary.threatsFound / report.summary.filesScanned).toFixed(2) : '0'; lines.push('| Metric | Value | Analysis |'); lines.push('|--------|-------|----------|'); lines.push(`| **Files Analyzed** | ${report.summary.filesScanned} | Target scope coverage |`); lines.push(`| **Security Issues** | ${report.summary.threatsFound} | Total findings across all categories |`); lines.push(`| **Scan Duration** | ${(report.summary.scanDuration / 1000).toFixed(2)}s | Processing efficiency |`); lines.push(`| **Analysis Rate** | ${scanRate} files/sec | Performance metric |`); lines.push(`| **Issue Density** | ${avgIssuesPerFile} issues/file | Code quality indicator |`); lines.push(`| **Risk Score** | ${riskScore}/100 | Composite risk assessment |`); lines.push(`| **Scan Timestamp** | ${new Date(report.metadata.timestamp).toLocaleString()} | Analysis execution time |`); if (report.metadata.aiProvider) { lines.push(`| **AI Analysis Engine** | ${report.metadata.aiProvider} | Detection methodology |`); } lines.push(''); // Enhanced severity analysis if (report.summary.threatsFound > 0) { lines.push('### đŸŽ¯ Risk Distribution Analysis'); lines.push(''); // Calculate percentages and risk weights const totalIssues = report.summary.threatsFound; lines.push('| Severity Level | Count | Percentage | Risk Weight | Priority |'); lines.push('|----------------|-------|------------|-------------|----------|'); const severityData = [ { level: 'Critical', key: 'critical', weight: 10, priority: 'Immediate Action Required' }, { level: 'High', key: 'high', weight: 7, priority: 'Address within 24h' }, { level: 'Medium', key: 'medium', weight: 4, priority: 'Plan remediation' }, { level: 'Low', key: 'low', weight: 1, priority: 'Monitor & review' } ]; for (const sev of severityData) { const count = report.summary.severityCount[sev.key] || 0; if (count > 0) { const percentage = ((count / totalIssues) * 100).toFixed(1); const icon = this.getSeverityIcon(sev.key); const badge = this.getSeverityBadge(sev.key); lines.push(`| ${icon} **${sev.level}** ${badge} | ${count} | ${percentage}% | ${sev.weight}/10 | ${sev.priority} |`); } } lines.push(''); } // Enhanced findings analysis if (report.findings.length > 0) { lines.push('## đŸ”Ŧ Detailed Security Findings Analysis'); lines.push(''); lines.push('> **Methodology:** Static analysis with pattern recognition, entropy analysis, and AI-powered threat detection'); lines.push(''); const groupedByFile = this.groupFindingsByFile(report.findings); const basePath = process.cwd(); let fileIndex = 1; for (const [filePath, findings] of groupedByFile.entries()) { const relativePath = this.getRelativePath(filePath, basePath); const fileRiskScore = this.calculateFileRiskScore(findings); const issueCount = findings.length; lines.push(`### ${fileIndex}. 📄 \`${relativePath}\``); lines.push(''); lines.push(`**File Risk Assessment:** ${fileRiskScore}/100 | **Issues Found:** ${issueCount}`); lines.push(''); // Group by severity for this file const severityGroups = this.groupFindingsBySeverity(findings); for (const severity of ['critical', 'high', 'medium', 'low']) { const severityFindings = severityGroups[severity]; if (severityFindings && severityFindings.length > 0) { const icon = this.getSeverityIcon(severity); const badge = this.getSeverityBadge(severity); lines.push(`#### ${icon} ${severity.toUpperCase()} SEVERITY ${badge}`); lines.push(''); // Group by type for scientific analysis const typeGroups = this.groupFindingsByType(severityFindings); for (const [issueType, typeFindings] of typeGroups.entries()) { const frequency = typeFindings.length; const confidenceLevel = this.calculateConfidenceLevel(typeFindings); lines.push(`**🔍 Issue Pattern:** ${issueType}`); lines.push(`**📊 Detection Frequency:** ${frequency} occurrence${frequency > 1 ? 's' : ''}`); lines.push(`**đŸŽ¯ Confidence Level:** ${confidenceLevel}%`); lines.push(''); if (typeFindings.length === 1) { const finding = typeFindings[0]; lines.push(`**📍 Location:** ${finding.line ? `Line ${finding.line}` : 'File-level'}`); if (finding.evidence && finding.evidence.length <= 100) { lines.push(`**đŸ”Ŧ Evidence:** \`${finding.evidence}\``); } if (finding.description) { lines.push(`**📝 Analysis:** ${finding.description}`); } if (finding.suggestion) { lines.push(`**💡 Remediation:** ${finding.suggestion}`); } } else { lines.push(`**📍 Locations:** Lines ${typeFindings.map(f => f.line || '?').join(', ')}`); if (typeFindings[0]?.suggestion) { lines.push(`**💡 Remediation:** ${typeFindings[0].suggestion}`); } } lines.push(''); } } } lines.push('---'); lines.push(''); fileIndex++; } } else { lines.push('## ✅ No Security Issues Found!'); lines.push(''); lines.push('🎉 **Congratulations!** Your code appears clean and secure.'); lines.push(''); } // Recommendations if (report.summary.threatsFound > 0) { lines.push('## 💡 Recommendations'); lines.push(''); lines.push('### Immediate Actions'); lines.push(''); const criticalCount = report.summary.severityCount.critical || 0; const highCount = report.summary.severityCount.high || 0; if (criticalCount > 0) { lines.push(`- 🚨 **URGENT**: Address all ${criticalCount} critical severity issues immediately`); } if (highCount > 0) { lines.push(`- âš ī¸ **HIGH PRIORITY**: Review and fix ${highCount} high severity issues`); } lines.push('- 📋 Review medium and low priority issues for code quality improvements'); lines.push('- 🔄 Run scans regularly to catch issues early'); lines.push('- 📊 Use `--format json` for detailed programmatic analysis'); lines.push('- đŸŽ¯ Consider running additional analyzers with `--analyzers` flag'); lines.push(''); lines.push('### Security Best Practices'); lines.push(''); lines.push('- 🔐 Never commit secrets, API keys, or credentials to version control'); lines.push('- đŸ›Ąī¸ Keep dependencies updated and scan for vulnerabilities regularly'); lines.push('- 🔍 Implement code review processes for all changes'); lines.push('- 📝 Use static analysis tools in your CI/CD pipeline'); lines.push('- 🚀 Follow secure coding guidelines for your technology stack'); } else { lines.push('## 🏆 Excellent Security Posture!'); lines.push(''); lines.push('Keep up the great work! Continue following security best practices:'); lines.push(''); lines.push('- 🔄 Run regular security scans'); lines.push('- 📚 Stay updated on security vulnerabilities'); lines.push('- đŸ› ī¸ Keep dependencies updated'); lines.push('- đŸ‘Ĩ Maintain security awareness in your team'); } lines.push(''); // Footer lines.push('---'); lines.push(''); lines.push(`**Generated by PuryAI v${report.metadata.version}** | ${new Date().toISOString()}`); lines.push(''); lines.push('> 🚀 Advanced AI-Powered Code Security Analysis'); return lines.join('\n'); } groupFindingsByFile(findings) { const grouped = new Map(); for (const finding of findings) { if (!grouped.has(finding.file)) { grouped.set(finding.file, []); } grouped.get(finding.file).push(finding); } return grouped; } groupFindingsByType(findings) { const grouped = new Map(); for (const finding of findings) { const key = finding.title; if (!grouped.has(key)) { grouped.set(key, []); } grouped.get(key).push(finding); } return grouped; } getRelativePath(filePath, basePath) { if (filePath.startsWith(basePath)) { const relativePath = filePath.substring(basePath.length); return relativePath.startsWith('/') ? relativePath.substring(1) : relativePath; } return filePath; } groupFindingsBySeverity(findings) { const grouped = { [Severity.CRITICAL]: [], [Severity.HIGH]: [], [Severity.MEDIUM]: [], [Severity.LOW]: [] }; for (const finding of findings) { grouped[finding.severity].push(finding); } return grouped; } getSeverityIcon(severity) { switch (severity) { case Severity.CRITICAL: return '🚨'; case Severity.HIGH: return 'âš ī¸'; case Severity.MEDIUM: return '📋'; case Severity.LOW: return 'â„šī¸'; default: return '📝'; } } getSeverityBadge(severity) { switch (severity) { case Severity.CRITICAL: return '![Critical](https://img.shields.io/badge/Critical-red?style=flat-square)'; case Severity.HIGH: return '![High](https://img.shields.io/badge/High-orange?style=flat-square)'; case Severity.MEDIUM: return '![Medium](https://img.shields.io/badge/Medium-yellow?style=flat-square)'; case Severity.LOW: return '![Low](https://img.shields.io/badge/Low-blue?style=flat-square)'; default: return '![Info](https://img.shields.io/badge/Info-lightgrey?style=flat-square)'; } } calculateOverallRiskLevel(severityCount) { const critical = severityCount.critical || 0; const high = severityCount.high || 0; const medium = severityCount.medium || 0; if (critical > 0) return '🚨 **CRITICAL RISK**'; if (high > 5) return 'âš ī¸ **HIGH RISK**'; if (high > 0 || medium > 10) return '📋 **MEDIUM RISK**'; if (medium > 0) return 'â„šī¸ **LOW RISK**'; return '✅ **MINIMAL RISK**'; } calculateRiskScore(severityCount, filesScanned) { const critical = severityCount.critical || 0; const high = severityCount.high || 0; const medium = severityCount.medium || 0; const low = severityCount.low || 0; // Risk scoring algorithm: weighted severity * frequency / file count const rawScore = critical * 10 + high * 7 + medium * 4 + low * 1; const normalizedScore = Math.min(100, Math.round((rawScore / Math.max(1, filesScanned)) * 2)); return normalizedScore; } calculateFileRiskScore(findings) { let score = 0; for (const finding of findings) { switch (finding.severity) { case Severity.CRITICAL: score += 25; break; case Severity.HIGH: score += 15; break; case Severity.MEDIUM: score += 8; break; case Severity.LOW: score += 3; break; } } return Math.min(100, score); } calculateConfidenceLevel(findings) { // Simple confidence calculation based on pattern consistency const hasEvidence = findings.filter(f => f.evidence).length; const totalFindings = findings.length; return Math.round((hasEvidence / totalFindings) * 100); } } //# sourceMappingURL=markdown.js.map