pompelmi 0.35.0 → 0.35.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/dist/pompelmi.browser.cjs +45 -58
- package/dist/pompelmi.browser.cjs.map +1 -1
- package/dist/pompelmi.browser.esm.js +45 -58
- package/dist/pompelmi.browser.esm.js.map +1 -1
- package/dist/pompelmi.cjs +52 -61
- package/dist/pompelmi.cjs.map +1 -1
- package/dist/pompelmi.esm.js +52 -61
- package/dist/pompelmi.esm.js.map +1 -1
- package/dist/pompelmi.react.cjs +45 -58
- package/dist/pompelmi.react.cjs.map +1 -1
- package/dist/pompelmi.react.esm.js +45 -58
- package/dist/pompelmi.react.esm.js.map +1 -1
- package/package.json +2 -2
package/dist/pompelmi.esm.js
CHANGED
|
@@ -979,7 +979,7 @@ function composeScanners(...args) {
|
|
|
979
979
|
const all = [];
|
|
980
980
|
if (opts.parallel) {
|
|
981
981
|
// Parallel execution — collect all results then return
|
|
982
|
-
const results = await Promise.allSettled(entries.map(([
|
|
982
|
+
const results = await Promise.allSettled(entries.map(([_name, scanner]) => runWithTimeout(() => toScanFn(scanner)(input, ctx), opts.timeoutMsPerScanner)));
|
|
983
983
|
for (let i = 0; i < results.length; i++) {
|
|
984
984
|
const result = results[i];
|
|
985
985
|
if (result.status === "fulfilled" && Array.isArray(result.value)) {
|
|
@@ -1033,75 +1033,62 @@ function composeScanners(...args) {
|
|
|
1033
1033
|
};
|
|
1034
1034
|
}
|
|
1035
1035
|
function createPresetScanner(preset, opts = {}) {
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
scanners.push(CommonHeuristicsScanner);
|
|
1036
|
+
const baseScanners = [CommonHeuristicsScanner];
|
|
1037
|
+
const dynamicScannerPromises = [];
|
|
1039
1038
|
// Add decompilation scanners based on preset
|
|
1040
1039
|
if (preset === "decompilation-basic" ||
|
|
1041
1040
|
preset === "decompilation-deep" ||
|
|
1042
1041
|
preset === "malware-analysis" ||
|
|
1043
1042
|
opts.enableDecompilation) {
|
|
1044
|
-
const depth = preset === "decompilation-deep"
|
|
1043
|
+
const depth = preset === "decompilation-deep" || preset === "malware-analysis"
|
|
1045
1044
|
? "deep"
|
|
1046
1045
|
: preset === "decompilation-basic"
|
|
1047
1046
|
? "basic"
|
|
1048
1047
|
: opts.decompilationDepth || "basic";
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
// Dynamic import to avoid bundling issues - using Function to bypass TypeScript type checking
|
|
1054
|
-
const importModule = new Function("specifier", "return import(specifier)");
|
|
1055
|
-
importModule("@pompelmi/engine-binaryninja")
|
|
1056
|
-
.then((mod) => {
|
|
1057
|
-
const binjaScanner = mod.createBinaryNinjaScanner({
|
|
1058
|
-
timeout: opts.decompilationTimeout || opts.timeout || 30000,
|
|
1059
|
-
depth,
|
|
1060
|
-
pythonPath: opts.pythonPath,
|
|
1061
|
-
binaryNinjaPath: opts.binaryNinjaPath,
|
|
1062
|
-
});
|
|
1063
|
-
scanners.push(binjaScanner);
|
|
1064
|
-
})
|
|
1065
|
-
.catch(() => {
|
|
1066
|
-
// Binary Ninja engine not available - silently skip
|
|
1067
|
-
});
|
|
1068
|
-
}
|
|
1069
|
-
catch {
|
|
1070
|
-
// Engine not installed
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
if (!opts.decompilationEngine ||
|
|
1074
|
-
opts.decompilationEngine === "ghidra-pcode" ||
|
|
1075
|
-
opts.decompilationEngine === "both") {
|
|
1076
|
-
try {
|
|
1077
|
-
// Dynamic import for Ghidra engine (when implemented) - using Function to bypass TypeScript type checking
|
|
1078
|
-
const importModule = new Function("specifier", "return import(specifier)");
|
|
1079
|
-
importModule("@pompelmi/engine-ghidra")
|
|
1080
|
-
.then((mod) => {
|
|
1081
|
-
const ghidraScanner = mod.createGhidraScanner({
|
|
1082
|
-
timeout: opts.decompilationTimeout || opts.timeout || 30000,
|
|
1083
|
-
depth,
|
|
1084
|
-
ghidraPath: opts.ghidraPath,
|
|
1085
|
-
analyzeHeadless: opts.analyzeHeadless,
|
|
1086
|
-
});
|
|
1087
|
-
scanners.push(ghidraScanner);
|
|
1088
|
-
})
|
|
1089
|
-
.catch(() => {
|
|
1090
|
-
// Ghidra engine not available - silently skip
|
|
1091
|
-
});
|
|
1092
|
-
}
|
|
1093
|
-
catch {
|
|
1094
|
-
// Engine not installed
|
|
1095
|
-
}
|
|
1048
|
+
let importModule;
|
|
1049
|
+
try {
|
|
1050
|
+
// Dynamic import to avoid bundling issues - using Function to bypass TypeScript type checking
|
|
1051
|
+
importModule = new Function("specifier", "return import(specifier)");
|
|
1096
1052
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1053
|
+
catch {
|
|
1054
|
+
importModule = undefined;
|
|
1055
|
+
}
|
|
1056
|
+
if (importModule &&
|
|
1057
|
+
(!opts.decompilationEngine ||
|
|
1058
|
+
opts.decompilationEngine === "binaryninja-hlil" ||
|
|
1059
|
+
opts.decompilationEngine === "both")) {
|
|
1060
|
+
dynamicScannerPromises.push(importModule("@pompelmi/engine-binaryninja")
|
|
1061
|
+
.then((mod) => mod.createBinaryNinjaScanner({
|
|
1062
|
+
timeout: opts.decompilationTimeout || opts.timeout || 30000,
|
|
1063
|
+
depth,
|
|
1064
|
+
pythonPath: opts.pythonPath,
|
|
1065
|
+
binaryNinjaPath: opts.binaryNinjaPath,
|
|
1066
|
+
}))
|
|
1067
|
+
.catch(() => null));
|
|
1068
|
+
}
|
|
1069
|
+
if (importModule &&
|
|
1070
|
+
(!opts.decompilationEngine ||
|
|
1071
|
+
opts.decompilationEngine === "ghidra-pcode" ||
|
|
1072
|
+
opts.decompilationEngine === "both")) {
|
|
1073
|
+
dynamicScannerPromises.push(importModule("@pompelmi/engine-ghidra")
|
|
1074
|
+
.then((mod) => mod.createGhidraScanner({
|
|
1075
|
+
timeout: opts.decompilationTimeout || opts.timeout || 30000,
|
|
1076
|
+
depth,
|
|
1077
|
+
ghidraPath: opts.ghidraPath,
|
|
1078
|
+
analyzeHeadless: opts.analyzeHeadless,
|
|
1079
|
+
}))
|
|
1080
|
+
.catch(() => null));
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
let composedScannerPromise;
|
|
1084
|
+
const getComposedScanner = async () => {
|
|
1085
|
+
composedScannerPromise ?? (composedScannerPromise = Promise.all(dynamicScannerPromises).then((dynamicScanners) => composeScanners(...baseScanners, ...dynamicScanners.filter((scanner) => scanner !== null))));
|
|
1086
|
+
return composedScannerPromise;
|
|
1087
|
+
};
|
|
1088
|
+
return async (input, ctx) => {
|
|
1089
|
+
const scanner = await getComposedScanner();
|
|
1090
|
+
return scanner(input, ctx);
|
|
1091
|
+
};
|
|
1105
1092
|
}
|
|
1106
1093
|
|
|
1107
1094
|
/**
|
|
@@ -1993,10 +1980,14 @@ class BatchScanner {
|
|
|
1993
1980
|
processingQueue.push(promise);
|
|
1994
1981
|
currentIndex++;
|
|
1995
1982
|
// Remove completed promises from queue
|
|
1996
|
-
promise
|
|
1983
|
+
promise
|
|
1984
|
+
.finally(() => {
|
|
1997
1985
|
const idx = processingQueue.indexOf(promise);
|
|
1998
1986
|
if (idx > -1)
|
|
1999
1987
|
processingQueue.splice(idx, 1);
|
|
1988
|
+
})
|
|
1989
|
+
.catch(() => {
|
|
1990
|
+
// Rejections are handled by the main queue waits; swallow the cleanup chain.
|
|
2000
1991
|
});
|
|
2001
1992
|
}
|
|
2002
1993
|
// Wait for at least one task to complete before continuing
|