@voidagency/web-scanner 0.0.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.
- package/README.md +198 -0
- package/dist/aggregator.d.ts +65 -0
- package/dist/aggregator.d.ts.map +1 -0
- package/dist/aggregator.js +546 -0
- package/dist/aggregator.js.map +1 -0
- package/dist/categories.d.ts +59 -0
- package/dist/categories.d.ts.map +1 -0
- package/dist/categories.js +278 -0
- package/dist/categories.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +457 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +121 -0
- package/dist/config.js.map +1 -0
- package/dist/coverage.d.ts +49 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +165 -0
- package/dist/coverage.js.map +1 -0
- package/dist/enrichers/nvd.d.ts +55 -0
- package/dist/enrichers/nvd.d.ts.map +1 -0
- package/dist/enrichers/nvd.js +326 -0
- package/dist/enrichers/nvd.js.map +1 -0
- package/dist/report.d.ts +12 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +460 -0
- package/dist/report.js.map +1 -0
- package/dist/runners/nuclei.d.ts +59 -0
- package/dist/runners/nuclei.d.ts.map +1 -0
- package/dist/runners/nuclei.js +531 -0
- package/dist/runners/nuclei.js.map +1 -0
- package/dist/runners/testssl.d.ts +16 -0
- package/dist/runners/testssl.d.ts.map +1 -0
- package/dist/runners/testssl.js +179 -0
- package/dist/runners/testssl.js.map +1 -0
- package/dist/runners/zap.d.ts +30 -0
- package/dist/runners/zap.d.ts.map +1 -0
- package/dist/runners/zap.js +389 -0
- package/dist/runners/zap.js.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
- package/templates/drupal-api-index-exposed.yaml +81 -0
- package/templates/drupal-api-user-detail.yaml +76 -0
- package/templates/drupal-api-user-listing.yaml +59 -0
- package/templates/drupal-dev-files-exposed.yaml +73 -0
- package/templates/drupal-file-path-disclosure.yaml +59 -0
- package/templates/drupal-files-listing.yaml +63 -0
- package/templates/drupal-install-error-disclosure.yaml +62 -0
- package/templates/drupal-theme-lockfiles.yaml +79 -0
- package/templates/drupal-version-detect.yaml +89 -0
- package/templates/http-options-enabled.yaml +56 -0
- package/templates/nextjs-version-detect.yaml +35 -0
- package/templates/php-version-detect.yaml +37 -0
- package/zap.yaml +33 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Coverage Tracker
|
|
3
|
+
* Tracks which test categories were run and their results
|
|
4
|
+
*/
|
|
5
|
+
import { Finding } from './types.js';
|
|
6
|
+
import { CategoryResult } from './categories.js';
|
|
7
|
+
/**
|
|
8
|
+
* Coverage summary for reporting
|
|
9
|
+
*/
|
|
10
|
+
export interface CoverageSummary {
|
|
11
|
+
totalCategories: number;
|
|
12
|
+
testedCategories: number;
|
|
13
|
+
categoriesWithFindings: number;
|
|
14
|
+
results: CategoryResult[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Calculate test coverage from findings
|
|
18
|
+
* Each finding is counted in only ONE category (its best/first match)
|
|
19
|
+
* to avoid double-counting
|
|
20
|
+
*/
|
|
21
|
+
export declare function calculateCoverage(findings: Finding[]): CoverageSummary;
|
|
22
|
+
/**
|
|
23
|
+
* Mark categories as tested based on scan profile
|
|
24
|
+
* In deep/standard profiles, we run more templates so more categories are "tested"
|
|
25
|
+
*/
|
|
26
|
+
export declare function markTestedCategories(coverage: CoverageSummary, profile: 'quick' | 'standard' | 'deep', ranTemplates: string[]): CoverageSummary;
|
|
27
|
+
/**
|
|
28
|
+
* Format coverage for CLI output
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatCoverageForCli(coverage: CoverageSummary): string;
|
|
31
|
+
/**
|
|
32
|
+
* Get coverage data for HTML report
|
|
33
|
+
*/
|
|
34
|
+
export declare function getCoverageForReport(coverage: CoverageSummary): Array<{
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
tested: boolean;
|
|
38
|
+
status: 'pass' | 'fail' | 'info' | 'untested';
|
|
39
|
+
count: number;
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Get passed security checks for the report footer
|
|
43
|
+
* Shows all tested categories with 0 findings
|
|
44
|
+
*/
|
|
45
|
+
export declare function getPassedChecksForReport(coverage: CoverageSummary): Array<{
|
|
46
|
+
name: string;
|
|
47
|
+
description: string;
|
|
48
|
+
}>;
|
|
49
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAGL,cAAc,EAGf,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,eAAe,CAgEtE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,EACtC,YAAY,EAAE,MAAM,EAAE,GACrB,eAAe,CAoDjB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAwBtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,KAAK,CAAC;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAcD;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,KAAK,CAAC;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAQD"}
|
package/dist/coverage.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Coverage Tracker
|
|
3
|
+
* Tracks which test categories were run and their results
|
|
4
|
+
*/
|
|
5
|
+
import { TEST_CATEGORIES, matchCategories } from './categories.js';
|
|
6
|
+
/**
|
|
7
|
+
* Calculate test coverage from findings
|
|
8
|
+
* Each finding is counted in only ONE category (its best/first match)
|
|
9
|
+
* to avoid double-counting
|
|
10
|
+
*/
|
|
11
|
+
export function calculateCoverage(findings) {
|
|
12
|
+
// Initialize results for all categories
|
|
13
|
+
const categoryResults = new Map();
|
|
14
|
+
for (const category of TEST_CATEGORIES) {
|
|
15
|
+
categoryResults.set(category.id, {
|
|
16
|
+
category,
|
|
17
|
+
tested: false,
|
|
18
|
+
findingCount: 0,
|
|
19
|
+
findings: [],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// Track which findings have been assigned
|
|
23
|
+
const assignedFindings = new Set();
|
|
24
|
+
// Process each finding - assign to FIRST matching category only
|
|
25
|
+
for (const finding of findings) {
|
|
26
|
+
if (assignedFindings.has(finding.id))
|
|
27
|
+
continue;
|
|
28
|
+
const categories = matchCategories(finding.templateId || '', finding.tags || []);
|
|
29
|
+
// Only count in the FIRST (most specific) matching category
|
|
30
|
+
if (categories.length > 0) {
|
|
31
|
+
const categoryId = categories[0];
|
|
32
|
+
const result = categoryResults.get(categoryId);
|
|
33
|
+
if (result) {
|
|
34
|
+
result.tested = true;
|
|
35
|
+
result.findingCount++;
|
|
36
|
+
result.findings.push(finding.id);
|
|
37
|
+
assignedFindings.add(finding.id);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Also mark categories as "tested" if templates ran (even with 0 findings)
|
|
42
|
+
for (const finding of findings) {
|
|
43
|
+
const categories = matchCategories(finding.templateId || '', finding.tags || []);
|
|
44
|
+
for (const categoryId of categories) {
|
|
45
|
+
const result = categoryResults.get(categoryId);
|
|
46
|
+
if (result) {
|
|
47
|
+
result.tested = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Convert to array and calculate summary
|
|
52
|
+
const results = Array.from(categoryResults.values());
|
|
53
|
+
// Mark categories as "tested" if we ran templates that would have found them
|
|
54
|
+
// (For now, we mark all categories as tested in standard/deep profiles)
|
|
55
|
+
return {
|
|
56
|
+
totalCategories: TEST_CATEGORIES.length,
|
|
57
|
+
testedCategories: results.filter(r => r.tested).length,
|
|
58
|
+
categoriesWithFindings: results.filter(r => r.findingCount > 0).length,
|
|
59
|
+
results,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Mark categories as tested based on scan profile
|
|
64
|
+
* In deep/standard profiles, we run more templates so more categories are "tested"
|
|
65
|
+
*/
|
|
66
|
+
export function markTestedCategories(coverage, profile, ranTemplates) {
|
|
67
|
+
// Categories that are always tested (basic checks)
|
|
68
|
+
const alwaysTested = [
|
|
69
|
+
'security-headers',
|
|
70
|
+
'tech-detection',
|
|
71
|
+
'admin-panels',
|
|
72
|
+
'misconfigurations',
|
|
73
|
+
];
|
|
74
|
+
// Additional categories for standard profile
|
|
75
|
+
const standardTested = [
|
|
76
|
+
'sensitive-files',
|
|
77
|
+
'info-disclosure',
|
|
78
|
+
'directory-listing',
|
|
79
|
+
'api-endpoints',
|
|
80
|
+
'client-policies',
|
|
81
|
+
'http-methods',
|
|
82
|
+
'known-cves',
|
|
83
|
+
];
|
|
84
|
+
// Additional categories for deep profile (fuzzing)
|
|
85
|
+
const deepTested = [
|
|
86
|
+
'xss',
|
|
87
|
+
'sqli',
|
|
88
|
+
'lfi',
|
|
89
|
+
'rce',
|
|
90
|
+
'ssrf',
|
|
91
|
+
'redirect',
|
|
92
|
+
];
|
|
93
|
+
// Determine which categories were tested based on profile
|
|
94
|
+
let testedIds = [...alwaysTested];
|
|
95
|
+
if (profile === 'standard' || profile === 'deep') {
|
|
96
|
+
testedIds = [...testedIds, ...standardTested];
|
|
97
|
+
}
|
|
98
|
+
if (profile === 'deep') {
|
|
99
|
+
testedIds = [...testedIds, ...deepTested];
|
|
100
|
+
}
|
|
101
|
+
// Mark categories as tested
|
|
102
|
+
for (const result of coverage.results) {
|
|
103
|
+
if (testedIds.includes(result.category.id)) {
|
|
104
|
+
result.tested = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Recalculate summary
|
|
108
|
+
coverage.testedCategories = coverage.results.filter(r => r.tested).length;
|
|
109
|
+
return coverage;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format coverage for CLI output
|
|
113
|
+
*/
|
|
114
|
+
export function formatCoverageForCli(coverage) {
|
|
115
|
+
const lines = [];
|
|
116
|
+
lines.push('\nTest Coverage:');
|
|
117
|
+
lines.push('─'.repeat(50));
|
|
118
|
+
for (const result of coverage.results) {
|
|
119
|
+
if (!result.tested)
|
|
120
|
+
continue; // Skip untested categories
|
|
121
|
+
const icon = result.findingCount > 0 ? '⚠️' : '✅';
|
|
122
|
+
const count = result.findingCount > 0
|
|
123
|
+
? ` (${result.findingCount} issue${result.findingCount > 1 ? 's' : ''})`
|
|
124
|
+
: '';
|
|
125
|
+
const status = result.findingCount > 0
|
|
126
|
+
? `${result.findingCount} found`
|
|
127
|
+
: 'Nothing found';
|
|
128
|
+
lines.push(`${icon} ${result.category.name} - ${status}`);
|
|
129
|
+
}
|
|
130
|
+
lines.push('─'.repeat(50));
|
|
131
|
+
lines.push(`Tested: ${coverage.testedCategories}/${coverage.totalCategories} categories`);
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get coverage data for HTML report
|
|
136
|
+
*/
|
|
137
|
+
export function getCoverageForReport(coverage) {
|
|
138
|
+
return coverage.results.map(result => ({
|
|
139
|
+
name: result.category.name,
|
|
140
|
+
description: result.category.description,
|
|
141
|
+
tested: result.tested,
|
|
142
|
+
status: !result.tested
|
|
143
|
+
? 'untested'
|
|
144
|
+
: result.findingCount === 0
|
|
145
|
+
? 'pass'
|
|
146
|
+
: result.category.id === 'tech-detection'
|
|
147
|
+
? 'info'
|
|
148
|
+
: 'fail',
|
|
149
|
+
count: result.findingCount,
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get passed security checks for the report footer
|
|
154
|
+
* Shows all tested categories with 0 findings
|
|
155
|
+
*/
|
|
156
|
+
export function getPassedChecksForReport(coverage) {
|
|
157
|
+
return coverage.results
|
|
158
|
+
.filter(result => result.tested && result.findingCount === 0)
|
|
159
|
+
.filter(result => result.category.id !== 'tech-detection') // Exclude tech detection (not a "security check")
|
|
160
|
+
.map(result => ({
|
|
161
|
+
name: result.category.name,
|
|
162
|
+
description: result.category.description,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NVD API Enrichment
|
|
3
|
+
* Query NIST NVD for CVE details, CVSS scores, descriptions
|
|
4
|
+
*
|
|
5
|
+
* API Docs: https://nvd.nist.gov/developers/vulnerabilities
|
|
6
|
+
*/
|
|
7
|
+
export interface NvdCveData {
|
|
8
|
+
id: string;
|
|
9
|
+
description: string;
|
|
10
|
+
cvssScore?: number;
|
|
11
|
+
cvssVector?: string;
|
|
12
|
+
cweId?: string;
|
|
13
|
+
cweDescription?: string;
|
|
14
|
+
references: string[];
|
|
15
|
+
published?: string;
|
|
16
|
+
lastModified?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface NvdEnrichment {
|
|
19
|
+
description: string;
|
|
20
|
+
cvssScore?: number;
|
|
21
|
+
cvssVector?: string;
|
|
22
|
+
cweId?: string;
|
|
23
|
+
references: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Query NVD API for a specific CVE
|
|
27
|
+
*/
|
|
28
|
+
export declare function getCveDetails(cveId: string): Promise<NvdCveData | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Query NVD for CVEs affecting a specific software version (by CPE)
|
|
31
|
+
*/
|
|
32
|
+
export declare function getCvesByCpe(vendor: string, product: string, version: string, limit?: number): Promise<NvdCveData[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Get CPE mapping for a technology name
|
|
35
|
+
*/
|
|
36
|
+
export declare function getCpeMapping(techName: string): {
|
|
37
|
+
vendor: string;
|
|
38
|
+
product: string;
|
|
39
|
+
} | null;
|
|
40
|
+
/**
|
|
41
|
+
* Enrich a finding with NVD data
|
|
42
|
+
* Returns enrichment data to merge into finding
|
|
43
|
+
* Handles multiple CVEs in a single field
|
|
44
|
+
*/
|
|
45
|
+
export declare function enrichWithNvd(cveString: string): Promise<NvdEnrichment | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Query NVD API by keyword search
|
|
48
|
+
*/
|
|
49
|
+
export declare function getCvesByKeyword(keyword: string, limit?: number): Promise<NvdCveData[]>;
|
|
50
|
+
/**
|
|
51
|
+
* Get CVEs for a specific technology and version
|
|
52
|
+
* Tries CPE first, falls back to keyword search
|
|
53
|
+
*/
|
|
54
|
+
export declare function getCvesForTechnology(technology: string, version: string, limit?: number): Promise<NvdCveData[]>;
|
|
55
|
+
//# sourceMappingURL=nvd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd.d.ts","sourceRoot":"","sources":["../../src/enrichers/nvd.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAiBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA8E7E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CA+EvB;AA0BD;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAG1F;AAWD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAqBpF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CA4EvB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BvB"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NVD API Enrichment
|
|
3
|
+
* Query NIST NVD for CVE details, CVSS scores, descriptions
|
|
4
|
+
*
|
|
5
|
+
* API Docs: https://nvd.nist.gov/developers/vulnerabilities
|
|
6
|
+
*/
|
|
7
|
+
const NVD_API_BASE = 'https://services.nvd.nist.gov/rest/json/cves/2.0';
|
|
8
|
+
// Rate limit: 5 requests per 30 seconds without API key
|
|
9
|
+
// With API key: 50 requests per 30 seconds
|
|
10
|
+
const RATE_LIMIT_DELAY = 6500; // 6.5 seconds between requests (safe without key)
|
|
11
|
+
let lastRequestTime = 0;
|
|
12
|
+
/**
|
|
13
|
+
* Wait for rate limit
|
|
14
|
+
*/
|
|
15
|
+
async function waitForRateLimit() {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const timeSinceLastRequest = now - lastRequestTime;
|
|
18
|
+
if (timeSinceLastRequest < RATE_LIMIT_DELAY) {
|
|
19
|
+
const waitTime = RATE_LIMIT_DELAY - timeSinceLastRequest;
|
|
20
|
+
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
21
|
+
}
|
|
22
|
+
lastRequestTime = Date.now();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Query NVD API for a specific CVE
|
|
26
|
+
*/
|
|
27
|
+
export async function getCveDetails(cveId) {
|
|
28
|
+
if (!cveId || !cveId.startsWith('CVE-')) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
await waitForRateLimit();
|
|
32
|
+
try {
|
|
33
|
+
const url = `${NVD_API_BASE}?cveId=${encodeURIComponent(cveId)}`;
|
|
34
|
+
const response = await fetch(url, {
|
|
35
|
+
headers: {
|
|
36
|
+
'User-Agent': 'VoidSec-Scanner/0.1.0',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
console.warn(`NVD API error for ${cveId}: ${response.status}`);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
if (!data.vulnerabilities || data.vulnerabilities.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const vuln = data.vulnerabilities[0].cve;
|
|
48
|
+
// Extract description (prefer English)
|
|
49
|
+
const descriptions = vuln.descriptions || [];
|
|
50
|
+
const engDesc = descriptions.find((d) => d.lang === 'en');
|
|
51
|
+
const description = engDesc?.value || descriptions[0]?.value || '';
|
|
52
|
+
// Extract CVSS (prefer v3.1, then v3.0, then v2)
|
|
53
|
+
const metrics = vuln.metrics || {};
|
|
54
|
+
let cvssScore;
|
|
55
|
+
let cvssVector;
|
|
56
|
+
if (metrics.cvssMetricV31?.[0]) {
|
|
57
|
+
cvssScore = metrics.cvssMetricV31[0].cvssData?.baseScore;
|
|
58
|
+
cvssVector = metrics.cvssMetricV31[0].cvssData?.vectorString;
|
|
59
|
+
}
|
|
60
|
+
else if (metrics.cvssMetricV30?.[0]) {
|
|
61
|
+
cvssScore = metrics.cvssMetricV30[0].cvssData?.baseScore;
|
|
62
|
+
cvssVector = metrics.cvssMetricV30[0].cvssData?.vectorString;
|
|
63
|
+
}
|
|
64
|
+
else if (metrics.cvssMetricV2?.[0]) {
|
|
65
|
+
cvssScore = metrics.cvssMetricV2[0].cvssData?.baseScore;
|
|
66
|
+
cvssVector = metrics.cvssMetricV2[0].cvssData?.vectorString;
|
|
67
|
+
}
|
|
68
|
+
// Extract CWE
|
|
69
|
+
const weaknesses = vuln.weaknesses || [];
|
|
70
|
+
let cweId;
|
|
71
|
+
for (const w of weaknesses) {
|
|
72
|
+
const desc = w.description?.find((d) => d.lang === 'en');
|
|
73
|
+
if (desc?.value && desc.value.startsWith('CWE-')) {
|
|
74
|
+
cweId = desc.value;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Extract references
|
|
79
|
+
const refs = vuln.references || [];
|
|
80
|
+
const references = refs.map((r) => r.url).slice(0, 5); // Limit to 5
|
|
81
|
+
return {
|
|
82
|
+
id: cveId,
|
|
83
|
+
description,
|
|
84
|
+
cvssScore,
|
|
85
|
+
cvssVector,
|
|
86
|
+
cweId,
|
|
87
|
+
references,
|
|
88
|
+
published: vuln.published,
|
|
89
|
+
lastModified: vuln.lastModified,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.warn(`Failed to fetch CVE ${cveId}: ${error}`);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Query NVD for CVEs affecting a specific software version (by CPE)
|
|
99
|
+
*/
|
|
100
|
+
export async function getCvesByCpe(vendor, product, version, limit = 10) {
|
|
101
|
+
await waitForRateLimit();
|
|
102
|
+
// Build CPE 2.3 string
|
|
103
|
+
const cpe = `cpe:2.3:a:${vendor}:${product}:${version}:*:*:*:*:*:*:*`;
|
|
104
|
+
try {
|
|
105
|
+
const url = `${NVD_API_BASE}?cpeName=${encodeURIComponent(cpe)}&resultsPerPage=${limit}`;
|
|
106
|
+
const response = await fetch(url, {
|
|
107
|
+
headers: {
|
|
108
|
+
'User-Agent': 'VoidSec-Scanner/0.1.0',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
console.warn(`NVD API error for CPE ${cpe}: ${response.status}`);
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const data = await response.json();
|
|
116
|
+
if (!data.vulnerabilities || data.vulnerabilities.length === 0) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
const results = [];
|
|
120
|
+
for (const item of data.vulnerabilities) {
|
|
121
|
+
const vuln = item.cve;
|
|
122
|
+
const descriptions = vuln.descriptions || [];
|
|
123
|
+
const engDesc = descriptions.find((d) => d.lang === 'en');
|
|
124
|
+
const description = engDesc?.value || descriptions[0]?.value || '';
|
|
125
|
+
const metrics = vuln.metrics || {};
|
|
126
|
+
let cvssScore;
|
|
127
|
+
let cvssVector;
|
|
128
|
+
if (metrics.cvssMetricV31?.[0]) {
|
|
129
|
+
cvssScore = metrics.cvssMetricV31[0].cvssData?.baseScore;
|
|
130
|
+
cvssVector = metrics.cvssMetricV31[0].cvssData?.vectorString;
|
|
131
|
+
}
|
|
132
|
+
else if (metrics.cvssMetricV30?.[0]) {
|
|
133
|
+
cvssScore = metrics.cvssMetricV30[0].cvssData?.baseScore;
|
|
134
|
+
cvssVector = metrics.cvssMetricV30[0].cvssData?.vectorString;
|
|
135
|
+
}
|
|
136
|
+
else if (metrics.cvssMetricV2?.[0]) {
|
|
137
|
+
cvssScore = metrics.cvssMetricV2[0].cvssData?.baseScore;
|
|
138
|
+
cvssVector = metrics.cvssMetricV2[0].cvssData?.vectorString;
|
|
139
|
+
}
|
|
140
|
+
const weaknesses = vuln.weaknesses || [];
|
|
141
|
+
let cweId;
|
|
142
|
+
for (const w of weaknesses) {
|
|
143
|
+
const desc = w.description?.find((d) => d.lang === 'en');
|
|
144
|
+
if (desc?.value && desc.value.startsWith('CWE-')) {
|
|
145
|
+
cweId = desc.value;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const refs = vuln.references || [];
|
|
150
|
+
const references = refs.map((r) => r.url).slice(0, 3);
|
|
151
|
+
results.push({
|
|
152
|
+
id: vuln.id,
|
|
153
|
+
description,
|
|
154
|
+
cvssScore,
|
|
155
|
+
cvssVector,
|
|
156
|
+
cweId,
|
|
157
|
+
references,
|
|
158
|
+
published: vuln.published,
|
|
159
|
+
lastModified: vuln.lastModified,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
console.warn(`Failed to fetch CVEs for CPE ${cpe}: ${error}`);
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Common CPE vendor/product mappings for detected technologies
|
|
170
|
+
const CPE_MAPPINGS = {
|
|
171
|
+
'nginx': { vendor: 'f5', product: 'nginx' },
|
|
172
|
+
'apache': { vendor: 'apache', product: 'http_server' },
|
|
173
|
+
'drupal': { vendor: 'drupal', product: 'drupal' },
|
|
174
|
+
'wordpress': { vendor: 'wordpress', product: 'wordpress' },
|
|
175
|
+
'php': { vendor: 'php', product: 'php' },
|
|
176
|
+
'mysql': { vendor: 'oracle', product: 'mysql' },
|
|
177
|
+
'postgresql': { vendor: 'postgresql', product: 'postgresql' },
|
|
178
|
+
'nodejs': { vendor: 'nodejs', product: 'node.js' },
|
|
179
|
+
'node.js': { vendor: 'nodejs', product: 'node.js' },
|
|
180
|
+
'openssl': { vendor: 'openssl', product: 'openssl' },
|
|
181
|
+
'jquery': { vendor: 'jquery', product: 'jquery' },
|
|
182
|
+
'bootstrap': { vendor: 'getbootstrap', product: 'bootstrap' },
|
|
183
|
+
'laravel': { vendor: 'laravel', product: 'laravel' },
|
|
184
|
+
'nextjs': { vendor: 'vercel', product: 'next.js' },
|
|
185
|
+
'next.js': { vendor: 'vercel', product: 'next.js' },
|
|
186
|
+
'react': { vendor: 'facebook', product: 'react' },
|
|
187
|
+
'vue': { vendor: 'vuejs', product: 'vue.js' },
|
|
188
|
+
'angular': { vendor: 'google', product: 'angular' },
|
|
189
|
+
'tomcat': { vendor: 'apache', product: 'tomcat' },
|
|
190
|
+
'iis': { vendor: 'microsoft', product: 'internet_information_services' },
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Get CPE mapping for a technology name
|
|
194
|
+
*/
|
|
195
|
+
export function getCpeMapping(techName) {
|
|
196
|
+
const normalized = techName.toLowerCase().trim();
|
|
197
|
+
return CPE_MAPPINGS[normalized] || null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Parse CVE string - may contain multiple CVEs separated by space
|
|
201
|
+
*/
|
|
202
|
+
function parseCveIds(cveString) {
|
|
203
|
+
// Match all CVE-XXXX-XXXXX patterns
|
|
204
|
+
const matches = cveString.match(/CVE-\d{4}-\d+/g);
|
|
205
|
+
return matches || [];
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Enrich a finding with NVD data
|
|
209
|
+
* Returns enrichment data to merge into finding
|
|
210
|
+
* Handles multiple CVEs in a single field
|
|
211
|
+
*/
|
|
212
|
+
export async function enrichWithNvd(cveString) {
|
|
213
|
+
const cveIds = parseCveIds(cveString);
|
|
214
|
+
if (cveIds.length === 0) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
// For multiple CVEs, get data for the first one (usually the most relevant)
|
|
218
|
+
const cveData = await getCveDetails(cveIds[0]);
|
|
219
|
+
if (!cveData) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
description: cveData.description,
|
|
224
|
+
cvssScore: cveData.cvssScore,
|
|
225
|
+
cvssVector: cveData.cvssVector,
|
|
226
|
+
cweId: cveData.cweId,
|
|
227
|
+
references: cveData.references,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Query NVD API by keyword search
|
|
232
|
+
*/
|
|
233
|
+
export async function getCvesByKeyword(keyword, limit = 10) {
|
|
234
|
+
await waitForRateLimit();
|
|
235
|
+
try {
|
|
236
|
+
const url = `${NVD_API_BASE}?keywordSearch=${encodeURIComponent(keyword)}&resultsPerPage=${limit}`;
|
|
237
|
+
const response = await fetch(url, {
|
|
238
|
+
headers: {
|
|
239
|
+
'User-Agent': 'VoidSec-Scanner/0.1.0',
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
console.warn(`NVD API error for keyword "${keyword}": ${response.status}`);
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
const data = await response.json();
|
|
247
|
+
if (!data.vulnerabilities || data.vulnerabilities.length === 0) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
const results = [];
|
|
251
|
+
for (const item of data.vulnerabilities) {
|
|
252
|
+
const vuln = item.cve;
|
|
253
|
+
const descriptions = vuln.descriptions || [];
|
|
254
|
+
const engDesc = descriptions.find((d) => d.lang === 'en');
|
|
255
|
+
const description = engDesc?.value || descriptions[0]?.value || '';
|
|
256
|
+
const metrics = vuln.metrics || {};
|
|
257
|
+
let cvssScore;
|
|
258
|
+
let cvssVector;
|
|
259
|
+
if (metrics.cvssMetricV31?.[0]) {
|
|
260
|
+
cvssScore = metrics.cvssMetricV31[0].cvssData?.baseScore;
|
|
261
|
+
cvssVector = metrics.cvssMetricV31[0].cvssData?.vectorString;
|
|
262
|
+
}
|
|
263
|
+
else if (metrics.cvssMetricV30?.[0]) {
|
|
264
|
+
cvssScore = metrics.cvssMetricV30[0].cvssData?.baseScore;
|
|
265
|
+
cvssVector = metrics.cvssMetricV30[0].cvssData?.vectorString;
|
|
266
|
+
}
|
|
267
|
+
else if (metrics.cvssMetricV2?.[0]) {
|
|
268
|
+
cvssScore = metrics.cvssMetricV2[0].cvssData?.baseScore;
|
|
269
|
+
cvssVector = metrics.cvssMetricV2[0].cvssData?.vectorString;
|
|
270
|
+
}
|
|
271
|
+
const weaknesses = vuln.weaknesses || [];
|
|
272
|
+
let cweId;
|
|
273
|
+
for (const w of weaknesses) {
|
|
274
|
+
const desc = w.description?.find((d) => d.lang === 'en');
|
|
275
|
+
if (desc?.value && desc.value.startsWith('CWE-')) {
|
|
276
|
+
cweId = desc.value;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const refs = vuln.references || [];
|
|
281
|
+
const references = refs.map((r) => r.url).slice(0, 3);
|
|
282
|
+
results.push({
|
|
283
|
+
id: vuln.id,
|
|
284
|
+
description,
|
|
285
|
+
cvssScore,
|
|
286
|
+
cvssVector,
|
|
287
|
+
cweId,
|
|
288
|
+
references,
|
|
289
|
+
published: vuln.published,
|
|
290
|
+
lastModified: vuln.lastModified,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return results;
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
console.warn(`Failed to fetch CVEs for keyword "${keyword}": ${error}`);
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Get CVEs for a specific technology and version
|
|
302
|
+
* Tries CPE first, falls back to keyword search
|
|
303
|
+
*/
|
|
304
|
+
export async function getCvesForTechnology(technology, version, limit = 10) {
|
|
305
|
+
const cpeMapping = getCpeMapping(technology);
|
|
306
|
+
console.log(` 🔍 Looking up CVEs for ${technology} ${version}...`);
|
|
307
|
+
let cves = [];
|
|
308
|
+
// Try CPE-based search first
|
|
309
|
+
if (cpeMapping) {
|
|
310
|
+
cves = await getCvesByCpe(cpeMapping.vendor, cpeMapping.product, version, limit);
|
|
311
|
+
}
|
|
312
|
+
// If CPE search found nothing, try keyword search
|
|
313
|
+
if (cves.length === 0) {
|
|
314
|
+
const keyword = `${technology} ${version}`;
|
|
315
|
+
console.log(` ⚠ No CPE results, trying keyword search: "${keyword}"...`);
|
|
316
|
+
cves = await getCvesByKeyword(keyword, limit);
|
|
317
|
+
}
|
|
318
|
+
if (cves.length > 0) {
|
|
319
|
+
console.log(` ✓ Found ${cves.length} CVEs for ${technology} ${version}`);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
console.log(` ⚠ No CVEs found for ${technology} ${version}`);
|
|
323
|
+
}
|
|
324
|
+
return cves;
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=nvd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd.js","sourceRoot":"","sources":["../../src/enrichers/nvd.ts"],"names":[],"mappings":"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"}
|
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Generator
|
|
3
|
+
* Generate HTML reports from scan results
|
|
4
|
+
* Uses Tailwind CSS + Alpine.js for styling and interactivity
|
|
5
|
+
*/
|
|
6
|
+
import { Report } from './types.js';
|
|
7
|
+
export declare function generateHtmlReport(report: Report): string;
|
|
8
|
+
/**
|
|
9
|
+
* Generate JSON report from scan results
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateJsonReport(report: Report): string;
|
|
12
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAqB,MAAM,YAAY,CAAC;AAocvD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|