-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.ts
108 lines (93 loc) · 3.48 KB
/
App.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import fs from "fs/promises";
import path from "path";
import { secretsPatterns } from "./patterns/SecretsPatterns";
import { urlPattern } from "./patterns/UrlPatterns";
import MatchingRule from "./rules/MatchingRule";
import UnpackingService from "./services/UnpackingService";
import type { AnalysisResult } from "./models/AnalysisResult";
import { parseArgs, usage } from "./utils/CliUtil";
import AnalysisService from "./services/AnalysisService";
import { allowedExtensions } from "./constants/FileExtensions";
async function performAnalysis(
filePaths: string[],
outputDirPath: string,
rulesConfig: { [ruleName: string]: boolean }
): Promise<void> {
const matchingRules: MatchingRule[] = [
new MatchingRule("endpoints", urlPattern),
new MatchingRule("secrets", secretsPatterns),
];
const fileData = [];
for (const filePath of filePaths) {
try {
const content = await fs.readFile(filePath, "utf8");
fileData.push({ filePath, fileContent: content });
} catch (error) {
console.error(`Failed to read file ${filePath}:`, error);
continue; // Skip files that cannot be read
}
}
const analysisService = new AnalysisService();
let results = [];
try {
results = await analysisService.run(fileData, matchingRules, rulesConfig);
console.log(JSON.stringify(results, null, 2));
} catch (error) {
console.error('Error during analysis:', error);
return; // Optionally, handle more gracefully depending on requirements
}
try {
await fs.mkdir(outputDirPath, { recursive: true });
const outputPath = path.join(outputDirPath, "analysisResults.json");
await fs.writeFile(outputPath, JSON.stringify(results, null, 2), "utf8");
} catch (error) {
console.error('Failed to write analysis results:', error);
}
}
async function getAllFiles(
dirPath: string,
arrayOfFiles: string[] = []
): Promise<string[]> {
const entries = await fs.readdir(dirPath, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name);
if (entry.isDirectory()) {
await getAllFiles(fullPath, arrayOfFiles);
} else if (
entry.isFile() &&
allowedExtensions.some((ext) => entry.name.endsWith(ext))
) {
arrayOfFiles.push(fullPath);
}
}
return arrayOfFiles;
}
async function main() {
const options = parseArgs(process.argv.slice(2));
if (!options.targetPath) {
usage();
return;
}
try {
const stat = await fs.stat(options.targetPath);
let filePaths = stat.isDirectory() ? await getAllFiles(options.targetPath) : [options.targetPath];
const processedFiles = await Promise.all(filePaths.map(async (filePath) => {
console.log(`Processing ${path.basename(filePath)}...`);
const unpackingService = new UnpackingService(filePath, options.unpackOutputDirPath);
if (options.unpack || options.deobfuscate || options.unminify) {
const unpackedPath = await unpackingService.unpack(options);
if (unpackedPath && (await fs.stat(unpackedPath)).isFile()) {
return unpackedPath; // Use the unpacked file path if valid
} else {
console.warn(`Skipping non-file path post-processing: ${unpackedPath}`);
return null; // Skip this path
}
}
return filePath; // Use the original path if no processing needed
}));
await performAnalysis(filePaths, options.unpackOutputDirPath, options.rules);
} catch (error) {
console.error("An error occurred in main:", error);
}
}
main();