UNPKG

@iota-big3/sdk-security

Version:

Advanced security features including zero trust, quantum-safe crypto, and ML threat detection

820 lines (792 loc) 33.3 kB
"use strict"; /** * Penetration Testing Manager * Central orchestrator for security testing operations */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PenTestManager = void 0; const tslib_1 = require("tslib"); const crypto = tslib_1.__importStar(require("crypto")); const events_1 = require("events"); const exploit_engine_1 = require("./exploit-engine"); const network_scanner_1 = require("./scanners/network-scanner"); const web_scanner_1 = require("./scanners/web-scanner"); const types_1 = require("./types"); class PenTestManager extends events_1.EventEmitter { constructor(config = {}) { super(); this.sessions = new Map(); this.activeSessions = new Set(); this.config = { maxConcurrentTests: config.maxConcurrentTests || 5, autoExploit: config.autoExploit ?? false, safeMode: config.safeMode ?? true, reportPath: config.reportPath || './pentest-reports' }; // Initialize scanners and exploit engine this.networkScanner = new network_scanner_1.NetworkScanner(); this.webScanner = new web_scanner_1.WebScanner(); this.exploitEngine = new exploit_engine_1.ExploitEngine(); this.setupEventHandlers(); } /** * Create a new penetration test session */ async createSession(config) { // Validate authorization if (!config.authorization.authorized) { throw new Error('Penetration test must be authorized'); } const sessionId = crypto.randomUUID(); const session = { id: sessionId, projectName: `PenTest-${new Date().toISOString().split('T')[0]}`, startTime: new Date(), status: types_1.TestStatus.PLANNING, config, testers: [], vulnerabilities: [], statistics: this.initializeStatistics(), timeline: [], reports: [] }; // Add initial timeline event this.addTimelineEvent(session, { type: types_1.EventType.TEST_STARTED, description: 'Penetration test session created', tester: 'System' }); this.sessions.set(sessionId, session); this.emit('session:created', { sessionId, config }); return session; } /** * Get session by ID */ async getSession(id) { const session = this.sessions.get(id); if (!session) { throw new Error(`Session ${id} not found`); } return session; } /** * Update session */ async updateSession(id, updates) { const session = await this.getSession(id); Object.assign(session, updates); this.emit('session:updated', { sessionId: id, updates }); } /** * Start penetration test */ async startTest(sessionId) { const session = await this.getSession(sessionId); if (session.status !== types_1.TestStatus.PLANNING) { throw new Error(`Cannot start test in ${session.status} status`); } // Check concurrent test limit if (this.activeSessions.size >= this.config.maxConcurrentTests) { throw new Error('Maximum concurrent tests reached'); } session.status = types_1.TestStatus.IN_PROGRESS; this.activeSessions.add(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.TEST_STARTED, description: 'Penetration test started', tester: 'System' }); this.emit('test:started', { sessionId }); // Start automated testing based on config this.runAutomatedTests(session); } /** * Pause test */ async pauseTest(sessionId) { const session = await this.getSession(sessionId); if (session.status !== types_1.TestStatus.IN_PROGRESS) { throw new Error('Can only pause in-progress tests'); } session.status = types_1.TestStatus.PAUSED; this.activeSessions.delete(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.OTHER, description: 'Test paused', tester: 'System' }); this.emit('test:paused', { sessionId }); } /** * Resume test */ async resumeTest(sessionId) { const session = await this.getSession(sessionId); if (session.status !== types_1.TestStatus.PAUSED) { throw new Error('Can only resume paused tests'); } session.status = types_1.TestStatus.IN_PROGRESS; this.activeSessions.add(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.OTHER, description: 'Test resumed', tester: 'System' }); this.emit('test:resumed', { sessionId }); } /** * Stop test */ async stopTest(sessionId) { const session = await this.getSession(sessionId); session.status = types_1.TestStatus.COMPLETED; session.endTime = new Date(); this.activeSessions.delete(sessionId); // Calculate final statistics this.updateStatistics(session); this.addTimelineEvent(session, { type: types_1.EventType.TEST_COMPLETED, description: 'Penetration test completed', tester: 'System' }); this.emit('test:completed', { sessionId }); // Auto-generate report if configured if (session.config.reporting.executiveSummary) { await this.generateReport(sessionId, session.config.reporting); } } /** * Scan specific target */ async scanTarget(sessionId, target) { const session = await this.getSession(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.SCAN_STARTED, description: `Scanning target: ${target.address}`, tester: 'NetworkScanner', target: target.address }); const result = await this.networkScanner.scanTarget(target); // Add vulnerabilities to session session.vulnerabilities.push(...result.vulnerabilities); session.statistics.targetsScanned++; session.statistics.vulnerabilitiesFound += result.vulnerabilities.length; this.addTimelineEvent(session, { type: types_1.EventType.SCAN_COMPLETED, description: `Scan completed: ${result.vulnerabilities.length} vulnerabilities found`, tester: 'NetworkScanner', target: target.address }); // Auto-exploit if configured if (this.config.autoExploit) { for (const vuln of result.vulnerabilities) { if (this.exploitEngine.isSafeToExploit(vuln)) { await this.exploitVulnerability(vuln.id); } } } return result; } /** * Scan network range */ async scanNetwork(sessionId, range) { const session = await this.getSession(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.SCAN_STARTED, description: `Network scan started: ${range}`, tester: 'NetworkScanner' }); const result = await this.networkScanner.scanNetwork(range); // Update session session.vulnerabilities.push(...result.vulnerabilities); session.statistics.targetsScanned += result.discoveredHosts.length; session.statistics.vulnerabilitiesFound += result.vulnerabilities.length; this.addTimelineEvent(session, { type: types_1.EventType.SCAN_COMPLETED, description: `Network scan completed: ${result.discoveredHosts.length} hosts, ${result.vulnerabilities.length} vulnerabilities`, tester: 'NetworkScanner' }); return result; } /** * Scan web application */ async scanWebApp(sessionId, url) { const session = await this.getSession(sessionId); this.addTimelineEvent(session, { type: types_1.EventType.SCAN_STARTED, description: `Web application scan started: ${url}`, tester: 'WebScanner' }); const result = await this.webScanner.scanWebApp(url); // Update session session.vulnerabilities.push(...result.vulnerabilities); session.statistics.vulnerabilitiesFound += result.vulnerabilities.length; // Update vulnerability categories result.vulnerabilities.forEach(vuln => { session.statistics.vulnerabilitiesByCategory[vuln.category] = (session.statistics.vulnerabilitiesByCategory[vuln.category] || 0) + 1; }); this.addTimelineEvent(session, { type: types_1.EventType.SCAN_COMPLETED, description: `Web scan completed: ${result.vulnerabilities.length} vulnerabilities found`, tester: 'WebScanner' }); return result; } /** * Report vulnerability */ async reportVulnerability(sessionId, vuln) { const session = await this.getSession(sessionId); // Check if already reported if (!session.vulnerabilities.find(v => v.id === vuln.id)) { session.vulnerabilities.push(vuln); session.statistics.vulnerabilitiesFound++; // Update severity counts if (vuln.severity === 'CRITICAL') session.statistics.criticalVulnerabilities++; if (vuln.severity === 'HIGH') session.statistics.highVulnerabilities++; this.addTimelineEvent(session, { type: types_1.EventType.VULNERABILITY_FOUND, description: vuln.title, tester: vuln.discoveredBy, severity: vuln.severity }); this.emit('vulnerability:found', { sessionId, vulnerability: vuln }); } } /** * Verify vulnerability */ async verifyVulnerability(vulnId) { // Find vulnerability across all sessions let vulnerability; let session; for (const [id, s] of this.sessions) { const v = s.vulnerabilities.find(vuln => vuln.id === vulnId); if (v) { vulnerability = v; session = s; break; } } if (!vulnerability || !session) { throw new Error(`Vulnerability ${vulnId} not found`); } // Mock verification - in production would re-test const verified = Math.random() > 0.2; // 80% verification rate this.addTimelineEvent(session, { type: types_1.EventType.FINDING_VERIFIED, description: `Vulnerability ${verified ? 'verified' : 'not reproducible'}: ${vulnerability.title}`, tester: 'System' }); return verified; } /** * Exploit vulnerability */ async exploitVulnerability(vulnId) { // Find vulnerability let vulnerability; let session; for (const [id, s] of this.sessions) { const v = s.vulnerabilities.find(vuln => vuln.id === vulnId); if (v) { vulnerability = v; session = s; break; } } if (!vulnerability || !session) { throw new Error(`Vulnerability ${vulnId} not found`); } // Check safe mode if (this.config.safeMode && !this.exploitEngine.isSafeToExploit(vulnerability)) { throw new Error('Exploitation blocked by safe mode'); } this.addTimelineEvent(session, { type: types_1.EventType.EXPLOIT_ATTEMPTED, description: `Attempting to exploit: ${vulnerability.title}`, tester: 'ExploitEngine' }); const result = await this.exploitEngine.exploitVulnerability(vulnerability); if (result.success) { session.statistics.exploitsSuccessful++; this.addTimelineEvent(session, { type: types_1.EventType.EXPLOIT_SUCCESSFUL, description: `Successfully exploited: ${vulnerability.title}`, tester: 'ExploitEngine' }); } else { this.addTimelineEvent(session, { type: types_1.EventType.EXPLOIT_FAILED, description: `Failed to exploit: ${vulnerability.title}`, tester: 'ExploitEngine' }); } return result; } /** * Generate report */ async generateReport(sessionId, config) { const session = await this.getSession(sessionId); const report = { id: crypto.randomUUID(), title: `Penetration Test Report - ${session.projectName}`, type: config.detail, generatedAt: new Date(), generatedBy: 'PenTestManager', format: config.format[0] || types_1.ReportFormat.PDF, findings: this.prepareFindings(session, config), recommendations: this.generateRecommendations(session), conclusion: this.generateConclusion(session) }; // Add sections based on config if (config.executiveSummary) { report.executiveSummary = this.generateExecutiveSummary(session); } report.methodology = this.generateMethodology(session); report.scope = this.generateScope(session); if (config.technicalAppendix) { report.appendices = this.generateAppendices(session); } session.reports.push(report); this.emit('report:generated', { sessionId, reportId: report.id }); return report; } /** * Export report */ async exportReport(reportId, format) { // Find report let report; for (const [, session] of this.sessions) { const r = session.reports.find(rep => rep.id === reportId); if (r) { report = r; break; } } if (!report) { throw new Error(`Report ${reportId} not found`); } switch (format) { case types_1.ReportFormat.JSON: return Buffer.from(JSON.stringify(report, null, 2)); case types_1.ReportFormat.HTML: return this.exportToHTML(report); case types_1.ReportFormat.MARKDOWN: return this.exportToMarkdown(report); case types_1.ReportFormat.PDF: case types_1.ReportFormat.XML: default: // In production, would use proper libraries return this.exportToHTML(report); } } /** * Private helper methods */ setupEventHandlers() { // Forward scanner events this.networkScanner.on('scan:completed', (data) => { this.emit('scan:completed', data); }); this.webScanner.on('vulnerability:found', (data) => { this.emit('vulnerability:found', data); }); this.exploitEngine.on('exploit:successful', (data) => { this.emit('exploit:successful', data); }); } initializeStatistics() { return { totalTargets: 0, targetsScanned: 0, vulnerabilitiesFound: 0, criticalVulnerabilities: 0, highVulnerabilities: 0, exploitsSuccessful: 0, testDuration: 0, vulnerabilitiesByCategory: {}, coveragePercentage: 0, testTypesCompleted: [] }; } addTimelineEvent(session, event) { session.timeline.push({ ...event, timestamp: new Date() }); } async runAutomatedTests(session) { // Run tests based on configuration for (const testType of session.config.testTypes) { if (session.status !== types_1.TestStatus.IN_PROGRESS) break; try { switch (testType) { case 'NETWORK': await this.runNetworkTests(session); break; case 'WEB_APPLICATION': await this.runWebTests(session); break; case 'API': await this.runAPITests(session); break; default: this.emit('test:skipped', { sessionId: session.id, testType, reason: 'Not implemented' }); } session.statistics.testTypesCompleted.push(testType); } catch (error) { this.emit('test:error', { sessionId: session.id, testType, error }); } } // Auto-complete if all tests done if (session.status === types_1.TestStatus.IN_PROGRESS) { await this.stopTest(session.id); } } async runNetworkTests(session) { const { targets, ipRanges } = session.config.scope; // Scan individual targets for (const target of targets) { if (target.type === 'HOST' || target.type === 'NETWORK') { await this.scanTarget(session.id, target); } } // Scan IP ranges if (ipRanges) { for (const range of ipRanges) { await this.scanNetwork(session.id, range); } } } async runWebTests(session) { const { applications, domains } = session.config.scope; // Scan applications if (applications) { for (const app of applications) { await this.scanWebApp(session.id, app.url); } } // Scan domains if (domains) { for (const domain of domains) { await this.scanWebApp(session.id, `https://${domain}`); } } } async runAPITests(session) { // API testing would be implemented here this.emit('test:info', { sessionId: session.id, message: 'API testing not yet implemented' }); } updateStatistics(session) { const duration = session.endTime ? (session.endTime.getTime() - session.startTime.getTime()) / (1000 * 60 * 60) : 0; session.statistics.testDuration = duration; // Calculate coverage const scanned = session.statistics.targetsScanned; const total = session.statistics.totalTargets || session.config.scope.targets.length; session.statistics.coveragePercentage = total > 0 ? (scanned / total) * 100 : 0; // Count by severity session.statistics.criticalVulnerabilities = session.vulnerabilities .filter(v => v.severity === 'CRITICAL').length; session.statistics.highVulnerabilities = session.vulnerabilities .filter(v => v.severity === 'HIGH').length; } prepareFindings(session, config) { return session.vulnerabilities .sort((a, b) => { const severityOrder = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, INFO: 4 }; return severityOrder[a.severity] - severityOrder[b.severity]; }) .map(vuln => ({ vulnerability: vuln, risk: this.calculateRisk(vuln), exploited: vuln.exploitStatus === 'SUCCESSFUL', businessContext: this.getBusinessContext(vuln), remediationTimeline: this.getRemediationTimeline(vuln) })); } calculateRisk(vuln) { const score = vuln.riskScore || 5; const level = score >= 8 ? 'CRITICAL' : score >= 6 ? 'HIGH' : score >= 4 ? 'MEDIUM' : 'LOW'; return { score, level, justification: `Based on ${vuln.severity} severity, ${vuln.exploitComplexity} complexity, and ${vuln.impact.confidentiality} confidentiality impact` }; } getBusinessContext(vuln) { const contexts = { [types_1.VulnerabilityCategory.INJECTION]: 'Could lead to complete database compromise and data theft', [types_1.VulnerabilityCategory.BROKEN_AUTHENTICATION]: 'Allows unauthorized access to user accounts', [types_1.VulnerabilityCategory.SENSITIVE_DATA_EXPOSURE]: 'Exposes customer data and violates privacy regulations', [types_1.VulnerabilityCategory.XXE]: 'Allows reading of system files and internal network access', [types_1.VulnerabilityCategory.BROKEN_ACCESS_CONTROL]: 'Users can access unauthorized resources', [types_1.VulnerabilityCategory.SECURITY_MISCONFIGURATION]: 'Weakens overall security posture', [types_1.VulnerabilityCategory.XSS]: 'Enables theft of user sessions and credentials', [types_1.VulnerabilityCategory.INSECURE_DESERIALIZATION]: 'Can lead to remote code execution', [types_1.VulnerabilityCategory.USING_VULNERABLE_COMPONENTS]: 'Inherits vulnerabilities from third-party code', [types_1.VulnerabilityCategory.INSUFFICIENT_LOGGING]: 'Prevents detection and response to attacks', [types_1.VulnerabilityCategory.SSRF]: 'Allows access to internal systems', [types_1.VulnerabilityCategory.CSRF]: 'Forces users to perform unwanted actions', [types_1.VulnerabilityCategory.BUFFER_OVERFLOW]: 'Can crash systems or execute arbitrary code', [types_1.VulnerabilityCategory.PRIVILEGE_ESCALATION]: 'Allows attackers to gain administrative access', [types_1.VulnerabilityCategory.INFORMATION_DISCLOSURE]: 'Reveals sensitive system information', [types_1.VulnerabilityCategory.DENIAL_OF_SERVICE]: 'Can make services unavailable to legitimate users', [types_1.VulnerabilityCategory.BUSINESS_LOGIC]: 'Allows manipulation of business processes', [types_1.VulnerabilityCategory.OTHER]: 'Security weakness requiring attention' }; return contexts[vuln.category] || 'Security vulnerability requiring remediation'; } getRemediationTimeline(vuln) { switch (vuln.severity) { case 'CRITICAL': return 'Immediate (within 24 hours)'; case 'HIGH': return 'Urgent (within 7 days)'; case 'MEDIUM': return 'Short-term (within 30 days)'; case 'LOW': return 'Scheduled (within 90 days)'; default: return 'As resources permit'; } } generateRecommendations(session) { const recommendations = [ 'Implement a vulnerability management program with regular scanning', 'Establish a security incident response team and procedures', 'Conduct security awareness training for all staff' ]; // Add specific recommendations based on findings const categories = new Set(session.vulnerabilities.map(v => v.category)); if (categories.has(types_1.VulnerabilityCategory.INJECTION)) { recommendations.push('Implement input validation and parameterized queries throughout the application'); } if (categories.has(types_1.VulnerabilityCategory.BROKEN_AUTHENTICATION)) { recommendations.push('Enforce strong password policies and implement multi-factor authentication'); } if (categories.has(types_1.VulnerabilityCategory.SENSITIVE_DATA_EXPOSURE)) { recommendations.push('Encrypt all sensitive data at rest and in transit'); } if (session.statistics.criticalVulnerabilities > 0) { recommendations.unshift('Address all critical vulnerabilities immediately before they are exploited'); } return recommendations; } generateConclusion(session) { const { vulnerabilitiesFound, criticalVulnerabilities, highVulnerabilities } = session.statistics; if (criticalVulnerabilities > 0) { return `The penetration test identified ${vulnerabilitiesFound} vulnerabilities, including ${criticalVulnerabilities} critical issues that pose an immediate risk to the organization. Immediate remediation is required to prevent potential compromise.`; } else if (highVulnerabilities > 0) { return `The assessment revealed ${vulnerabilitiesFound} vulnerabilities, with ${highVulnerabilities} high-severity issues that could be exploited by attackers. A remediation plan should be implemented promptly.`; } else if (vulnerabilitiesFound > 0) { return `The security testing discovered ${vulnerabilitiesFound} vulnerabilities of medium to low severity. While not immediately critical, these should be addressed as part of ongoing security improvements.`; } else { return 'The penetration test did not identify any significant vulnerabilities. Continue with regular security assessments and maintain current security practices.'; } } generateExecutiveSummary(session) { return ` ## Executive Summary This penetration test was conducted from ${session.startTime.toLocaleDateString()} to ${session.endTime?.toLocaleDateString() || 'ongoing'} to assess the security posture of the target environment. ### Key Findings: - Total vulnerabilities discovered: ${session.statistics.vulnerabilitiesFound} - Critical vulnerabilities: ${session.statistics.criticalVulnerabilities} - High severity vulnerabilities: ${session.statistics.highVulnerabilities} - Successful exploitations: ${session.statistics.exploitsSuccessful} ### Risk Assessment: The overall security risk is ${this.getOverallRisk(session.statistics)}. ### Immediate Actions Required: ${session.statistics.criticalVulnerabilities > 0 ? '1. Address critical vulnerabilities within 24 hours' : '1. Continue monitoring and regular assessments'} 2. Implement recommended security controls 3. Schedule follow-up assessment after remediation `.trim(); } generateMethodology(session) { return ` ## Methodology This penetration test followed the ${session.config.methodology} methodology with the following approach: 1. **Information Gathering**: Passive and active reconnaissance 2. **Vulnerability Scanning**: Automated and manual vulnerability identification 3. **Exploitation**: ${session.config.constraints?.exploitationAllowed ? 'Controlled exploitation of discovered vulnerabilities' : 'Exploitation simulation without actual compromise'} 4. **Post-Exploitation**: ${session.config.constraints?.dataExfiltrationAllowed ? 'Limited data access verification' : 'No data access attempted'} 5. **Reporting**: Comprehensive documentation of all findings Test Types Performed: ${session.config.testTypes.join(', ')} `.trim(); } generateScope(session) { const { targets, ipRanges, domains, applications } = session.config.scope; return ` ## Scope ### In-Scope Assets: - Target Systems: ${targets.length} - IP Ranges: ${ipRanges?.join(', ') || 'None'} - Domains: ${domains?.join(', ') || 'None'} - Applications: ${applications?.map(a => a.name).join(', ') || 'None'} ### Exclusions: ${session.config.scope.exclusions?.join('\n- ') || 'None'} ### Constraints: - Exploitation: ${session.config.constraints?.exploitationAllowed ? 'Allowed' : 'Not Allowed'} - DoS Testing: ${session.config.constraints?.dosAllowed ? 'Allowed' : 'Not Allowed'} - Brute Force: ${session.config.constraints?.bruteForceAllowed ? 'Allowed' : 'Not Allowed'} `.trim(); } generateAppendices(session) { return [ { title: 'Testing Tools', content: 'IOTA Security Scanner, Network Scanner, Web Application Scanner, Exploit Engine', type: 'TOOLS' }, { title: 'OWASP Top 10 Coverage', content: this.generateOWASPCoverage(session), type: 'METHODOLOGY' }, { title: 'Detailed Timeline', content: this.generateDetailedTimeline(session), type: 'TECHNICAL' } ]; } generateOWASPCoverage(session) { const owaspCategories = [ types_1.VulnerabilityCategory.INJECTION, types_1.VulnerabilityCategory.BROKEN_AUTHENTICATION, types_1.VulnerabilityCategory.SENSITIVE_DATA_EXPOSURE, types_1.VulnerabilityCategory.XXE, types_1.VulnerabilityCategory.BROKEN_ACCESS_CONTROL, types_1.VulnerabilityCategory.SECURITY_MISCONFIGURATION, types_1.VulnerabilityCategory.XSS, types_1.VulnerabilityCategory.INSECURE_DESERIALIZATION, types_1.VulnerabilityCategory.USING_VULNERABLE_COMPONENTS, types_1.VulnerabilityCategory.INSUFFICIENT_LOGGING ]; const coverage = owaspCategories.map(cat => { const found = session.vulnerabilities.filter(v => v.category === cat).length; return `- ${cat}: ${found > 0 ? `✓ (${found} issues)` : '✗'}`; }); return coverage.join('\n'); } generateDetailedTimeline(session) { return session.timeline .slice(-50) // Last 50 events .map(event => `${event.timestamp.toISOString()} - ${event.type}: ${event.description}`) .join('\n'); } getOverallRisk(stats) { if (stats.criticalVulnerabilities > 0) return 'CRITICAL'; if (stats.highVulnerabilities > 2) return 'HIGH'; if (stats.vulnerabilitiesFound > 10) return 'MEDIUM'; return 'LOW'; } exportToHTML(report) { const html = ` <!DOCTYPE html> <html> <head> <title>${report.title}</title> <style> body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; } h1, h2, h3 { color: #333; } .critical { color: #d32f2f; } .high { color: #f57c00; } .medium { color: #fbc02d; } .low { color: #388e3c; } .info { color: #1976d2; } table { border-collapse: collapse; width: 100%; margin: 20px 0; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .finding { margin-bottom: 30px; padding: 20px; border-left: 4px solid #ccc; } .finding.critical { border-color: #d32f2f; } .finding.high { border-color: #f57c00; } pre { background: #f5f5f5; padding: 10px; overflow-x: auto; } </style> </head> <body> <h1>${report.title}</h1> <p><strong>Generated:</strong> ${report.generatedAt.toLocaleString()}</p> ${report.executiveSummary ? `<section>${report.executiveSummary}</section>` : ''} <h2>Findings</h2> ${report.findings.map(f => ` <div class="finding ${f.vulnerability.severity.toLowerCase()}"> <h3>${f.vulnerability.title} <span class="${f.vulnerability.severity.toLowerCase()}">[${f.vulnerability.severity}]</span></h3> <p>${f.vulnerability.description}</p> <p><strong>Risk:</strong> ${f.risk.level} (Score: ${f.risk.score}/10)</p> <p><strong>Category:</strong> ${f.vulnerability.category}</p> <p><strong>Exploited:</strong> ${f.exploited ? 'Yes' : 'No'}</p> ${f.businessContext ? `<p><strong>Business Impact:</strong> ${f.businessContext}</p>` : ''} <p><strong>Remediation Timeline:</strong> ${f.remediationTimeline}</p> <h4>Remediation</h4> <p>${f.vulnerability.remediation.summary}</p> <ol>${f.vulnerability.remediation.steps.map(s => `<li>${s}</li>`).join('')}</ol> </div> `).join('')} <h2>Recommendations</h2> <ol> ${report.recommendations.map(r => `<li>${r}</li>`).join('')} </ol> <h2>Conclusion</h2> <p>${report.conclusion}</p> </body> </html> `.trim(); return Buffer.from(html); } exportToMarkdown(report) { const markdown = ` # ${report.title} **Generated:** ${report.generatedAt.toLocaleString()} ${report.executiveSummary || ''} ## Findings ${report.findings.map(f => ` ### ${f.vulnerability.title} [${f.vulnerability.severity}] ${f.vulnerability.description} - **Risk:** ${f.risk.level} (Score: ${f.risk.score}/10) - **Category:** ${f.vulnerability.category} - **Exploited:** ${f.exploited ? 'Yes' : 'No'} ${f.businessContext ? `- **Business Impact:** ${f.businessContext}` : ''} - **Remediation Timeline:** ${f.remediationTimeline} #### Remediation ${f.vulnerability.remediation.summary} ${f.vulnerability.remediation.steps.map((s, i) => `${i + 1}. ${s}`).join('\n')} --- `).join('\n')} ## Recommendations ${report.recommendations.map((r, i) => `${i + 1}. ${r}`).join('\n')} ## Conclusion ${report.conclusion} `.trim(); return Buffer.from(markdown); } } exports.PenTestManager = PenTestManager; //# sourceMappingURL=pentest-manager.js.map