codeprobe-scanner 1.0.14 ā 1.0.15
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/package.json +1 -1
- package/src/cli/commands/scan.ts +2 -2
- package/src/engine/index.ts +62 -1
- package/src/shared/file-scanner.ts +50 -0
package/package.json
CHANGED
package/src/cli/commands/scan.ts
CHANGED
|
@@ -110,8 +110,8 @@ export async function scanCommand(args: string[]): Promise<void> {
|
|
|
110
110
|
try {
|
|
111
111
|
const engine = createEngine();
|
|
112
112
|
|
|
113
|
-
// Run
|
|
114
|
-
const report = await engine.
|
|
113
|
+
// Run recursive scan to find all package.json files
|
|
114
|
+
const report = await engine.scanRecursive(repoPath);
|
|
115
115
|
|
|
116
116
|
const duration = Date.now() - startTime;
|
|
117
117
|
|
package/src/engine/index.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { createSandbox } from "./sandbox";
|
|
|
4
4
|
import { createMatcher } from "./matcher";
|
|
5
5
|
import { createPatcher } from "./patcher";
|
|
6
6
|
import { createReportBuilder } from "./report";
|
|
7
|
-
import { Report } from "../shared/types";
|
|
7
|
+
import { Report, ScanCVE } from "../shared/types";
|
|
8
|
+
import { findAllPackageJsons } from "../shared/file-scanner";
|
|
8
9
|
|
|
9
10
|
export class CodeProbeEngine {
|
|
10
11
|
private parser = createParser();
|
|
@@ -18,6 +19,66 @@ export class CodeProbeEngine {
|
|
|
18
19
|
return this.sandbox.getVideoRecorder();
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
async scanRecursive(rootPath: string): Promise<Report> {
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Find all package.json files
|
|
27
|
+
console.log("š Searching for package.json files...");
|
|
28
|
+
const packageJsonLocations = await findAllPackageJsons(rootPath);
|
|
29
|
+
console.log(` Found ${packageJsonLocations.length} package.json file(s)`);
|
|
30
|
+
|
|
31
|
+
if (packageJsonLocations.length === 0) {
|
|
32
|
+
throw new Error("No package.json files found in the repository");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Scan each location
|
|
36
|
+
const allCves: ScanCVE[] = [];
|
|
37
|
+
const allDependencies: number[] = [];
|
|
38
|
+
const scannedLocations: string[] = [];
|
|
39
|
+
|
|
40
|
+
for (const location of packageJsonLocations) {
|
|
41
|
+
console.log(`\nš Scanning: ${location.path}`);
|
|
42
|
+
try {
|
|
43
|
+
const report = await this.scan(location.path);
|
|
44
|
+
allCves.push(...report.scan.cves);
|
|
45
|
+
allDependencies.push(report.scan.total_dependencies);
|
|
46
|
+
scannedLocations.push(location.path);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.warn(
|
|
49
|
+
` ā ļø Skipped: ${error instanceof Error ? error.message : String(error)}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Aggregate results
|
|
55
|
+
const riskScore = this.matcher.calculateRiskScore(allCves);
|
|
56
|
+
const scanDuration = Date.now() - startTime;
|
|
57
|
+
const totalDependencies = allDependencies.reduce((a, b) => a + b, 0);
|
|
58
|
+
|
|
59
|
+
const report = await this.reportBuilder.buildReport(
|
|
60
|
+
rootPath,
|
|
61
|
+
allCves,
|
|
62
|
+
riskScore,
|
|
63
|
+
scanDuration,
|
|
64
|
+
totalDependencies
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Add metadata about scanned locations
|
|
68
|
+
(report as any).scanned_locations = scannedLocations;
|
|
69
|
+
|
|
70
|
+
await this.reportBuilder.saveReport(report);
|
|
71
|
+
|
|
72
|
+
return report;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Recursive scan failed: ${
|
|
76
|
+
error instanceof Error ? error.message : String(error)
|
|
77
|
+
}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
21
82
|
async scan(repoPath: string): Promise<Report> {
|
|
22
83
|
const startTime = Date.now();
|
|
23
84
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readdir } from "fs/promises";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
|
|
4
|
+
export interface PackageJsonLocation {
|
|
5
|
+
path: string;
|
|
6
|
+
depth: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function findAllPackageJsons(
|
|
10
|
+
rootPath: string,
|
|
11
|
+
maxDepth: number = 3,
|
|
12
|
+
currentDepth: number = 0,
|
|
13
|
+
results: PackageJsonLocation[] = []
|
|
14
|
+
): Promise<PackageJsonLocation[]> {
|
|
15
|
+
if (currentDepth > maxDepth) {
|
|
16
|
+
return results;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const entries = await readdir(rootPath, { withFileTypes: true });
|
|
21
|
+
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
// Skip node_modules, .git, and other common folders
|
|
24
|
+
if (
|
|
25
|
+
entry.name.startsWith(".") ||
|
|
26
|
+
entry.name === "node_modules" ||
|
|
27
|
+
entry.name === "dist" ||
|
|
28
|
+
entry.name === "build" ||
|
|
29
|
+
entry.name === "coverage"
|
|
30
|
+
) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const fullPath = join(rootPath, entry.name);
|
|
35
|
+
|
|
36
|
+
if (entry.isFile() && entry.name === "package.json") {
|
|
37
|
+
results.push({
|
|
38
|
+
path: rootPath,
|
|
39
|
+
depth: currentDepth,
|
|
40
|
+
});
|
|
41
|
+
} else if (entry.isDirectory()) {
|
|
42
|
+
await findAllPackageJsons(fullPath, maxDepth, currentDepth + 1, results);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// Permission denied or other errors - skip
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return results;
|
|
50
|
+
}
|