@coana-tech/cli 14.12.16 → 14.12.19
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/cli.mjs +5 -5
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +136 -205
- package/repos/coana-tech/alucard/alucard.jar +0 -0
- package/repos/coana-tech/goana/bin/goana-darwin-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-darwin-arm64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-arm64.gz +0 -0
- package/repos/coana-tech/mambalade/dist/{mambalade-0.3.11-py3-none-any.whl → mambalade-0.3.12-py3-none-any.whl} +0 -0
- package/repos/coana-tech/mambalade/dist/typing_extensions-4.15.0-py3-none-any.whl +0 -0
- package/repos/coana-tech/mambalade/dist/typing_extensions-4.14.1-py3-none-any.whl +0 -0
package/cli.mjs
CHANGED
|
@@ -206082,7 +206082,7 @@ var NpmSocketUpgradeManager = class {
|
|
|
206082
206082
|
this.rootDir,
|
|
206083
206083
|
subprojectDir
|
|
206084
206084
|
);
|
|
206085
|
-
this.applySecurityFixesForSocketArtifacts(
|
|
206085
|
+
await this.applySecurityFixesForSocketArtifacts(
|
|
206086
206086
|
subprojectDir,
|
|
206087
206087
|
fixingManager,
|
|
206088
206088
|
artifacts,
|
|
@@ -224639,7 +224639,7 @@ var CoanaSupportedVulnerabilitiesDBInterface = class _CoanaSupportedVulnerabilit
|
|
|
224639
224639
|
async upsertVulnerabilityPattern(ghsa, ecosystem, updateFields) {
|
|
224640
224640
|
const advisory = ghsa;
|
|
224641
224641
|
const _id = `${ghsa}-${ecosystem}`;
|
|
224642
|
-
return this.vulnerabilitiesSupportedCollection.updateOne(
|
|
224642
|
+
return await this.vulnerabilitiesSupportedCollection.updateOne(
|
|
224643
224643
|
{ _id },
|
|
224644
224644
|
{
|
|
224645
224645
|
$set: {
|
|
@@ -225672,7 +225672,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
|
|
|
225672
225672
|
}
|
|
225673
225673
|
|
|
225674
225674
|
// dist/version.js
|
|
225675
|
-
var version2 = "14.12.
|
|
225675
|
+
var version2 = "14.12.19";
|
|
225676
225676
|
|
|
225677
225677
|
// dist/cli-core.js
|
|
225678
225678
|
var { mapValues, omit, partition, pick } = import_lodash15.default;
|
|
@@ -226517,7 +226517,7 @@ async function computeFixesAndUpgradePurls(path2, options, logFile) {
|
|
|
226517
226517
|
if (computedFix.type !== "success") {
|
|
226518
226518
|
throw new Error(`No fix found for the given vulnerabilities`);
|
|
226519
226519
|
}
|
|
226520
|
-
const ghsasFailedToFix =
|
|
226520
|
+
const ghsasFailedToFix = Object.keys(ghsaToVulnerableArtifactIdsToApply).filter((ghsa) => {
|
|
226521
226521
|
const artifactIds = ghsaToVulnerableArtifactIdsToApply[ghsa];
|
|
226522
226522
|
if (!artifactIds)
|
|
226523
226523
|
return false;
|
|
@@ -226550,7 +226550,7 @@ async function computeFixesAndUpgradePurls(path2, options, logFile) {
|
|
|
226550
226550
|
concurrency: "1",
|
|
226551
226551
|
globPattern: options.globPattern,
|
|
226552
226552
|
rangeStyle: options.rangeStyle
|
|
226553
|
-
}, autofixRunId) ?? "fixed-all";
|
|
226553
|
+
}, void 0, autofixRunId) ?? "fixed-all";
|
|
226554
226554
|
if (autofixRunId) {
|
|
226555
226555
|
await getSocketAPI().finalizeAutofixRun(autofixRunId, ghsasFailedToFix.length === 0 && applyFixesStatus === "fixed-all" ? "fixed-all" : ghsasFailedToFix.length === Object.keys(ghsaToVulnerableArtifactIdsToApply).length || applyFixesStatus === "fixed-none" ? "fixed-none" : "fixed-some");
|
|
226556
226556
|
}
|
package/package.json
CHANGED
|
@@ -73725,12 +73725,6 @@ async function asyncForEach(array, fn, concurrency = 1) {
|
|
|
73725
73725
|
}
|
|
73726
73726
|
await Promise.all(Array.from({ length: concurrency }, async () => worker()));
|
|
73727
73727
|
}
|
|
73728
|
-
async function applySeries(arr, fn) {
|
|
73729
|
-
let i2 = 0;
|
|
73730
|
-
for (const item of arr) {
|
|
73731
|
-
await fn(item, i2++);
|
|
73732
|
-
}
|
|
73733
|
-
}
|
|
73734
73728
|
async function asyncFilter(arr, predicate, concurrency = 1) {
|
|
73735
73729
|
const results = await asyncMap(arr, predicate, concurrency);
|
|
73736
73730
|
return arr.filter((_v, index2) => results[index2]);
|
|
@@ -74383,20 +74377,6 @@ async function withTmpDirectory(prefix, fn, deleteTmpDir = true) {
|
|
|
74383
74377
|
|
|
74384
74378
|
// ../web-compat-utils/src/vuln-chain-detail-utils.ts
|
|
74385
74379
|
var ROOT_NODE_STR = "";
|
|
74386
|
-
function computeParentsMap(d) {
|
|
74387
|
-
const parentsMap = /* @__PURE__ */ new Map();
|
|
74388
|
-
const addToMap = (children2, id) => {
|
|
74389
|
-
children2?.forEach((dep) => {
|
|
74390
|
-
if (!parentsMap.has(dep)) parentsMap.set(dep, []);
|
|
74391
|
-
parentsMap.get(dep).push(id);
|
|
74392
|
-
});
|
|
74393
|
-
};
|
|
74394
|
-
for (const [id, node] of Object.entries(d.transitiveDependencies)) {
|
|
74395
|
-
addToMap(node.children, id);
|
|
74396
|
-
}
|
|
74397
|
-
addToMap(d.children, ROOT_NODE_STR);
|
|
74398
|
-
return parentsMap;
|
|
74399
|
-
}
|
|
74400
74380
|
|
|
74401
74381
|
// dist/whole-program-code-aware-vulnerability-scanner/code-aware-vulnerability-scanner.js
|
|
74402
74382
|
var import_lodash13 = __toESM(require_lodash(), 1);
|
|
@@ -88577,130 +88557,6 @@ async function convertSocketArtifacts2(artifacts, tmpDir) {
|
|
|
88577
88557
|
return deps;
|
|
88578
88558
|
}
|
|
88579
88559
|
|
|
88580
|
-
// dist/whole-program-code-aware-vulnerability-scanner/js/jelly-runner.js
|
|
88581
|
-
var import_lodash9 = __toESM(require_lodash(), 1);
|
|
88582
|
-
import { readFile as readFile7, rm as rm2, writeFile as writeFile5 } from "fs/promises";
|
|
88583
|
-
import { relative as relative4, resolve as resolve6 } from "path";
|
|
88584
|
-
var { map: map2, uniq: uniq4 } = import_lodash9.default;
|
|
88585
|
-
var PRINT_JELLY_COMMAND = false;
|
|
88586
|
-
async function runJellyAnalysis(mainProjectRoot, projectRoot, jellyOptions, reachabilityAnalysisOptions, vulnerabilities, experiment) {
|
|
88587
|
-
const tmpFolder = await createTmpDirectory("jelly-analysis");
|
|
88588
|
-
try {
|
|
88589
|
-
const filesToAnalyze = reachabilityAnalysisOptions.entryPoints ? reachabilityAnalysisOptions.entryPoints : [projectRoot];
|
|
88590
|
-
const jellyExecutable = resolve6(COANA_REPOS_PATH(), "jelly-private", "dist", "bundle", "jelly.js");
|
|
88591
|
-
const vulnerabilitiesInJellyFormat = vulnerabilities.map((v) => ({
|
|
88592
|
-
osv: v,
|
|
88593
|
-
patterns: v.vulnerabilityAccessPaths.map((p) => experiment === "AUGMENT_IMPORT_PATHS_EXPERIMENT" ? p.replace(">", "/**>") : p)
|
|
88594
|
-
// Repalce > with /**> to ensure Jelly also matches call <PKG/dist/index.js>.foo for pattern <PKG>.foo
|
|
88595
|
-
}));
|
|
88596
|
-
const vulnerabilitiesFile = resolve6(tmpFolder, "vulnerabilities.json");
|
|
88597
|
-
const diagnosticsFile = resolve6(tmpFolder, "diagnostics.json");
|
|
88598
|
-
const matchesFile = resolve6(tmpFolder, "matches.json");
|
|
88599
|
-
const callStackFile = resolve6(tmpFolder, "call-stacks.json");
|
|
88600
|
-
const logFile = reachabilityAnalysisOptions.analysisLogFile ?? (reachabilityAnalysisOptions.printLogFile && resolve6(projectRoot, "js-analysis.log"));
|
|
88601
|
-
await writeFile5(vulnerabilitiesFile, JSON.stringify(vulnerabilitiesInJellyFormat));
|
|
88602
|
-
let excludeEntries;
|
|
88603
|
-
if (reachabilityAnalysisOptions.excludeDirs?.length) {
|
|
88604
|
-
const excludeDirsRelativeToProjectRoot = reachabilityAnalysisOptions.excludeDirs.map((d) => relative4(projectRoot, resolve6(mainProjectRoot, d)));
|
|
88605
|
-
const excludeDirsRelativeToProjectRootWithWildcards = excludeDirsRelativeToProjectRoot.map((d) => `${d}/**`);
|
|
88606
|
-
excludeEntries = [...excludeDirsRelativeToProjectRoot, ...excludeDirsRelativeToProjectRootWithWildcards];
|
|
88607
|
-
}
|
|
88608
|
-
const jellyCmd = [
|
|
88609
|
-
"node",
|
|
88610
|
-
`--max-old-space-size=${reachabilityAnalysisOptions.memoryLimitInMB ?? 8192}`,
|
|
88611
|
-
jellyExecutable,
|
|
88612
|
-
"--basedir",
|
|
88613
|
-
mainProjectRoot,
|
|
88614
|
-
"--timeout",
|
|
88615
|
-
"" + (reachabilityAnalysisOptions.timeoutInSeconds ?? 60),
|
|
88616
|
-
"--vulnerabilities",
|
|
88617
|
-
vulnerabilitiesFile,
|
|
88618
|
-
...excludeEntries ? ["--exclude-entries", ...excludeEntries] : [],
|
|
88619
|
-
"--diagnostics-json",
|
|
88620
|
-
diagnosticsFile,
|
|
88621
|
-
...jellyOptions.maxIndirections ? ["--max-indirections", "" + jellyOptions.maxIndirections] : [],
|
|
88622
|
-
...jellyOptions.includePackages ? ["--include-packages", ...jellyOptions.includePackages] : [],
|
|
88623
|
-
...jellyOptions.approx ? ["--approx"] : [],
|
|
88624
|
-
...logFile ? ["--logfile", logFile] : [],
|
|
88625
|
-
"--matches-file",
|
|
88626
|
-
matchesFile,
|
|
88627
|
-
"--vulnerabilities-callstacks",
|
|
88628
|
-
callStackFile,
|
|
88629
|
-
...filesToAnalyze
|
|
88630
|
-
];
|
|
88631
|
-
if (PRINT_JELLY_COMMAND)
|
|
88632
|
-
logger.info("Jelly command:", jellyCmd.join(" "));
|
|
88633
|
-
await runCommandResolveStdOut(
|
|
88634
|
-
jellyCmd,
|
|
88635
|
-
void 0,
|
|
88636
|
-
// If it is an experimental run, make sure to crash the process if Jelly takes more than 50% longer than the timeout.
|
|
88637
|
-
// This is done to mitigate the scenario where the Jelly process gets close to the memory limit and thus ends up spending most of its time on garbage collection, which can increase the time between timeout checks dramatically.
|
|
88638
|
-
experiment && reachabilityAnalysisOptions.timeoutInSeconds ? { timeout: reachabilityAnalysisOptions.timeoutInSeconds * 1e3 * 1.5 } : void 0
|
|
88639
|
-
);
|
|
88640
|
-
if (reachabilityAnalysisOptions.printLogFile)
|
|
88641
|
-
logger.info("JS analysis log file:", await readFile7(logFile, "utf-8"));
|
|
88642
|
-
const analysisDiagnostics = JSON.parse(await readFile7(diagnosticsFile, "utf-8"));
|
|
88643
|
-
analysisDiagnostics.time = analysisDiagnostics.analysisTime;
|
|
88644
|
-
delete analysisDiagnostics.analysisTime;
|
|
88645
|
-
analysisDiagnostics.timings = {
|
|
88646
|
-
analysisTime: analysisDiagnostics.time,
|
|
88647
|
-
patternMatchingTime: analysisDiagnostics.patternMatchingTime
|
|
88648
|
-
};
|
|
88649
|
-
const callStacks = JSON.parse(await readFile7(callStackFile, "utf-8"));
|
|
88650
|
-
const matches = {};
|
|
88651
|
-
for (const { vulnerability, paths } of callStacks) {
|
|
88652
|
-
const transformedStacks = transformJellyCallStacks(projectRoot, paths);
|
|
88653
|
-
if (matches[vulnerability.osv.url]) {
|
|
88654
|
-
matches[vulnerability.osv.url].stacks.push(...transformedStacks.stacks);
|
|
88655
|
-
} else
|
|
88656
|
-
matches[vulnerability.osv.url] = transformedStacks;
|
|
88657
|
-
}
|
|
88658
|
-
return {
|
|
88659
|
-
matches,
|
|
88660
|
-
analysisDiagnostics
|
|
88661
|
-
};
|
|
88662
|
-
} finally {
|
|
88663
|
-
await rm2(tmpFolder, { recursive: true });
|
|
88664
|
-
}
|
|
88665
|
-
}
|
|
88666
|
-
async function runJellyPhantomDependencyAnalysis(projectRoot) {
|
|
88667
|
-
const tmpFolder = await createTmpDirectory("jelly-analysis");
|
|
88668
|
-
try {
|
|
88669
|
-
const jellyExecutable = resolve6(COANA_REPOS_PATH(), "jelly-private", "dist", "bundle", "jelly.js");
|
|
88670
|
-
const reachablePackagesFile = resolve6(tmpFolder, "reachable-packages.json");
|
|
88671
|
-
const jellyCmd = [
|
|
88672
|
-
"node",
|
|
88673
|
-
jellyExecutable,
|
|
88674
|
-
"--basedir",
|
|
88675
|
-
projectRoot,
|
|
88676
|
-
"--modules-only",
|
|
88677
|
-
"--ignore-dependencies",
|
|
88678
|
-
"--reachable-packages-file",
|
|
88679
|
-
reachablePackagesFile,
|
|
88680
|
-
projectRoot
|
|
88681
|
-
];
|
|
88682
|
-
await runCommandResolveStdOut(jellyCmd);
|
|
88683
|
-
return JSON.parse(await readFile7(reachablePackagesFile, "utf-8"));
|
|
88684
|
-
} finally {
|
|
88685
|
-
await rm2(tmpFolder, { recursive: true });
|
|
88686
|
-
}
|
|
88687
|
-
}
|
|
88688
|
-
function relativizeSourceLocations(projectDir, paths) {
|
|
88689
|
-
return {
|
|
88690
|
-
...paths,
|
|
88691
|
-
stacks: paths.stacks.map((stack) => stack.map((s2) => ({
|
|
88692
|
-
...s2,
|
|
88693
|
-
sourceLocation: { ...s2.sourceLocation, filename: relative4(projectDir, s2.sourceLocation.filename) }
|
|
88694
|
-
})))
|
|
88695
|
-
};
|
|
88696
|
-
}
|
|
88697
|
-
function transformJellyCallStacks(projectRoot, paths) {
|
|
88698
|
-
return {
|
|
88699
|
-
...relativizeSourceLocations(projectRoot, paths),
|
|
88700
|
-
affectedPackages: uniq4(paths.stacks.flatMap((stack) => map2(stack, "package")))
|
|
88701
|
-
};
|
|
88702
|
-
}
|
|
88703
|
-
|
|
88704
88560
|
// dist/whole-program-code-aware-vulnerability-scanner/js/js-code-aware-vulnerability-scanner.js
|
|
88705
88561
|
import { mkdtempSync } from "fs";
|
|
88706
88562
|
import { cp as cp3, mkdir as mkdir7, rm as rm3, writeFile as writeFile6 } from "fs/promises";
|
|
@@ -88708,11 +88564,11 @@ import { tmpdir as tmpdir2 } from "os";
|
|
|
88708
88564
|
import { join as join16 } from "path";
|
|
88709
88565
|
|
|
88710
88566
|
// dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
|
|
88711
|
-
var
|
|
88567
|
+
var import_lodash9 = __toESM(require_lodash(), 1);
|
|
88712
88568
|
import { existsSync as existsSync8 } from "fs";
|
|
88713
88569
|
import { mkdir as mkdir6, symlink } from "fs/promises";
|
|
88714
88570
|
import { availableParallelism } from "os";
|
|
88715
|
-
import { dirname as dirname9, resolve as
|
|
88571
|
+
import { dirname as dirname9, resolve as resolve7 } from "path";
|
|
88716
88572
|
|
|
88717
88573
|
// ../../node_modules/.pnpm/@isaacs+fs-minipass@4.0.1/node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
88718
88574
|
import EE from "events";
|
|
@@ -93350,7 +93206,7 @@ var mkdirpNative = Object.assign(async (path9, options) => {
|
|
|
93350
93206
|
}, { sync: mkdirpNativeSync });
|
|
93351
93207
|
|
|
93352
93208
|
// ../../node_modules/.pnpm/mkdirp@3.0.1/node_modules/mkdirp/dist/mjs/path-arg.js
|
|
93353
|
-
import { parse as parse13, resolve as
|
|
93209
|
+
import { parse as parse13, resolve as resolve6 } from "path";
|
|
93354
93210
|
var platform3 = process.env.__TESTING_MKDIRP_PLATFORM__ || process.platform;
|
|
93355
93211
|
var pathArg = (path9) => {
|
|
93356
93212
|
if (/\0/.test(path9)) {
|
|
@@ -93359,7 +93215,7 @@ var pathArg = (path9) => {
|
|
|
93359
93215
|
code: "ERR_INVALID_ARG_VALUE"
|
|
93360
93216
|
});
|
|
93361
93217
|
}
|
|
93362
|
-
path9 =
|
|
93218
|
+
path9 = resolve6(path9);
|
|
93363
93219
|
if (platform3 === "win32") {
|
|
93364
93220
|
const badWinChars = /[*|"<>?:]/;
|
|
93365
93221
|
const { root: root3 } = parse13(path9);
|
|
@@ -94704,12 +94560,12 @@ var mtimeFilter = (opt) => {
|
|
|
94704
94560
|
};
|
|
94705
94561
|
|
|
94706
94562
|
// dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
|
|
94707
|
-
var { chunk } =
|
|
94563
|
+
var { chunk } = import_lodash9.default;
|
|
94708
94564
|
async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToArtifact, directDependencies, packageNamesToInstall) {
|
|
94709
|
-
if (existsSync8(
|
|
94565
|
+
if (existsSync8(resolve7(subprojectDir, "node_modules")))
|
|
94710
94566
|
return { failedPackages: [], installedPackages: [] };
|
|
94711
94567
|
return await withTmpDirectory("npm-packages", async (tmpDir) => {
|
|
94712
|
-
const dirToInstallDependencies =
|
|
94568
|
+
const dirToInstallDependencies = resolve7(subprojectDir, "node_modules", ".jelly");
|
|
94713
94569
|
const transitiveDependenciesToInstall = Object.fromEntries(Object.entries(artifactIdToArtifact).filter(([_, dep]) => packageNamesToInstall.includes(getPackageName(dep))).map(([depId, dep]) => [depId, { ...dep }]));
|
|
94714
94570
|
const { installedPackages, failedPackages } = await downloadDependenciesToDir(Object.values(transitiveDependenciesToInstall), tmpDir);
|
|
94715
94571
|
const augmentedInstalledPackages = await extractDownloadedDependenciesToDir(dirToInstallDependencies, tmpDir, installedPackages);
|
|
@@ -94742,7 +94598,7 @@ async function downloadDependenciesToDir(dependenciesToInstall, tmpDir) {
|
|
|
94742
94598
|
})}`, tmpDir);
|
|
94743
94599
|
const npmPackRes = JSON.parse(stdout);
|
|
94744
94600
|
chunk2.forEach((dep, idx) => {
|
|
94745
|
-
dep.tarFileName =
|
|
94601
|
+
dep.tarFileName = resolve7(tmpDir, npmPackRes[idx].filename);
|
|
94746
94602
|
});
|
|
94747
94603
|
installedPackages.push(...chunk2);
|
|
94748
94604
|
} catch (e) {
|
|
@@ -94771,8 +94627,8 @@ function getPackageName(dep) {
|
|
|
94771
94627
|
}
|
|
94772
94628
|
async function extractDownloadedDependenciesToDir(dirToInstallDependencies, tmpDir, dependenciesToInstall) {
|
|
94773
94629
|
return await asyncMap(dependenciesToInstall, async (dep) => {
|
|
94774
|
-
const tgzPath =
|
|
94775
|
-
const dependencyDir =
|
|
94630
|
+
const tgzPath = resolve7(tmpDir, dep.tarFileName);
|
|
94631
|
+
const dependencyDir = resolve7(dirToInstallDependencies, `${dep.version ? `${getPackageName(dep)}@${dep.version}` : getPackageName(dep)}`.replace("/", "+"), "node_modules", "aliasName" in dep && dep.aliasName ? dep.aliasName : getPackageName(dep));
|
|
94776
94632
|
await mkdir6(dependencyDir, { recursive: true });
|
|
94777
94633
|
await extract({ file: tgzPath, cwd: dependencyDir, stripComponents: 1 });
|
|
94778
94634
|
dep.installedPath = dependencyDir;
|
|
@@ -94787,7 +94643,7 @@ async function createSymlinksForDependenciesInRootDir(workspaceDir, dependencies
|
|
|
94787
94643
|
const aliasName = "aliasName" in dependencyToInstall ? dependencyToInstall.aliasName : void 0;
|
|
94788
94644
|
if (directDependencyNameToInfo[packageName] && directDependencyNameToInfo[packageName].version !== version3)
|
|
94789
94645
|
continue;
|
|
94790
|
-
const pathToCreateSymlinkFrom =
|
|
94646
|
+
const pathToCreateSymlinkFrom = resolve7(workspaceDir, "node_modules", aliasName ?? packageName);
|
|
94791
94647
|
if (existsSync8(pathToCreateSymlinkFrom))
|
|
94792
94648
|
continue;
|
|
94793
94649
|
await mkdir6(dirname9(pathToCreateSymlinkFrom), { recursive: true });
|
|
@@ -94801,7 +94657,7 @@ async function createSymlinksForEachDependency(dependencyInfosForDependenciesToI
|
|
|
94801
94657
|
const pathToCreateSymlinkTo = dep.installedPath;
|
|
94802
94658
|
if (!existsSync8(pathToCreateSymlinkTo))
|
|
94803
94659
|
continue;
|
|
94804
|
-
const pathToCreateSymlinkFrom =
|
|
94660
|
+
const pathToCreateSymlinkFrom = resolve7(depInfo.installedPath, "..", "aliasName" in dep && dep.aliasName !== void 0 ? dep.aliasName : getPackageName(dep));
|
|
94805
94661
|
if (existsSync8(pathToCreateSymlinkFrom))
|
|
94806
94662
|
continue;
|
|
94807
94663
|
await mkdir6(dirname9(pathToCreateSymlinkFrom), { recursive: true });
|
|
@@ -94928,6 +94784,122 @@ function computePackagesOnVulnPathExcludingVulnerablePackage(vulnerabilities) {
|
|
|
94928
94784
|
return [...packagesToAnalyze];
|
|
94929
94785
|
}
|
|
94930
94786
|
|
|
94787
|
+
// dist/whole-program-code-aware-vulnerability-scanner/js/jelly-runner.js
|
|
94788
|
+
var import_lodash10 = __toESM(require_lodash(), 1);
|
|
94789
|
+
import { readFile as readFile7, rm as rm2, writeFile as writeFile5 } from "fs/promises";
|
|
94790
|
+
import { relative as relative4, resolve as resolve8 } from "path";
|
|
94791
|
+
var { map: map2, uniq: uniq4 } = import_lodash10.default;
|
|
94792
|
+
var PRINT_JELLY_COMMAND = false;
|
|
94793
|
+
async function runJellyAnalysis(mainProjectRoot, projectRoot, jellyOptions, reachabilityAnalysisOptions, vulnerabilities, experiment) {
|
|
94794
|
+
const tmpFolder = await createTmpDirectory("jelly-analysis");
|
|
94795
|
+
try {
|
|
94796
|
+
const filesToAnalyze = reachabilityAnalysisOptions.entryPoints ? reachabilityAnalysisOptions.entryPoints : [projectRoot];
|
|
94797
|
+
const jellyExecutable = resolve8(COANA_REPOS_PATH(), "jelly-private", "dist", "bundle", "jelly.js");
|
|
94798
|
+
const vulnerabilitiesInJellyFormat = vulnerabilities.map((v) => ({
|
|
94799
|
+
osv: v,
|
|
94800
|
+
patterns: v.vulnerabilityAccessPaths.map((p) => experiment === "AUGMENT_IMPORT_PATHS_EXPERIMENT" ? p.replace(">", "/**>") : p)
|
|
94801
|
+
// Replace > with /**> to ensure Jelly also matches call <PKG/dist/index.js>.foo for pattern <PKG>.foo
|
|
94802
|
+
}));
|
|
94803
|
+
const vulnerabilitiesFile = resolve8(tmpFolder, "vulnerabilities.json");
|
|
94804
|
+
const diagnosticsFile = resolve8(tmpFolder, "diagnostics.json");
|
|
94805
|
+
const matchesFile = resolve8(tmpFolder, "matches.json");
|
|
94806
|
+
const callStackFile = resolve8(tmpFolder, "call-stacks.json");
|
|
94807
|
+
const logFile = reachabilityAnalysisOptions.analysisLogFile ?? (reachabilityAnalysisOptions.printLogFile && resolve8(projectRoot, "js-analysis.log"));
|
|
94808
|
+
await writeFile5(vulnerabilitiesFile, JSON.stringify(vulnerabilitiesInJellyFormat));
|
|
94809
|
+
let excludeEntries;
|
|
94810
|
+
if (reachabilityAnalysisOptions.excludeDirs?.length) {
|
|
94811
|
+
const excludeDirsRelativeToProjectRoot = reachabilityAnalysisOptions.excludeDirs.map((d) => relative4(projectRoot, resolve8(mainProjectRoot, d)));
|
|
94812
|
+
const excludeDirsRelativeToProjectRootWithWildcards = excludeDirsRelativeToProjectRoot.map((d) => `${d}/**`);
|
|
94813
|
+
excludeEntries = [...excludeDirsRelativeToProjectRoot, ...excludeDirsRelativeToProjectRootWithWildcards];
|
|
94814
|
+
}
|
|
94815
|
+
const jellyCmd = [
|
|
94816
|
+
"node",
|
|
94817
|
+
`--max-old-space-size=${reachabilityAnalysisOptions.memoryLimitInMB ?? 8192}`,
|
|
94818
|
+
jellyExecutable,
|
|
94819
|
+
"--basedir",
|
|
94820
|
+
mainProjectRoot,
|
|
94821
|
+
"--timeout",
|
|
94822
|
+
"" + (reachabilityAnalysisOptions.timeoutInSeconds ?? 60),
|
|
94823
|
+
"--vulnerabilities",
|
|
94824
|
+
vulnerabilitiesFile,
|
|
94825
|
+
...excludeEntries ? ["--exclude-entries", ...excludeEntries] : [],
|
|
94826
|
+
"--diagnostics-json",
|
|
94827
|
+
diagnosticsFile,
|
|
94828
|
+
...jellyOptions.maxIndirections ? ["--max-indirections", "" + jellyOptions.maxIndirections] : [],
|
|
94829
|
+
...jellyOptions.includePackages ? ["--include-packages", ...jellyOptions.includePackages] : [],
|
|
94830
|
+
...jellyOptions.approx ? ["--approx"] : [],
|
|
94831
|
+
...logFile ? ["--logfile", logFile] : [],
|
|
94832
|
+
"--matches-file",
|
|
94833
|
+
matchesFile,
|
|
94834
|
+
"--vulnerabilities-callstacks",
|
|
94835
|
+
callStackFile,
|
|
94836
|
+
...filesToAnalyze
|
|
94837
|
+
];
|
|
94838
|
+
if (PRINT_JELLY_COMMAND)
|
|
94839
|
+
logger.info("Jelly command:", jellyCmd.join(" "));
|
|
94840
|
+
await runCommandResolveStdOut(
|
|
94841
|
+
jellyCmd,
|
|
94842
|
+
void 0,
|
|
94843
|
+
// If it is an experimental run, make sure to crash the process if Jelly takes more than 50% longer than the timeout.
|
|
94844
|
+
// This is done to mitigate the scenario where the Jelly process gets close to the memory limit and thus ends up spending most of its time on garbage collection, which can increase the time between timeout checks dramatically.
|
|
94845
|
+
experiment && reachabilityAnalysisOptions.timeoutInSeconds ? { timeout: reachabilityAnalysisOptions.timeoutInSeconds * 1e3 * 1.5 } : void 0
|
|
94846
|
+
);
|
|
94847
|
+
if (reachabilityAnalysisOptions.printLogFile)
|
|
94848
|
+
logger.info("JS analysis log file:", await readFile7(logFile, "utf-8"));
|
|
94849
|
+
const analysisDiagnostics = JSON.parse(await readFile7(diagnosticsFile, "utf-8"));
|
|
94850
|
+
analysisDiagnostics.time = analysisDiagnostics.analysisTime;
|
|
94851
|
+
delete analysisDiagnostics.analysisTime;
|
|
94852
|
+
analysisDiagnostics.timings = {
|
|
94853
|
+
analysisTime: analysisDiagnostics.time,
|
|
94854
|
+
patternMatchingTime: analysisDiagnostics.patternMatchingTime
|
|
94855
|
+
};
|
|
94856
|
+
const callStacks = JSON.parse(await readFile7(callStackFile, "utf-8"));
|
|
94857
|
+
const matches = {};
|
|
94858
|
+
for (const { vulnerability, paths } of callStacks) {
|
|
94859
|
+
const transformedStacks = transformJellyCallStacks(projectRoot, paths);
|
|
94860
|
+
if (matches[vulnerability.osv.url]) {
|
|
94861
|
+
matches[vulnerability.osv.url].stacks.push(...transformedStacks.stacks);
|
|
94862
|
+
} else
|
|
94863
|
+
matches[vulnerability.osv.url] = transformedStacks;
|
|
94864
|
+
}
|
|
94865
|
+
return {
|
|
94866
|
+
matches,
|
|
94867
|
+
analysisDiagnostics
|
|
94868
|
+
};
|
|
94869
|
+
} finally {
|
|
94870
|
+
await rm2(tmpFolder, { recursive: true });
|
|
94871
|
+
}
|
|
94872
|
+
}
|
|
94873
|
+
async function runJellyPhantomDependencyAnalysis(projectRoot, options) {
|
|
94874
|
+
const tmpFolder = await createTmpDirectory("jelly-analysis");
|
|
94875
|
+
try {
|
|
94876
|
+
const jellyExecutable = resolve8(COANA_REPOS_PATH(), "jelly-private", "dist", "bundle", "jelly.js");
|
|
94877
|
+
const reachablePackagesFile = resolve8(tmpFolder, "reachable-packages.json");
|
|
94878
|
+
const jellyCmd = cmdt`node --max-old-space-size=${options.memoryLimitInMB}
|
|
94879
|
+
${jellyExecutable} --basedir ${projectRoot} --modules-only --ignore-dependencies
|
|
94880
|
+
--reachable-packages-file ${reachablePackagesFile} ${projectRoot}`;
|
|
94881
|
+
await runCommandResolveStdOut(jellyCmd);
|
|
94882
|
+
return JSON.parse(await readFile7(reachablePackagesFile, "utf-8"));
|
|
94883
|
+
} finally {
|
|
94884
|
+
await rm2(tmpFolder, { recursive: true });
|
|
94885
|
+
}
|
|
94886
|
+
}
|
|
94887
|
+
function relativizeSourceLocations(projectDir, paths) {
|
|
94888
|
+
return {
|
|
94889
|
+
...paths,
|
|
94890
|
+
stacks: paths.stacks.map((stack) => stack.map((s2) => ({
|
|
94891
|
+
...s2,
|
|
94892
|
+
sourceLocation: { ...s2.sourceLocation, filename: relative4(projectDir, s2.sourceLocation.filename) }
|
|
94893
|
+
})))
|
|
94894
|
+
};
|
|
94895
|
+
}
|
|
94896
|
+
function transformJellyCallStacks(projectRoot, paths) {
|
|
94897
|
+
return {
|
|
94898
|
+
...relativizeSourceLocations(projectRoot, paths),
|
|
94899
|
+
affectedPackages: uniq4(paths.stacks.flatMap((stack) => map2(stack, "package")))
|
|
94900
|
+
};
|
|
94901
|
+
}
|
|
94902
|
+
|
|
94931
94903
|
// dist/whole-program-code-aware-vulnerability-scanner/js/js-code-aware-vulnerability-scanner.js
|
|
94932
94904
|
var JSCodeAwareVulnerabilityScanner = class _JSCodeAwareVulnerabilityScanner {
|
|
94933
94905
|
mainProjectDir;
|
|
@@ -94969,7 +94941,7 @@ var JSCodeAwareVulnerabilityScanner = class _JSCodeAwareVulnerabilityScanner {
|
|
|
94969
94941
|
computeDetectedOccurrences: ({ url: url2 }) => transformSourceLocations3(matches[url2] ?? [])
|
|
94970
94942
|
};
|
|
94971
94943
|
} catch (e) {
|
|
94972
|
-
logger.
|
|
94944
|
+
logger.debug("Error while running analysis: ", e.stack);
|
|
94973
94945
|
return { type: "error", message: e.message };
|
|
94974
94946
|
} finally {
|
|
94975
94947
|
this.numberAnalysesRun++;
|
|
@@ -96575,10 +96547,13 @@ ${errors.join("\n")}`);
|
|
|
96575
96547
|
var trunc = trunc2;
|
|
96576
96548
|
const exc = e;
|
|
96577
96549
|
msg = util5.format("Error running mambalade:\n%O\nStdout:\n%s\nStderr:\n%s", pick(exc, ["code", "signal"]), trunc2(exc.stdout), trunc2(exc.stderr));
|
|
96578
|
-
if (exc.signal ?? (exc.stderr.endsWith("MemoryError\n") || exc.stderr.includes("OSError: [Errno 12] Cannot allocate memory")))
|
|
96550
|
+
if (exc.signal ?? (exc.stderr.endsWith("MemoryError\n") || exc.stderr.includes("OSError: [Errno 12] Cannot allocate memory"))) {
|
|
96579
96551
|
msg = `Mambalade ran out of memory:
|
|
96580
96552
|
${msg}`;
|
|
96581
|
-
|
|
96553
|
+
logger.debug(msg);
|
|
96554
|
+
} else {
|
|
96555
|
+
logger.error(msg);
|
|
96556
|
+
}
|
|
96582
96557
|
} else
|
|
96583
96558
|
logger.error("Unexpected error:", e);
|
|
96584
96559
|
return { type: "error", message: msg };
|
|
@@ -97449,9 +97424,9 @@ var NpmAnalyzer = class {
|
|
|
97449
97424
|
}
|
|
97450
97425
|
async runPhantomDependencyAnalysis() {
|
|
97451
97426
|
try {
|
|
97452
|
-
return (await runJellyPhantomDependencyAnalysis(this.projectDir)).map((r) => r.name);
|
|
97427
|
+
return (await runJellyPhantomDependencyAnalysis(this.projectDir, this.state.reachabilityAnalysisOptions)).map((r) => r.name);
|
|
97453
97428
|
} catch (e) {
|
|
97454
|
-
|
|
97429
|
+
logger.debug("Error while running jelly phantom dependency analysis: ", e);
|
|
97455
97430
|
}
|
|
97456
97431
|
}
|
|
97457
97432
|
async runReachabilityAnalysis(vulns, analysisMetadataCollector, statusUpdater) {
|
|
@@ -97518,46 +97493,6 @@ var RustAnalyzer = class {
|
|
|
97518
97493
|
}
|
|
97519
97494
|
};
|
|
97520
97495
|
|
|
97521
|
-
// dist/apply-precomputed-reachability-results.js
|
|
97522
|
-
async function addPrecomputedResultsToVulnerabilities(analyzer, vulnerabilities) {
|
|
97523
|
-
const phantomDependencies = await analyzer.runPhantomDependencyAnalysis();
|
|
97524
|
-
if (!phantomDependencies)
|
|
97525
|
-
return;
|
|
97526
|
-
await applySeries(vulnerabilities, async (v) => {
|
|
97527
|
-
const dismissVulnerability = canDismissVulnerability(phantomDependencies, v.vulnChainDetails);
|
|
97528
|
-
v.unreachableByPrecomputation = dismissVulnerability ? "YES" : "NO";
|
|
97529
|
-
});
|
|
97530
|
-
}
|
|
97531
|
-
function canDismissVulnerability(phantomDependencies, vulnChainDetails) {
|
|
97532
|
-
const parentsMap = computeParentsMap(vulnChainDetails);
|
|
97533
|
-
const [vulnNodeIdentifier] = Object.entries(vulnChainDetails.transitiveDependencies).find(([_identifier, node]) => node.vulnerable);
|
|
97534
|
-
let canDismiss = true;
|
|
97535
|
-
const recHelper = (nodeIdentifier, depth) => {
|
|
97536
|
-
if (depth === 0)
|
|
97537
|
-
return void 0;
|
|
97538
|
-
const parents3 = parentsMap.get(nodeIdentifier).filter((parent2) => parent2 !== ROOT_NODE_STR);
|
|
97539
|
-
const thisReachabilityPrecomp = nodeIdentifier === vulnNodeIdentifier ? "Reachable" : vulnChainDetails.transitiveDependencies[nodeIdentifier].reachabilityPrecomp;
|
|
97540
|
-
if (!thisReachabilityPrecomp)
|
|
97541
|
-
return void 0;
|
|
97542
|
-
const thisMayReachVulnerableNode = ["Reachable", "Unknown"].includes(thisReachabilityPrecomp);
|
|
97543
|
-
if (parents3.length === 0 && thisMayReachVulnerableNode) {
|
|
97544
|
-
canDismiss = false;
|
|
97545
|
-
}
|
|
97546
|
-
if (parents3) {
|
|
97547
|
-
const parentsReachabilityPrecomp = parents3.map((p) => recHelper(p, depth - 1));
|
|
97548
|
-
if (parentsReachabilityPrecomp.some((reachabilityPrecomp) => !reachabilityPrecomp) && thisMayReachVulnerableNode) {
|
|
97549
|
-
canDismiss = false;
|
|
97550
|
-
}
|
|
97551
|
-
}
|
|
97552
|
-
if (thisMayReachVulnerableNode && phantomDependencies.includes(nodeIdentifier)) {
|
|
97553
|
-
canDismiss = false;
|
|
97554
|
-
}
|
|
97555
|
-
return thisReachabilityPrecomp;
|
|
97556
|
-
};
|
|
97557
|
-
recHelper(vulnNodeIdentifier, 5);
|
|
97558
|
-
return canDismiss;
|
|
97559
|
-
}
|
|
97560
|
-
|
|
97561
97496
|
// dist/main.js
|
|
97562
97497
|
var { partition: partition3 } = import_lodash19.default;
|
|
97563
97498
|
var ecosystemAnalyzer = {
|
|
@@ -97578,10 +97513,6 @@ async function runReachabilityAnalysis(state) {
|
|
|
97578
97513
|
if (!constructor)
|
|
97579
97514
|
throw Error(`No analyzer associated with ecosystem ${ecosystem}`);
|
|
97580
97515
|
const analyzer = new constructor(state, projectDir);
|
|
97581
|
-
try {
|
|
97582
|
-
await addPrecomputedResultsToVulnerabilities(analyzer, state.vulnerabilities);
|
|
97583
|
-
} catch (e) {
|
|
97584
|
-
}
|
|
97585
97516
|
const [vulnerabilitiesWithPrecomputedResults, vulnerabilitiesWithoutPrecomputedResults] = partition3(state.vulnerabilities, (v) => "results" in v);
|
|
97586
97517
|
const augmentedVulnerabilities = await runWholeProgramCodeAwareVulnerabilityScanner(analyzer, vulnerabilitiesWithoutPrecomputedResults, async (amd) => {
|
|
97587
97518
|
await dashboardAPI2.registerAnalysisMetadata(relative6(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, state.workspaceData.data.type, amd, COANA_REPORT_ID, apiKey2);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
index e8523d7..c76daad 100644
|
|
|
Binary file
|