coverme-scanner 1.3.3 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,9 +6,24 @@ Execute this 22-agent security scan with cross-validation.
6
6
 
7
7
  ---
8
8
 
9
- ## PHASE 0: PROJECT DISCOVERY & RUNTIME CHECK
9
+ ## PHASE 0: PROJECT DISCOVERY & STATISTICS
10
10
 
11
- Before scanning, understand what you're scanning:
11
+ Before scanning, understand what you're scanning and gather statistics:
12
+
13
+ ### Step 1: Gather Project Statistics
14
+
15
+ ```bash
16
+ # Count files and lines of code
17
+ find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.py" -o -name "*.go" -o -name "*.java" -o -name "*.rb" -o -name "*.php" -o -name "*.cs" -o -name "*.swift" -o -name "*.kt" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/build/*" -not -path "*/__pycache__/*" | wc -l
18
+
19
+ # Count lines of code (approximate)
20
+ find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.py" -o -name "*.go" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" 2>/dev/null | head -100 | xargs wc -l 2>/dev/null | tail -1
21
+
22
+ # Generate project tree (max 3 levels deep, exclude node_modules etc)
23
+ find . -maxdepth 3 -type d -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/__pycache__/*" | head -30 | sort
24
+ ```
25
+
26
+ ### Step 2: Read Project Info
12
27
 
13
28
  ```bash
14
29
  cat package.json 2>/dev/null | head -30
@@ -17,10 +32,15 @@ ls -la
17
32
  ls src/ 2>/dev/null || ls app/ 2>/dev/null || ls lib/ 2>/dev/null
18
33
  ```
19
34
 
20
- Create a **Project Overview** to include in the report:
35
+ ### Step 3: Create Project Overview
36
+
37
+ Include these statistics in the final report:
21
38
 
22
39
  ```json
23
40
  {
41
+ "filesScanned": 45,
42
+ "linesOfCode": 4850,
43
+ "projectTree": "project-name/\n├── src/\n│ ├── api/\n│ ├── services/\n│ └── utils/\n├── tests/\n└── package.json",
24
44
  "projectOverview": {
25
45
  "name": "project-name",
26
46
  "type": "Backend API | Frontend SPA | Full-stack | CLI | Library | Microservice",
@@ -32,6 +52,11 @@ Create a **Project Overview** to include in the report:
32
52
  }
33
53
  ```
34
54
 
55
+ **IMPORTANT**:
56
+ - `filesScanned` - Count of source code files analyzed (not node_modules/dist)
57
+ - `linesOfCode` - Total lines in source files (approximate is fine)
58
+ - `projectTree` - ASCII tree representation of main directories (use tree format with ├── and └──)
59
+
35
60
  This context helps readers understand the security findings in context.
36
61
 
37
62
  ### Step 3: Check for Runtime Verification (SSH)
@@ -1594,6 +1619,9 @@ The final report should ONLY contain findings that are:
1594
1619
  {
1595
1620
  "projectName": "project-name",
1596
1621
  "scanDate": "{{SCAN_DATE}}",
1622
+ "filesScanned": 45,
1623
+ "linesOfCode": 4850,
1624
+ "projectTree": "project-name/\n├── src/\n│ ├── api/\n│ ├── services/\n│ └── utils/\n├── tests/\n└── package.json",
1597
1625
 
1598
1626
  "projectOverview": {
1599
1627
  "name": "project-name",
@@ -1630,6 +1658,187 @@ The final report should ONLY contain findings that are:
1630
1658
  }
1631
1659
  },
1632
1660
 
1661
+ "architectureOverview": {
1662
+ "components": [
1663
+ {
1664
+ "name": "API Server",
1665
+ "type": "service",
1666
+ "description": "Express.js REST API handling all client requests",
1667
+ "trustLevel": "semi-trusted"
1668
+ },
1669
+ {
1670
+ "name": "PostgreSQL",
1671
+ "type": "database",
1672
+ "description": "Primary data store for user and application data",
1673
+ "trustLevel": "trusted"
1674
+ },
1675
+ {
1676
+ "name": "Redis",
1677
+ "type": "cache",
1678
+ "description": "Session storage and rate limiting",
1679
+ "trustLevel": "trusted"
1680
+ },
1681
+ {
1682
+ "name": "External Payment API",
1683
+ "type": "external",
1684
+ "description": "Third-party payment processor",
1685
+ "trustLevel": "untrusted"
1686
+ }
1687
+ ],
1688
+ "trustBoundaries": [
1689
+ {
1690
+ "name": "Client to API",
1691
+ "from": "Browser/Mobile",
1692
+ "to": "API Server",
1693
+ "protocol": "HTTPS"
1694
+ },
1695
+ {
1696
+ "name": "API to Database",
1697
+ "from": "API Server",
1698
+ "to": "PostgreSQL",
1699
+ "protocol": "TLS"
1700
+ }
1701
+ ],
1702
+ "criticalAssets": [
1703
+ {
1704
+ "name": "User Credentials",
1705
+ "type": "credential",
1706
+ "location": "PostgreSQL users table",
1707
+ "protection": "bcrypt hashed"
1708
+ },
1709
+ {
1710
+ "name": "API Keys",
1711
+ "type": "key",
1712
+ "location": "Environment variables",
1713
+ "protection": "Encrypted at rest"
1714
+ },
1715
+ {
1716
+ "name": "Session Tokens",
1717
+ "type": "token",
1718
+ "location": "Redis",
1719
+ "protection": "HMAC signed"
1720
+ }
1721
+ ],
1722
+ "dataFlows": [
1723
+ "User Authentication Flow",
1724
+ "Payment Processing Flow",
1725
+ "Data Export Flow"
1726
+ ]
1727
+ },
1728
+
1729
+ "threatModel": [
1730
+ {
1731
+ "id": "T-001",
1732
+ "threat": "SQL Injection via user input",
1733
+ "category": "STRIDE",
1734
+ "strideType": "T",
1735
+ "status": "open",
1736
+ "relatedFindings": ["SEC-001", "DB-002"],
1737
+ "mitigation": "Use parameterized queries",
1738
+ "dreadScore": 8.5
1739
+ },
1740
+ {
1741
+ "id": "T-002",
1742
+ "threat": "Session hijacking via XSS",
1743
+ "category": "STRIDE",
1744
+ "strideType": "S",
1745
+ "status": "partial",
1746
+ "relatedFindings": ["SEC-003"],
1747
+ "mitigation": "CSP headers implemented but not comprehensive",
1748
+ "dreadScore": 7.2
1749
+ },
1750
+ {
1751
+ "id": "T-003",
1752
+ "threat": "Unauthorized data access",
1753
+ "category": "LINDDUN",
1754
+ "status": "mitigated",
1755
+ "relatedFindings": [],
1756
+ "mitigation": "Row-level security implemented",
1757
+ "dreadScore": 3.0
1758
+ }
1759
+ ],
1760
+
1761
+ "qualityReview": {
1762
+ "deleteItems": [
1763
+ {
1764
+ "type": "delete",
1765
+ "file": "src/utils/oldHelpers.ts",
1766
+ "lines": 250,
1767
+ "description": "Entire file is dead code - functions never called",
1768
+ "reason": "No imports found in codebase"
1769
+ },
1770
+ {
1771
+ "type": "delete",
1772
+ "file": "src/legacy/auth.js",
1773
+ "lines": 180,
1774
+ "description": "Legacy auth implementation replaced by Clerk",
1775
+ "reason": "Migration completed 6 months ago"
1776
+ }
1777
+ ],
1778
+ "mergeItems": [
1779
+ {
1780
+ "type": "merge",
1781
+ "file": "src/utils/validate.ts, src/helpers/validation.ts",
1782
+ "description": "Two files with overlapping validation functions",
1783
+ "reason": "DRY violation - consolidate into single module"
1784
+ }
1785
+ ],
1786
+ "simplifyItems": [
1787
+ {
1788
+ "type": "simplify",
1789
+ "file": "src/services/payment.ts",
1790
+ "lines": 450,
1791
+ "description": "Overly complex payment flow with excessive error handling",
1792
+ "reason": "Can be reduced to ~200 lines with proper abstraction"
1793
+ }
1794
+ ],
1795
+ "totalLinesRemovable": 680,
1796
+ "percentageOfCodebase": 4.2
1797
+ },
1798
+
1799
+ "actionItems": [
1800
+ {
1801
+ "id": "A-001",
1802
+ "title": "Fix SQL injection in user search",
1803
+ "priority": "immediate",
1804
+ "relatedFindings": ["SEC-001"],
1805
+ "effort": "low",
1806
+ "description": "Replace string concatenation with parameterized query"
1807
+ },
1808
+ {
1809
+ "id": "A-002",
1810
+ "title": "Implement rate limiting on auth endpoints",
1811
+ "priority": "immediate",
1812
+ "relatedFindings": ["AUTH-003"],
1813
+ "effort": "medium",
1814
+ "description": "Add Redis-based rate limiter to /login and /register"
1815
+ },
1816
+ {
1817
+ "id": "A-003",
1818
+ "title": "Add CSP headers",
1819
+ "priority": "high",
1820
+ "relatedFindings": ["SEC-005"],
1821
+ "effort": "low",
1822
+ "description": "Configure helmet with strict CSP policy"
1823
+ },
1824
+ {
1825
+ "id": "A-004",
1826
+ "title": "Clean up dead code",
1827
+ "priority": "medium",
1828
+ "relatedFindings": ["DEAD-001", "DEAD-002"],
1829
+ "effort": "medium",
1830
+ "description": "Remove 680 lines of unused code identified in quality review"
1831
+ },
1832
+ {
1833
+ "id": "A-005",
1834
+ "title": "Implement audit logging",
1835
+ "priority": "long-term",
1836
+ "relatedFindings": ["DATA-002"],
1837
+ "effort": "high",
1838
+ "description": "Add comprehensive audit trail for sensitive operations"
1839
+ }
1840
+ ],
1841
+
1633
1842
  "summary": {
1634
1843
  "total": 10,
1635
1844
  "critical": 1,
@@ -1638,17 +1847,42 @@ The final report should ONLY contain findings that are:
1638
1847
  "low": 2,
1639
1848
  "info": 0,
1640
1849
  "mitigatedCount": 5,
1641
- "falsePositiveCount": 3
1850
+ "falsePositiveCount": 3,
1851
+ "avgConfidence": 0.85
1642
1852
  },
1643
1853
 
1644
1854
  "findings": [
1645
1855
  {
1646
1856
  "id": "SEC-001",
1647
- "title": "Example finding",
1648
- "severity": "high",
1857
+ "title": "SQL Injection in User Search",
1858
+ "severity": "critical",
1859
+ "category": "security",
1860
+ "file": "src/routes/users.ts",
1861
+ "line": 45,
1862
+ "code": "db.query(`SELECT * FROM users WHERE name LIKE '%${searchTerm}%'`)",
1863
+ "description": "User search parameter is directly concatenated into SQL query without sanitization",
1864
+ "impact": "Attacker can extract entire database contents, modify data, or execute system commands",
1865
+ "attackChain": [
1866
+ {"step": 1, "action": "Send malicious search term: ' OR '1'='1' --", "result": "Query returns all users"},
1867
+ {"step": 2, "action": "Use UNION SELECT to extract data from other tables", "result": "Database schema exposed"},
1868
+ {"step": 3, "action": "Extract password hashes and sensitive data", "result": "Full data breach"}
1869
+ ],
1870
+ "recommendation": "Use parameterized queries: db.query('SELECT * FROM users WHERE name LIKE $1', [`%${searchTerm}%`])",
1871
+ "cwe": "CWE-89",
1872
+ "owasp": "A03:2021",
1873
+ "dreadScore": {
1874
+ "damage": 10,
1875
+ "reproducibility": 10,
1876
+ "exploitability": 9,
1877
+ "affectedUsers": 10,
1878
+ "discoverability": 8,
1879
+ "total": 9.4
1880
+ },
1881
+ "status": "open",
1882
+ "crossReferences": ["T-001"],
1883
+ "confidence": 95,
1649
1884
  "fixOwner": "developer",
1650
- "fixType": "code",
1651
- "...": "other fields"
1885
+ "fixType": "code"
1652
1886
  }
1653
1887
  ],
1654
1888
 
@@ -1682,8 +1916,22 @@ The final report should ONLY contain findings that are:
1682
1916
  ],
1683
1917
 
1684
1918
  "positiveObservations": [
1685
- "Good pattern 1",
1686
- "Good pattern 2"
1919
+ {
1920
+ "title": "Strong Authentication Implementation",
1921
+ "description": "Clerk integration with proper session management, MFA support, and secure cookie settings"
1922
+ },
1923
+ {
1924
+ "title": "Comprehensive Input Validation",
1925
+ "description": "Zod schemas used consistently across API endpoints with proper error handling"
1926
+ },
1927
+ {
1928
+ "title": "Secure Database Access",
1929
+ "description": "Prisma ORM with parameterized queries, preventing SQL injection in core modules"
1930
+ },
1931
+ {
1932
+ "title": "Good Error Handling Patterns",
1933
+ "description": "Errors are caught and logged without exposing internal details to clients"
1934
+ }
1687
1935
  ],
1688
1936
 
1689
1937
  "validationSummary": {
@@ -56,6 +56,30 @@ interface ExecutiveSummaryData {
56
56
  architect?: number;
57
57
  };
58
58
  }
59
+ interface ScanStats {
60
+ filesScanned: number;
61
+ linesOfCode: number;
62
+ agentCount: number;
63
+ avgConfidence: number;
64
+ }
65
+ interface QualityReviewData {
66
+ deleteItems: Array<{
67
+ file: string;
68
+ lines: number;
69
+ description: string;
70
+ }>;
71
+ mergeItems: Array<{
72
+ file: string;
73
+ description: string;
74
+ }>;
75
+ simplifyItems: Array<{
76
+ file: string;
77
+ description: string;
78
+ }>;
79
+ totalLinesRemovable: number;
80
+ percentageOfCodebase: number;
81
+ totalItems: number;
82
+ }
59
83
  interface ReportData {
60
84
  projectName: string;
61
85
  scanDate: string;
@@ -97,6 +121,9 @@ interface ReportData {
97
121
  architectureOverviewHtml: string;
98
122
  threatModelHtml: string;
99
123
  actionItemsHtml: string;
124
+ scanStats?: ScanStats;
125
+ projectTree?: string;
126
+ qualityReview?: QualityReviewData;
100
127
  }
101
128
  export declare function calculateScore(result: ScanResult): {
102
129
  grade: string;
@@ -116,5 +143,11 @@ export declare function generateHtmlReport(result: ScanResult, outputPath: strin
116
143
  file?: string;
117
144
  rejectionReason: string;
118
145
  }>): Promise<void>;
146
+ export declare function generateProfessionalPdf(result: ScanResult, outputPath: string, falsePositives?: Array<{
147
+ id: string;
148
+ title: string;
149
+ file?: string;
150
+ rejectionReason: string;
151
+ }>): Promise<void>;
119
152
  export {};
120
153
  //# sourceMappingURL=generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,7 @@ exports.generateExecutiveSummary = generateExecutiveSummary;
41
41
  exports.renderTemplate = renderTemplate;
42
42
  exports.generatePdfReport = generatePdfReport;
43
43
  exports.generateHtmlReport = generateHtmlReport;
44
+ exports.generateProfessionalPdf = generateProfessionalPdf;
44
45
  const fs = __importStar(require("fs"));
45
46
  const path = __importStar(require("path"));
46
47
  const puppeteer_1 = __importDefault(require("puppeteer"));
@@ -616,6 +617,33 @@ async function generateHtmlReport(result, outputPath, falsePositives = []) {
616
617
  const typeGroups = createTypeGroups(result.findings);
617
618
  const codeGroup = typeGroups.find(g => g.type === 'code');
618
619
  const devopsGroup = typeGroups.find(g => g.type === 'devops');
620
+ // Prepare scan statistics
621
+ const scanStats = (result.filesScanned || result.linesOfCode) ? {
622
+ filesScanned: result.filesScanned || 0,
623
+ linesOfCode: result.linesOfCode || 0,
624
+ agentCount: result.agentsUsed?.length || 0,
625
+ avgConfidence: Math.round((result.summary?.avgConfidence || 0) * 100),
626
+ } : undefined;
627
+ // Prepare quality review data
628
+ const qr = result.qualityReview;
629
+ const qualityReview = qr ? {
630
+ deleteItems: qr.deleteItems?.map(i => ({
631
+ file: i.file,
632
+ lines: i.lines || 0,
633
+ description: i.description,
634
+ })) || [],
635
+ mergeItems: qr.mergeItems?.map(i => ({
636
+ file: i.file,
637
+ description: i.description,
638
+ })) || [],
639
+ simplifyItems: qr.simplifyItems?.map(i => ({
640
+ file: i.file,
641
+ description: i.description,
642
+ })) || [],
643
+ totalLinesRemovable: qr.totalLinesRemovable || 0,
644
+ percentageOfCodebase: qr.percentageOfCodebase || 0,
645
+ totalItems: (qr.deleteItems?.length || 0) + (qr.mergeItems?.length || 0) + (qr.simplifyItems?.length || 0),
646
+ } : undefined;
619
647
  const data = {
620
648
  projectName: result.projectName,
621
649
  scanDate: new Date(result.scanDate).toLocaleDateString('en-US', {
@@ -654,9 +682,248 @@ async function generateHtmlReport(result, outputPath, falsePositives = []) {
654
682
  architectureOverviewHtml: generateArchitectureOverviewHtml(result),
655
683
  threatModelHtml: generateThreatModelHtml(result),
656
684
  actionItemsHtml: generateActionItemsHtml(result),
685
+ // New scan statistics and quality review
686
+ scanStats,
687
+ projectTree: result.projectTree,
688
+ qualityReview,
657
689
  };
658
690
  const renderedHtml = renderTemplate(templateHtml, data);
659
691
  fs.writeFileSync(outputPath, renderedHtml);
660
692
  console.log(`HTML report generated: ${outputPath}`);
661
693
  }
694
+ function formatDreadScore(score) {
695
+ if (!score)
696
+ return 'N/A';
697
+ return score.total.toFixed(2);
698
+ }
699
+ function getRiskLevel(result) {
700
+ const counts = getSeverityCounts(result.summary);
701
+ if (counts.critical > 0)
702
+ return 'CRITICAL';
703
+ if (counts.high > 0)
704
+ return 'HIGH';
705
+ if (counts.medium > 0)
706
+ return 'MEDIUM';
707
+ return 'LOW';
708
+ }
709
+ function enhanceFinding(f) {
710
+ return {
711
+ ...f,
712
+ dreadTotal: formatDreadScore(f.dreadScore),
713
+ };
714
+ }
715
+ async function generateProfessionalPdf(result, outputPath, falsePositives = []) {
716
+ const templatePath = path.join(__dirname, '..', 'templates', 'report-pdf.html');
717
+ const templateHtml = fs.readFileSync(templatePath, 'utf-8');
718
+ const counts = getSeverityCounts(result.summary);
719
+ const riskLevel = getRiskLevel(result);
720
+ const { grade, value } = calculateScore(result);
721
+ // Prepare findings with enhanced data
722
+ const criticalFindings = result.findings.filter(f => f.severity === 'critical').map(enhanceFinding);
723
+ const highFindings = result.findings.filter(f => f.severity === 'high').map(enhanceFinding);
724
+ const mediumFindings = result.findings.filter(f => f.severity === 'medium').map(enhanceFinding);
725
+ const lowFindings = result.findings.filter(f => f.severity === 'low' || f.severity === 'info').map(enhanceFinding);
726
+ // Prepare executive summary data
727
+ const execSummary = result.executiveSummary;
728
+ const topRisks = typeof execSummary === 'object' && execSummary?.topRisks
729
+ ? execSummary.topRisks
730
+ : criticalFindings.slice(0, 3).map(f => f.title);
731
+ const keyPositives = typeof execSummary === 'object' && execSummary?.positives
732
+ ? execSummary.positives
733
+ : (result.positiveObservations || []).slice(0, 3).map(o => typeof o === 'string' ? o : o.title || o.description || '');
734
+ // Prepare architecture data
735
+ const arch = result.architectureOverview;
736
+ const architectureComponents = arch?.components?.map(c => ({
737
+ name: c.name,
738
+ type: c.type,
739
+ description: c.description,
740
+ trustLevel: c.trustLevel,
741
+ })) || [];
742
+ const criticalAssets = arch?.criticalAssets?.map(a => ({
743
+ name: a.name,
744
+ type: a.type,
745
+ location: a.location,
746
+ })) || [];
747
+ const entryPoints = arch?.dataFlows || [];
748
+ // Prepare threat model
749
+ const threatModelEntries = result.threatModel?.map(t => ({
750
+ id: t.id,
751
+ threat: t.threat,
752
+ category: t.category,
753
+ strideType: t.strideType,
754
+ status: t.status,
755
+ dreadScore: t.dreadScore,
756
+ relatedFindings: t.relatedFindings?.join(', ') || '',
757
+ })) || [];
758
+ // Prepare quality review
759
+ const qr = result.qualityReview;
760
+ const qualityReview = {
761
+ deleteItems: qr?.deleteItems?.map(i => ({
762
+ file: i.file,
763
+ lines: i.lines || 0,
764
+ description: i.description,
765
+ })) || [],
766
+ mergeItems: qr?.mergeItems?.map(i => ({
767
+ files: i.file,
768
+ description: i.description,
769
+ })) || [],
770
+ simplifyItems: qr?.simplifyItems?.map(i => ({
771
+ file: i.file,
772
+ description: i.description,
773
+ })) || [],
774
+ totalLinesRemovable: qr?.totalLinesRemovable || 0,
775
+ percentageOfCodebase: qr?.percentageOfCodebase || 0,
776
+ };
777
+ // Prepare action items
778
+ const actions = result.actionItems || [];
779
+ const mapActions = (items) => items.map(a => ({
780
+ id: a.id,
781
+ title: a.title,
782
+ effort: a.effort,
783
+ relatedFindings: a.relatedFindings?.join(', ') || '',
784
+ }));
785
+ const immediateActions = mapActions(actions.filter(a => a.priority === 'immediate'));
786
+ const highPriorityActions = mapActions(actions.filter(a => a.priority === 'high'));
787
+ const mediumPriorityActions = mapActions(actions.filter(a => a.priority === 'medium'));
788
+ const longTermActions = mapActions(actions.filter(a => a.priority === 'long-term'));
789
+ // Prepare positive observations
790
+ const positiveObservations = (result.positiveObservations || []).map(o => {
791
+ if (typeof o === 'string') {
792
+ return { title: o, description: '' };
793
+ }
794
+ return { title: o.title || '', description: o.description || '' };
795
+ });
796
+ // Prepare project overview
797
+ const projOverview = result.projectOverview;
798
+ const projectType = projOverview?.type || 'Application';
799
+ const projectDescription = projOverview?.purpose || '';
800
+ const stack = projOverview?.stack?.join(', ') || '';
801
+ const componentsText = projOverview?.keyComponents?.join(', ') || '';
802
+ // Prepare trust boundaries and assets as strings for display
803
+ const trustBoundariesText = arch?.trustBoundaries?.map(b => `${b.from} -> ${b.to} (${b.protocol || 'N/A'})`).join(', ') || '';
804
+ const criticalAssetsText = arch?.criticalAssets?.map(a => `${a.name} (${a.type})`).join(', ') || '';
805
+ const entryPointsText = entryPoints.join(', ') || '';
806
+ // Quality review with total items count
807
+ const qualityReviewWithTotals = {
808
+ ...qualityReview,
809
+ totalItems: (qualityReview.deleteItems?.length || 0) +
810
+ (qualityReview.mergeItems?.length || 0) +
811
+ (qualityReview.simplifyItems?.length || 0),
812
+ };
813
+ // Generate executive summary HTML
814
+ const execSummaryText = generateExecutiveSummary(result);
815
+ const executiveSummaryHtml = `<p>${execSummaryText}</p>`;
816
+ // Cover description
817
+ const coverDescription = projectDescription ||
818
+ `Security assessment covering ${result.filesScanned || 0} files with ${result.findings?.length || 0} findings identified.`;
819
+ const data = {
820
+ projectName: result.projectName,
821
+ scanDate: new Date(result.scanDate).toLocaleDateString('en-US', {
822
+ year: 'numeric',
823
+ month: 'long',
824
+ day: 'numeric',
825
+ }),
826
+ scanDateFull: new Date(result.scanDate).toISOString(),
827
+ branch: result.branch,
828
+ commit: result.commit?.substring(0, 8),
829
+ scope: 'Full Security Assessment',
830
+ assessedBy: 'CoverMe Security Scanner',
831
+ version: '2.0',
832
+ // Project Overview
833
+ projectType,
834
+ projectDescription,
835
+ stack,
836
+ componentsText,
837
+ coverDescription,
838
+ // Project Tree and Lines of Code
839
+ projectTree: result.projectTree,
840
+ linesOfCode: result.linesOfCode || 0,
841
+ // Severity counts
842
+ criticalCount: counts.critical,
843
+ highCount: counts.high,
844
+ mediumCount: counts.medium,
845
+ lowCount: counts.low,
846
+ infoCount: counts.info,
847
+ totalFindings: result.findings?.length || 0,
848
+ // Risk
849
+ riskScore: `${grade.toUpperCase()} (${value}/100)`,
850
+ riskLevel,
851
+ // Executive Summary
852
+ executiveSummary: execSummaryText,
853
+ executiveSummaryHtml,
854
+ topRisks,
855
+ keyPositives,
856
+ // Architecture
857
+ architectureComponents,
858
+ criticalAssets: criticalAssetsText,
859
+ trustBoundaries: trustBoundariesText,
860
+ entryPoints: entryPointsText,
861
+ // Findings
862
+ criticalFindings,
863
+ highFindings,
864
+ mediumFindings,
865
+ lowFindings,
866
+ // Threat Model
867
+ threatModel: threatModelEntries,
868
+ // Quality Review
869
+ qualityReview: qualityReviewWithTotals,
870
+ // Resolved Issues (empty for now, can be populated from scan results)
871
+ resolvedIssues: [],
872
+ // Action Items
873
+ immediateActions,
874
+ highPriorityActions,
875
+ mediumPriorityActions,
876
+ longTermActions,
877
+ // Positive Observations
878
+ positiveObservations,
879
+ // Stats
880
+ filesScanned: result.filesScanned || 0,
881
+ agentCount: result.agentsUsed?.length || 0,
882
+ scanDuration: `${Math.round((result.scanDuration || 0) / 1000)} seconds`,
883
+ avgConfidence: Math.round((result.summary?.avgConfidence || 0) * 100),
884
+ };
885
+ // Register Handlebars helpers
886
+ handlebars_1.default.registerHelper('eq', (a, b) => a === b);
887
+ handlebars_1.default.registerHelper('gt', (a, b) => a > b);
888
+ handlebars_1.default.registerHelper('gte', (a, b) => a >= b);
889
+ handlebars_1.default.registerHelper('lt', (a, b) => a < b);
890
+ handlebars_1.default.registerHelper('add', (a, b) => a + b);
891
+ handlebars_1.default.registerHelper('toFixed', (n, digits) => n?.toFixed(digits) || 'N/A');
892
+ const template = handlebars_1.default.compile(templateHtml);
893
+ const renderedHtml = template(data);
894
+ // Generate PDF with proper pagination
895
+ const browser = await puppeteer_1.default.launch({
896
+ headless: true,
897
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
898
+ });
899
+ const page = await browser.newPage();
900
+ await page.setContent(renderedHtml, { waitUntil: 'networkidle0' });
901
+ // A4 PDF with proper page breaks
902
+ await page.pdf({
903
+ path: outputPath,
904
+ format: 'A4',
905
+ margin: {
906
+ top: '20mm',
907
+ right: '15mm',
908
+ bottom: '20mm',
909
+ left: '15mm',
910
+ },
911
+ printBackground: true,
912
+ displayHeaderFooter: true,
913
+ headerTemplate: `
914
+ <div style="width: 100%; font-size: 9px; color: #666; padding: 0 15mm; display: flex; justify-content: space-between;">
915
+ <span>${escapeHtml(result.projectName)} - Security Assessment</span>
916
+ <span>CONFIDENTIAL</span>
917
+ </div>
918
+ `,
919
+ footerTemplate: `
920
+ <div style="width: 100%; font-size: 9px; color: #666; padding: 0 15mm; display: flex; justify-content: space-between;">
921
+ <span>Generated by CoverMe Security Scanner</span>
922
+ <span>Page <span class="pageNumber"></span> of <span class="totalPages"></span></span>
923
+ </div>
924
+ `,
925
+ });
926
+ await browser.close();
927
+ console.log(`Professional PDF report generated: ${outputPath}`);
928
+ }
662
929
  //# sourceMappingURL=generator.js.map