@coana-tech/cli 14.12.201 → 15.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/cli.mjs +342 -58
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +244 -83
- 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/javap-service/javap-service.jar +0 -0
|
@@ -79900,6 +79900,16 @@ var ApiUrls = {
|
|
|
79900
79900
|
}
|
|
79901
79901
|
};
|
|
79902
79902
|
|
|
79903
|
+
// ../web-compat-utils/src/analysis-error-keys.ts
|
|
79904
|
+
var FAILED_TO_INSTALL_PACKAGE_KEY = "[UNABLE_TO_INSTALL_PACKAGE_ERROR]: ";
|
|
79905
|
+
var InstallError = class extends Error {
|
|
79906
|
+
constructor(failedPackages) {
|
|
79907
|
+
super(`Failed to install packages: ${failedPackages.join(", ")}`);
|
|
79908
|
+
this.failedPackages = failedPackages;
|
|
79909
|
+
this.name = "InstallError";
|
|
79910
|
+
}
|
|
79911
|
+
};
|
|
79912
|
+
|
|
79903
79913
|
// ../web-compat-utils/src/maven-dependency-utils.ts
|
|
79904
79914
|
function deserializeMavenDependency(s2) {
|
|
79905
79915
|
const [groupId, artifactId, version3] = s2.split(":");
|
|
@@ -88108,9 +88118,6 @@ var PromiseQueue = class {
|
|
|
88108
88118
|
}
|
|
88109
88119
|
};
|
|
88110
88120
|
|
|
88111
|
-
// ../web-compat-utils/src/analysis-error-keys.ts
|
|
88112
|
-
var FAILED_TO_INSTALL_PACKAGE_KEY = "[UNABLE_TO_INSTALL_PACKAGE_ERROR]: ";
|
|
88113
|
-
|
|
88114
88121
|
// ../web-compat-utils/src/ghsa.ts
|
|
88115
88122
|
function extractGHSAIdFromUrl(url2) {
|
|
88116
88123
|
const match2 = url2.match(/(GHSA-[a-z0-9-]+)/);
|
|
@@ -88151,6 +88158,7 @@ function getVulnReachability(c) {
|
|
|
88151
88158
|
// dist/analyzers/pip-analyzer.js
|
|
88152
88159
|
var import_lodash16 = __toESM(require_lodash(), 1);
|
|
88153
88160
|
import assert7 from "assert";
|
|
88161
|
+
import { existsSync as existsSync15 } from "fs";
|
|
88154
88162
|
import { resolve as resolve19 } from "path";
|
|
88155
88163
|
|
|
88156
88164
|
// ../utils/src/pip-utils.ts
|
|
@@ -88571,8 +88579,8 @@ function addPathToTrie(root3, vulnPath) {
|
|
|
88571
88579
|
// dist/whole-program-code-aware-vulnerability-scanner/python/python-code-aware-vulnerability-scanner.js
|
|
88572
88580
|
var import_lodash14 = __toESM(require_lodash(), 1);
|
|
88573
88581
|
import assert6 from "assert";
|
|
88574
|
-
import { existsSync as
|
|
88575
|
-
import { cp as cp7, readdir as
|
|
88582
|
+
import { existsSync as existsSync14 } from "fs";
|
|
88583
|
+
import { cp as cp7, readdir as readdir6, readFile as readFile12, rm as rm5 } from "fs/promises";
|
|
88576
88584
|
var import_semver3 = __toESM(require_semver2(), 1);
|
|
88577
88585
|
import { basename as basename11, dirname as dirname15, join as join17, resolve as resolve17, sep as sep5 } from "path";
|
|
88578
88586
|
import util5 from "util";
|
|
@@ -95565,7 +95573,7 @@ var prereleaseSpecifierNormalization = {
|
|
|
95565
95573
|
};
|
|
95566
95574
|
var postreleaseSpecifiers = ["post", "rev", "r"];
|
|
95567
95575
|
var devReleaseSpecifiers = ["dev"];
|
|
95568
|
-
var epochRegex = /(\d+)
|
|
95576
|
+
var epochRegex = /(\d+)!/;
|
|
95569
95577
|
var releaseSegmentRegex = /(\d+(?:\.\d+)*)/;
|
|
95570
95578
|
var prereleaseRegex = buildRegexWithSpecifier(prereleaseSpecifiers);
|
|
95571
95579
|
var postreleaseRegex = buildRegexWithSpecifier(postreleaseSpecifiers);
|
|
@@ -110508,7 +110516,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
|
|
|
110508
110516
|
if (result.error)
|
|
110509
110517
|
return void 0;
|
|
110510
110518
|
const packageIds = JSON.parse(await readFile8(outputFile, "utf-8")).result;
|
|
110511
|
-
return packageIds?.map((packageId) => this.depIdToPurl.get(packageId)).filter((purl) => purl !== void 0).map((purl) => `${purl.namespace}:${purl.name}
|
|
110519
|
+
return packageIds?.map((packageId) => this.depIdToPurl.get(packageId)).filter((purl) => purl !== void 0).map((purl) => `${purl.namespace}:${purl.name}`);
|
|
110512
110520
|
});
|
|
110513
110521
|
}
|
|
110514
110522
|
async runAnalysis(vulnerabilities, heuristic, timeoutInSeconds, _experiment, telemetryHandler, analyzerTelemetryHandler) {
|
|
@@ -110518,7 +110526,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
|
|
|
110518
110526
|
const packagesToAnalyzeSet = new Set(packagesToAnalyze);
|
|
110519
110527
|
const filteredDeps = !packagesToAnalyze ? this.deps : Object.fromEntries(Object.entries(this.deps).filter(([packageId]) => {
|
|
110520
110528
|
const purl = this.depIdToPurl.get(packageId);
|
|
110521
|
-
return purl && packagesToAnalyzeSet.has(`${purl.namespace}:${purl.name}
|
|
110529
|
+
return purl && packagesToAnalyzeSet.has(`${purl.namespace}:${purl.name}`);
|
|
110522
110530
|
}));
|
|
110523
110531
|
return await this.actuallyRunAnalysis(vulnerabilities.flatMap((v) => v.vulnerabilityAccessPaths), timeoutInSeconds, filteredDeps, telemetryHandler, analyzerTelemetryHandler);
|
|
110524
110532
|
} catch (e) {
|
|
@@ -110591,7 +110599,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
|
|
|
110591
110599
|
};
|
|
110592
110600
|
}
|
|
110593
110601
|
getPackagesExcludedUnrelatedToHeuristic() {
|
|
110594
|
-
return Object.entries(this.deps).filter(([_, { src, bin }]) => !src?.length && (!bin || bin.some((f2) => !existsSync9(f2)))).map(([packageId]) => this.depIdToPurl.get(packageId)).filter((purl) => purl !== void 0).map((purl) => `${purl.namespace}:${purl.name}
|
|
110602
|
+
return Object.entries(this.deps).filter(([_, { src, bin }]) => !src?.length && (!bin || bin.some((f2) => !existsSync9(f2)))).map(([packageId]) => this.depIdToPurl.get(packageId)).filter((purl) => purl !== void 0).map((purl) => `${purl.namespace}:${purl.name}`);
|
|
110595
110603
|
}
|
|
110596
110604
|
};
|
|
110597
110605
|
async function convertDependencyChain2(dependencyChain, tmpDir) {
|
|
@@ -110660,6 +110668,9 @@ async function convertSocketArtifacts2(rootDir, artifacts, tmpDir) {
|
|
|
110660
110668
|
}
|
|
110661
110669
|
}
|
|
110662
110670
|
}
|
|
110671
|
+
const artifactFile = getPathToArtifact(tmpDir, groupId, artifactId, type, classifier, version3);
|
|
110672
|
+
if (existsSync9(artifactFile))
|
|
110673
|
+
return artifactFile;
|
|
110663
110674
|
if (mavenInstalled && pomFile) {
|
|
110664
110675
|
try {
|
|
110665
110676
|
const dependencyGetCmd = cmdt`mvn -f=${basename8(resolve10(rootDir, pomFile))} dependency:get -DgroupId=${groupId} -DartifactId=${artifactId} -Dpackaging=${type} -Dclassifier${classifier} -Dversion=${version3} -Dtransitive=false`;
|
|
@@ -110670,7 +110681,6 @@ async function convertSocketArtifacts2(rootDir, artifacts, tmpDir) {
|
|
|
110670
110681
|
} catch {
|
|
110671
110682
|
}
|
|
110672
110683
|
}
|
|
110673
|
-
const artifactFile = getPathToArtifact(tmpDir, groupId, artifactId, type, classifier, version3);
|
|
110674
110684
|
await mkdir6(dirname11(artifactFile), { recursive: true });
|
|
110675
110685
|
const success = await resolveMavenArtifactFromStandardRepositories(groupId, artifactId, type, classifier, version3, artifactFile);
|
|
110676
110686
|
return success ? artifactFile : void 0;
|
|
@@ -110722,21 +110732,41 @@ import { tmpdir as tmpdir4 } from "os";
|
|
|
110722
110732
|
import { join as join15 } from "path";
|
|
110723
110733
|
|
|
110724
110734
|
// dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
|
|
110725
|
-
import { existsSync as
|
|
110735
|
+
import { existsSync as existsSync11 } from "fs";
|
|
110726
110736
|
import { resolve as resolve12 } from "path";
|
|
110727
110737
|
|
|
110728
110738
|
// dist/whole-program-code-aware-vulnerability-scanner/js/setup-npm-dependencies-for-analysis.js
|
|
110729
110739
|
var import_lodash9 = __toESM(require_lodash(), 1);
|
|
110730
|
-
import {
|
|
110740
|
+
import { existsSync as existsSync10 } from "fs";
|
|
110741
|
+
import { link, mkdir as mkdir7, readdir as readdir5 } from "fs/promises";
|
|
110731
110742
|
import { availableParallelism } from "os";
|
|
110732
110743
|
import { dirname as dirname12, join as join14, resolve as resolve11 } from "path";
|
|
110733
110744
|
var { chunk } = import_lodash9.default;
|
|
110734
110745
|
var ROOT_PACKAGE_METADATA_NAME = "UNIQUE_ROOT_PACKAGE_METADATA_NAME";
|
|
110735
|
-
async function setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, artifactIdToArtifact) {
|
|
110746
|
+
async function setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, artifactIdToArtifact, preinstallDir) {
|
|
110736
110747
|
return await withTmpDirectory("npm-packages", async (tmpDir) => {
|
|
110737
110748
|
const dirToInstallDependencies = resolve11(subprojectDir, "node_modules", ".jelly");
|
|
110738
|
-
|
|
110739
|
-
|
|
110749
|
+
let installedPackages;
|
|
110750
|
+
let failedPackages;
|
|
110751
|
+
if (preinstallDir && existsSync10(preinstallDir)) {
|
|
110752
|
+
const existingFiles = await readdir5(preinstallDir);
|
|
110753
|
+
installedPackages = [];
|
|
110754
|
+
failedPackages = [];
|
|
110755
|
+
for (const artifact of Object.values(artifactIdToArtifact)) {
|
|
110756
|
+
const tarballName = artifact.name.replace("@", "").replace("/", "-");
|
|
110757
|
+
const expectedFilename = artifact.version ? `${tarballName}-${artifact.version}.tgz` : void 0;
|
|
110758
|
+
const matchingTgz = existingFiles.find((f2) => expectedFilename ? f2 === expectedFilename : f2.endsWith(".tgz") && f2.startsWith(tarballName + "-"));
|
|
110759
|
+
if (matchingTgz) {
|
|
110760
|
+
installedPackages.push({ artifact, tarFileName: resolve11(preinstallDir, matchingTgz) });
|
|
110761
|
+
} else {
|
|
110762
|
+
failedPackages.push(artifact);
|
|
110763
|
+
}
|
|
110764
|
+
}
|
|
110765
|
+
logger.debug(`Reusing ${installedPackages.length} pre-installed tarballs from ${preinstallDir}`);
|
|
110766
|
+
} else {
|
|
110767
|
+
({ installedPackages, failedPackages } = await downloadDependenciesToDir(Object.values(artifactIdToArtifact), tmpDir));
|
|
110768
|
+
}
|
|
110769
|
+
const augmentedInstalledPackages = await extractDownloadedDependenciesToDir(dirToInstallDependencies, preinstallDir ?? tmpDir, installedPackages);
|
|
110740
110770
|
const packageMetadatas = convertToPackageMetadatas(workspaceDir, augmentedInstalledPackages, directDependencies, artifactIdToArtifact);
|
|
110741
110771
|
const packagePlacements = computePackagePlacements(packageMetadatas, resolve11(subprojectDir, "node_modules"));
|
|
110742
110772
|
await hardlinkPackages(packagePlacements);
|
|
@@ -111041,8 +111071,8 @@ function tarjanAndCondensation(packageMetadatas) {
|
|
|
111041
111071
|
}
|
|
111042
111072
|
|
|
111043
111073
|
// dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
|
|
111044
|
-
async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToArtifact, directDependencies, packageNamesToInstall) {
|
|
111045
|
-
if (
|
|
111074
|
+
async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToArtifact, directDependencies, packageNamesToInstall, preinstallDir) {
|
|
111075
|
+
if (existsSync11(resolve12(subprojectDir, "node_modules")))
|
|
111046
111076
|
return { failedPackages: [], installedPackages: [] };
|
|
111047
111077
|
const artifactToOriginal = /* @__PURE__ */ new Map();
|
|
111048
111078
|
const transitiveDependenciesToInstall = Object.fromEntries(Object.entries(artifactIdToArtifact).filter(([_, dep]) => packageNamesToInstall.includes(getPackageName(dep))).map(([depId, dep]) => {
|
|
@@ -111050,7 +111080,7 @@ async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToA
|
|
|
111050
111080
|
artifactToOriginal.set(artifact, dep);
|
|
111051
111081
|
return [depId, artifact];
|
|
111052
111082
|
}));
|
|
111053
|
-
const result = await setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, transitiveDependenciesToInstall);
|
|
111083
|
+
const result = await setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, transitiveDependenciesToInstall, preinstallDir);
|
|
111054
111084
|
return {
|
|
111055
111085
|
failedPackages: result.failedPackages.map((artifact) => artifactToOriginal.get(artifact)),
|
|
111056
111086
|
installedPackages: result.installedPackages.map((artifact) => artifactToOriginal.get(artifact))
|
|
@@ -111070,6 +111100,11 @@ function convertToArtifactForInstallation(dep) {
|
|
|
111070
111100
|
dependencies: dep.dependencies
|
|
111071
111101
|
};
|
|
111072
111102
|
}
|
|
111103
|
+
async function validateNpmDependencyDownloads(artifactIdToArtifact, packageNamesToInstall, preinstallDir) {
|
|
111104
|
+
const artifacts = Object.entries(artifactIdToArtifact).filter(([_, dep]) => packageNamesToInstall.includes(getPackageName(dep))).map(([_, dep]) => convertToArtifactForInstallation(dep));
|
|
111105
|
+
const { failedPackages } = await downloadDependenciesToDir(artifacts, preinstallDir);
|
|
111106
|
+
return failedPackages.map((p) => p.name);
|
|
111107
|
+
}
|
|
111073
111108
|
|
|
111074
111109
|
// dist/whole-program-code-aware-vulnerability-scanner/js/heuristics.js
|
|
111075
111110
|
var lazyIndirectionBoundOptions = {
|
|
@@ -111333,7 +111368,7 @@ var JSCodeAwareVulnerabilityScanner = class _JSCodeAwareVulnerabilityScanner {
|
|
|
111333
111368
|
...new Set(state.vulnerabilities.flatMap((v) => Object.values(v.vulnChainDetails?.transitiveDependencies ?? {}).filter((d) => d.vulnerable === true).map((d) => d.packageName)))
|
|
111334
111369
|
];
|
|
111335
111370
|
const packagesToInstall = !includePackages ? state.workspaceData.type === "coana" ? Object.values(state.workspaceData.data.dependencyTree.transitiveDependencies).map((dep) => getPackageName(dep)) : state.workspaceData.data.artifacts.map((dep) => getPackageName(dep)) : [.../* @__PURE__ */ new Set([...includePackages, ...vulnerablePackageNames])];
|
|
111336
|
-
const { failedPackages } = await prepareNpmDependencies(state.rootWorkingDir, this.projectDir, state.workspaceData.type === "coana" ? state.workspaceData.data.dependencyTree.transitiveDependencies : Object.fromEntries(state.workspaceData.data.artifacts.map((d) => [d.id, d])), state.workspaceData.type === "coana" ? state.workspaceData.data.dependencyTree.dependencies ?? [] : state.workspaceData.data.artifacts.filter((a2) => a2.direct).map((a2) => a2.id), packagesToInstall);
|
|
111371
|
+
const { failedPackages } = await prepareNpmDependencies(state.rootWorkingDir, this.projectDir, state.workspaceData.type === "coana" ? state.workspaceData.data.dependencyTree.transitiveDependencies : Object.fromEntries(state.workspaceData.data.artifacts.map((d) => [d.id, d])), state.workspaceData.type === "coana" ? state.workspaceData.data.dependencyTree.dependencies ?? [] : state.workspaceData.data.artifacts.filter((a2) => a2.direct).map((a2) => a2.id), packagesToInstall, state.preinstallDir);
|
|
111337
111372
|
this.packagesExcludedUnrelatedToHeuristic = failedPackages.map((p) => getPackageName(p));
|
|
111338
111373
|
}
|
|
111339
111374
|
async runAnalysis(vulnerabilities, heuristic, timeoutInSeconds, experiment, telemetryHandler, analyzerTelemetryHandler) {
|
|
@@ -111487,7 +111522,7 @@ function transformSourceLocations(fileMappings, detectedOccurrences) {
|
|
|
111487
111522
|
// dist/whole-program-code-aware-vulnerability-scanner/go/go-code-aware-vulnerability-scanner.js
|
|
111488
111523
|
var import_lodash11 = __toESM(require_lodash(), 1);
|
|
111489
111524
|
import assert5 from "assert";
|
|
111490
|
-
import { existsSync as
|
|
111525
|
+
import { existsSync as existsSync12, createReadStream as createReadStream2, createWriteStream as createWriteStream4 } from "fs";
|
|
111491
111526
|
import { readFile as readFile10, rm as rm4, cp as cp6 } from "fs/promises";
|
|
111492
111527
|
import zlib2 from "zlib";
|
|
111493
111528
|
import { join as join16, resolve as resolve14, sep as sep3 } from "path";
|
|
@@ -111526,7 +111561,7 @@ var GoCodeAwareVulnerabilityScanner = class {
|
|
|
111526
111561
|
}
|
|
111527
111562
|
async runAnalysis(vulns, heuristic, timeoutInSeconds, _experiment, telemetryHandler, analyzerTelemetryHandler) {
|
|
111528
111563
|
logger.info("Started instantiating Go code-aware analysis");
|
|
111529
|
-
if (!
|
|
111564
|
+
if (!existsSync12(join16(this.projectDir, "go.mod")))
|
|
111530
111565
|
throw new Error("go.mod file not found in the project directory");
|
|
111531
111566
|
const { memoryLimitInMB } = this.options;
|
|
111532
111567
|
const tmpDir = await createTmpDirectory("goana-output");
|
|
@@ -111607,7 +111642,7 @@ ${stderr}`);
|
|
|
111607
111642
|
try {
|
|
111608
111643
|
await cp6(Dir, projectDir, { recursive: true });
|
|
111609
111644
|
const projGoMod = resolve14(projectDir, "go.mod");
|
|
111610
|
-
if (!
|
|
111645
|
+
if (!existsSync12(projGoMod))
|
|
111611
111646
|
await cp6(GoMod, projGoMod);
|
|
111612
111647
|
await exec2(cmdt`chmod --recursive +w ${projectDir}`);
|
|
111613
111648
|
await runGoModTidy(projectDir);
|
|
@@ -111635,7 +111670,7 @@ ${stderr}`);
|
|
|
111635
111670
|
}
|
|
111636
111671
|
static async runOnAlreadyDownloadedPackages(packages, vuln, options) {
|
|
111637
111672
|
for (const pkg of packages)
|
|
111638
|
-
assert5(
|
|
111673
|
+
assert5(existsSync12(join16(pkg, "go.mod")), `${pkg} does not contain a go.mod file`);
|
|
111639
111674
|
const [app, ...dependencies] = packages;
|
|
111640
111675
|
const projectDir = await createTmpDirectory("go-run-on-already-downloaded-packages-");
|
|
111641
111676
|
try {
|
|
@@ -111666,6 +111701,8 @@ ${stderr}`);
|
|
|
111666
111701
|
await rm4(projectDir, { recursive: true, force: true });
|
|
111667
111702
|
}
|
|
111668
111703
|
}
|
|
111704
|
+
// Go dependencies are auto-installed during the reachability analysis process
|
|
111705
|
+
// (e.g. by `go build`), so there are no pre-install failures to track here.
|
|
111669
111706
|
getPackagesExcludedUnrelatedToHeuristic() {
|
|
111670
111707
|
return [];
|
|
111671
111708
|
}
|
|
@@ -111673,7 +111710,7 @@ ${stderr}`);
|
|
|
111673
111710
|
|
|
111674
111711
|
// dist/whole-program-code-aware-vulnerability-scanner/rust/rust-code-aware-vulnerability-scanner.js
|
|
111675
111712
|
var import_lodash12 = __toESM(require_lodash(), 1);
|
|
111676
|
-
import { existsSync as
|
|
111713
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
111677
111714
|
import { readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
|
|
111678
111715
|
import { basename as basename10, dirname as dirname14, resolve as resolve15 } from "node:path";
|
|
111679
111716
|
|
|
@@ -111774,7 +111811,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
|
|
|
111774
111811
|
let appCrateName;
|
|
111775
111812
|
const appSrc = [];
|
|
111776
111813
|
const dependencies = {};
|
|
111777
|
-
const appCrateInfo =
|
|
111814
|
+
const appCrateInfo = existsSync13(cargoTomlPath) ? await getCrateInfo(cargoTomlPath) : void 0;
|
|
111778
111815
|
if (appCrateInfo?.name) {
|
|
111779
111816
|
appSrc.push(...i([appCrateInfo.lib, ...appCrateInfo.examples ?? [], ...appCrateInfo.tests ?? []]));
|
|
111780
111817
|
appCrateName = appCrateInfo.name.replaceAll("-", "_");
|
|
@@ -111886,7 +111923,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
|
|
|
111886
111923
|
const appDependencies = {};
|
|
111887
111924
|
if (rustDependencyChain[0].src && rustDependencyChain[0].src.length > 0) {
|
|
111888
111925
|
const appCargoTomlPath = resolve15(rustDependencyChain[0].src[0], "..", "Cargo.toml");
|
|
111889
|
-
if (
|
|
111926
|
+
if (existsSync13(appCargoTomlPath)) {
|
|
111890
111927
|
const cargoTomlDeps = await extractDependenciesFromCargoToml(appCargoTomlPath);
|
|
111891
111928
|
for (const [packageName, names] of cargoTomlDeps.entries()) {
|
|
111892
111929
|
const depId = packageNameToId.get(packageName);
|
|
@@ -111913,7 +111950,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
|
|
|
111913
111950
|
const dependencies = {};
|
|
111914
111951
|
if (dep.src && dep.src.length > 0) {
|
|
111915
111952
|
const depCargoTomlPath = resolve15(dep.src[0], "..", "Cargo.toml");
|
|
111916
|
-
if (
|
|
111953
|
+
if (existsSync13(depCargoTomlPath)) {
|
|
111917
111954
|
const cargoTomlDeps = await extractDependenciesFromCargoToml(depCargoTomlPath);
|
|
111918
111955
|
for (const [packageName, names] of cargoTomlDeps.entries()) {
|
|
111919
111956
|
const transDepId = packageNameToId.get(packageName);
|
|
@@ -112042,7 +112079,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
|
|
|
112042
112079
|
};
|
|
112043
112080
|
}
|
|
112044
112081
|
getPackagesExcludedUnrelatedToHeuristic() {
|
|
112045
|
-
return Object.entries(this.deps).filter(([_, { src, bin }]) => !src?.length && (!bin || bin.some((f2) => !
|
|
112082
|
+
return Object.entries(this.deps).filter(([_, { src, bin }]) => !src?.length && (!bin || bin.some((f2) => !existsSync13(f2)))).map(([packageId]) => this.depIdToPurl.get(packageId)?.name).filter((name2) => name2 !== void 0).map((name2) => name2);
|
|
112046
112083
|
}
|
|
112047
112084
|
};
|
|
112048
112085
|
async function convertDependencyChain3(dependencyChain, tmpDir) {
|
|
@@ -112074,7 +112111,7 @@ function getCargoLocalRepositoryPaths() {
|
|
|
112074
112111
|
// Cargo git dependencies
|
|
112075
112112
|
{ path: resolve15(cargoHome, "git", "checkouts"), type: "git" }
|
|
112076
112113
|
];
|
|
112077
|
-
return repositories.filter((repo) =>
|
|
112114
|
+
return repositories.filter((repo) => existsSync13(repo.path));
|
|
112078
112115
|
}
|
|
112079
112116
|
async function findCargoPackageInLocalRepo(repo, packageName, version3, tmpDir) {
|
|
112080
112117
|
try {
|
|
@@ -112114,10 +112151,10 @@ async function findCargoPackageInLocalRepo(repo, packageName, version3, tmpDir)
|
|
|
112114
112151
|
}
|
|
112115
112152
|
async function extractCargoCrate(crateFilePath, packageName, version3, tmpDir) {
|
|
112116
112153
|
const packageDir = resolve15(tmpDir, `${packageName}-${version3}`);
|
|
112117
|
-
if (
|
|
112154
|
+
if (existsSync13(packageDir)) {
|
|
112118
112155
|
try {
|
|
112119
112156
|
const cargoTomlPath = resolve15(packageDir, "Cargo.toml");
|
|
112120
|
-
if (
|
|
112157
|
+
if (existsSync13(cargoTomlPath)) {
|
|
112121
112158
|
const depCrateInfo = await getCrateInfo(cargoTomlPath);
|
|
112122
112159
|
return [depCrateInfo.lib];
|
|
112123
112160
|
}
|
|
@@ -112137,7 +112174,7 @@ async function extractCargoCrate(crateFilePath, packageName, version3, tmpDir) {
|
|
|
112137
112174
|
}
|
|
112138
112175
|
async function downloadAndExtractCargoCrate(packageName, version3, tmpDir) {
|
|
112139
112176
|
const packageFile = resolve15(tmpDir, `${packageName}-${version3}.crate`);
|
|
112140
|
-
if (!
|
|
112177
|
+
if (!existsSync13(packageFile)) {
|
|
112141
112178
|
const packageUrl = getUrlForCrate(packageName, version3);
|
|
112142
112179
|
const success = await downloadFile(packageUrl, packageFile);
|
|
112143
112180
|
if (!success) {
|
|
@@ -112170,7 +112207,7 @@ async function convertSocketArtifacts3(artifacts, tmpDir, artifactNameToId) {
|
|
|
112170
112207
|
const dependencies = {};
|
|
112171
112208
|
if (src && src.length > 0) {
|
|
112172
112209
|
const cargoTomlPath = resolve15(dirname14(src[0]), "Cargo.toml");
|
|
112173
|
-
if (
|
|
112210
|
+
if (existsSync13(cargoTomlPath)) {
|
|
112174
112211
|
const cargoTomlDeps = await extractDependenciesFromCargoToml(cargoTomlPath);
|
|
112175
112212
|
for (const [packageName, names] of cargoTomlDeps.entries()) {
|
|
112176
112213
|
const depArtifactId = artifactNameToId.get(packageName);
|
|
@@ -112443,12 +112480,12 @@ var PythonCodeAwareVulnerabilityScanner = class {
|
|
|
112443
112480
|
this.projectDir = projectDir;
|
|
112444
112481
|
this.vm = new PythonVersionsManager(state.rootWorkingDir);
|
|
112445
112482
|
}
|
|
112446
|
-
async prepareDependencies(preInstalledDepInfos, vulns, heuristic) {
|
|
112483
|
+
async prepareDependencies(preInstalledDepInfos, vulns, heuristic, preinstallDir) {
|
|
112447
112484
|
const packagesToExclude = heuristic.getPackagesToExcludeFromAnalysis?.(vulns);
|
|
112448
112485
|
const packagesToInstall = uniqBy(preInstalledDepInfos.filter((n) => !packagesToExclude?.has(n.packageName)), "packageName");
|
|
112449
|
-
if (!await this.tryUsingPreinstalledVirtualEnv(packagesToInstall)) {
|
|
112486
|
+
if (!await this.tryUsingPreinstalledVirtualEnv(packagesToInstall) && !(preinstallDir && await this.tryUsingVenvFromPreinstallDir(preinstallDir))) {
|
|
112450
112487
|
logger.info(`Setting up virtual environment`);
|
|
112451
|
-
await this.prepareVirtualEnv(packagesToInstall);
|
|
112488
|
+
await this.prepareVirtualEnv(packagesToInstall, preinstallDir);
|
|
112452
112489
|
logger.info("Done setting up virtual environment");
|
|
112453
112490
|
}
|
|
112454
112491
|
}
|
|
@@ -112663,7 +112700,7 @@ ${msg}`;
|
|
|
112663
112700
|
// public for testing only
|
|
112664
112701
|
async tryUsingPreinstalledVirtualEnv(packages) {
|
|
112665
112702
|
const preinstallVirtualEnvPath = resolve17(this.projectDir, ".venv");
|
|
112666
|
-
if (!
|
|
112703
|
+
if (!existsSync14(preinstallVirtualEnvPath))
|
|
112667
112704
|
return false;
|
|
112668
112705
|
logger.info(`Checking preinstalled virtual environment at ${preinstallVirtualEnvPath}`);
|
|
112669
112706
|
try {
|
|
@@ -112684,12 +112721,20 @@ ${msg}`;
|
|
|
112684
112721
|
await this.updateVirtualEnvInfo(this.projectDir);
|
|
112685
112722
|
return true;
|
|
112686
112723
|
}
|
|
112724
|
+
async tryUsingVenvFromPreinstallDir(preinstallDir) {
|
|
112725
|
+
const venvPath = join17(preinstallDir, ".venv");
|
|
112726
|
+
if (!existsSync14(venvPath))
|
|
112727
|
+
return false;
|
|
112728
|
+
logger.info(`Reusing virtual environment from pre-install at ${venvPath}`);
|
|
112729
|
+
await this.updateVirtualEnvInfo(preinstallDir);
|
|
112730
|
+
return true;
|
|
112731
|
+
}
|
|
112687
112732
|
// public for testing only
|
|
112688
|
-
async prepareVirtualEnv(packages) {
|
|
112733
|
+
async prepareVirtualEnv(packages, preinstallDir) {
|
|
112689
112734
|
const uvCommand = getUvCommand();
|
|
112690
112735
|
if (!await hasUv())
|
|
112691
112736
|
throw new Error("uv (https://docs.astral.sh/uv/) is missing, but is required for Python analysis");
|
|
112692
|
-
const tmpDir = await createTmpDirectory("coana-python-analysis-venv");
|
|
112737
|
+
const tmpDir = preinstallDir ?? await createTmpDirectory("coana-python-analysis-venv");
|
|
112693
112738
|
const virtualEnvFolder = join17(tmpDir, ".venv");
|
|
112694
112739
|
const pythonExecutable = await this.vm.getPythonExecutableForWorkspace(this.projectDir, false);
|
|
112695
112740
|
await exec2(cmdt`${uvCommand} venv --python ${pythonExecutable} .venv`, tmpDir);
|
|
@@ -112762,7 +112807,7 @@ ${msg}`;
|
|
|
112762
112807
|
await this.updateVirtualEnvInfo(tmpDir, installStats);
|
|
112763
112808
|
}
|
|
112764
112809
|
async updateVirtualEnvInfo(virtualEnvFolder, packageInstallationStats) {
|
|
112765
|
-
const entries = await
|
|
112810
|
+
const entries = await readdir6(join17(virtualEnvFolder, ".venv", "lib"));
|
|
112766
112811
|
const pydir = entries.find((entry) => entry.startsWith("python"));
|
|
112767
112812
|
assert6(pydir, `No python* directory found in virtual environment: ${util5.inspect(entries)}`);
|
|
112768
112813
|
this.virtualEnvInfo = {
|
|
@@ -112859,7 +112904,7 @@ async function setupMambalade() {
|
|
|
112859
112904
|
logger.debug(`Using Python interpreter: ${python}`);
|
|
112860
112905
|
await exec2(cmdt`${uvCommand} venv --no-project --no-config --python=${python} .`, venvDir);
|
|
112861
112906
|
const mambaladeWheelsPath = ToolPathResolver.mambaladeDistPath;
|
|
112862
|
-
const mambaladeWheels = (await
|
|
112907
|
+
const mambaladeWheels = (await readdir6(mambaladeWheelsPath)).filter((f2) => f2.endsWith(".whl")).map((f2) => join17(mambaladeWheelsPath, f2));
|
|
112863
112908
|
if (!mambaladeWheels.length)
|
|
112864
112909
|
throw new Error(`No mambalade wheel files found in ${mambaladeWheelsPath}`);
|
|
112865
112910
|
logger.debug(`Installing mambalade wheels: ${mambaladeWheels.join(", ")}`);
|
|
@@ -112995,6 +113040,13 @@ async function processProject(projectDir) {
|
|
|
112995
113040
|
}, 4)).flat());
|
|
112996
113041
|
}
|
|
112997
113042
|
|
|
113043
|
+
// dist/analyzers/analyzer.js
|
|
113044
|
+
function checkForInstallErrors(failedPackages, otherAnalysisOptions) {
|
|
113045
|
+
if (failedPackages.length > 0 && otherAnalysisOptions.haltOnInstallErrors) {
|
|
113046
|
+
throw new InstallError(failedPackages);
|
|
113047
|
+
}
|
|
113048
|
+
}
|
|
113049
|
+
|
|
112998
113050
|
// dist/analyzers/pip-analyzer.js
|
|
112999
113051
|
var { once: once4 } = import_lodash16.default;
|
|
113000
113052
|
var PipAnalyzer = class {
|
|
@@ -113013,9 +113065,16 @@ var PipAnalyzer = class {
|
|
|
113013
113065
|
this.heuristic = MambaladeHeuristics.createOnlyVulnPathPackagesHeuristic(this.preInstalledDepInfos);
|
|
113014
113066
|
}
|
|
113015
113067
|
prepareScanner = once4(async () => {
|
|
113016
|
-
await this.scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), this.heuristic);
|
|
113068
|
+
await this.scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), this.heuristic, this.state.preinstallDir);
|
|
113017
113069
|
return this.scanner;
|
|
113018
113070
|
});
|
|
113071
|
+
async installDependencies(preinstallDir) {
|
|
113072
|
+
if (existsSync15(resolve19(this.projectDir, ".venv")))
|
|
113073
|
+
return [];
|
|
113074
|
+
const scanner = new PythonCodeAwareVulnerabilityScanner(this.state, this.projectDir);
|
|
113075
|
+
await scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), this.heuristic, preinstallDir);
|
|
113076
|
+
return scanner.getPackagesExcludedUnrelatedToHeuristic();
|
|
113077
|
+
}
|
|
113019
113078
|
async runPhantomDependencyAnalysis() {
|
|
113020
113079
|
const info = (await this.prepareScanner()).getVirtualEnvInfo();
|
|
113021
113080
|
assert7(info !== void 0);
|
|
@@ -113038,6 +113097,7 @@ var PipAnalyzer = class {
|
|
|
113038
113097
|
};
|
|
113039
113098
|
try {
|
|
113040
113099
|
const scanner = await this.prepareScanner();
|
|
113100
|
+
checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
113041
113101
|
const venvInfo = scanner.getVirtualEnvInfo();
|
|
113042
113102
|
this.preinstalledDependencies = venvInfo !== void 0 && !venvInfo.temporary ? "YES" : "NO";
|
|
113043
113103
|
return await analyzeWithHeuristics(this.state, vulns, [this.heuristic], false, scanner, wrappedCollector, statusUpdater);
|
|
@@ -113514,6 +113574,15 @@ var GoAnalyzer = class {
|
|
|
113514
113574
|
this.state = state;
|
|
113515
113575
|
this.projectDir = projectDir;
|
|
113516
113576
|
}
|
|
113577
|
+
async installDependencies(_preinstallDir) {
|
|
113578
|
+
try {
|
|
113579
|
+
await runCommandResolveStdOut2(cmdt`go build ./...`, this.projectDir);
|
|
113580
|
+
return [];
|
|
113581
|
+
} catch (e) {
|
|
113582
|
+
logger.warn(`go build failed for ${this.projectDir}: ${e instanceof Error ? e.message : String(e)}`);
|
|
113583
|
+
return ["(go build failure)"];
|
|
113584
|
+
}
|
|
113585
|
+
}
|
|
113517
113586
|
async runPhantomDependencyAnalysis() {
|
|
113518
113587
|
return void 0;
|
|
113519
113588
|
}
|
|
@@ -113601,9 +113670,16 @@ var MavenAnalyzer = class {
|
|
|
113601
113670
|
constructor(state) {
|
|
113602
113671
|
this.state = state;
|
|
113603
113672
|
}
|
|
113673
|
+
async createScanner(tmpDir, statusUpdater) {
|
|
113674
|
+
return this.state.workspaceData.type === "coana" ? JavaCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, tmpDir, statusUpdater) : JavaCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
|
|
113675
|
+
}
|
|
113676
|
+
async installDependencies(preinstallDir) {
|
|
113677
|
+
const scanner = await this.createScanner(preinstallDir);
|
|
113678
|
+
return scanner.getPackagesExcludedUnrelatedToHeuristic();
|
|
113679
|
+
}
|
|
113604
113680
|
async runPhantomDependencyAnalysis() {
|
|
113605
113681
|
return withTmpDirectory("maven-phantom-dependency-analysis", async (tmpDir) => {
|
|
113606
|
-
const scanner =
|
|
113682
|
+
const scanner = await this.createScanner(tmpDir);
|
|
113607
113683
|
return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
|
|
113608
113684
|
});
|
|
113609
113685
|
}
|
|
@@ -113615,11 +113691,17 @@ var MavenAnalyzer = class {
|
|
|
113615
113691
|
}
|
|
113616
113692
|
analysisMetadataCollector?.(metadata);
|
|
113617
113693
|
};
|
|
113618
|
-
|
|
113619
|
-
|
|
113694
|
+
const preinstallDir = this.state.preinstallDir;
|
|
113695
|
+
const runWithTmpDir = async (tmpDir) => {
|
|
113696
|
+
const scanner = await this.createScanner(tmpDir, statusUpdater);
|
|
113697
|
+
checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
113620
113698
|
const heuristicsInOrder = [AlucardHeuristics.ALL_PACKAGES];
|
|
113621
113699
|
return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
|
|
113622
|
-
}
|
|
113700
|
+
};
|
|
113701
|
+
if (preinstallDir) {
|
|
113702
|
+
return runWithTmpDir(preinstallDir);
|
|
113703
|
+
}
|
|
113704
|
+
return withTmpDirectory("maven-reachability-analysis", runWithTmpDir);
|
|
113623
113705
|
}
|
|
113624
113706
|
async getWorkspaceDiagnostics() {
|
|
113625
113707
|
let sourceFilesDetected;
|
|
@@ -113648,7 +113730,7 @@ var MavenAnalyzer = class {
|
|
|
113648
113730
|
// dist/analyzers/npm-analyzer.js
|
|
113649
113731
|
var import_lodash19 = __toESM(require_lodash(), 1);
|
|
113650
113732
|
var import_picomatch4 = __toESM(require_picomatch2(), 1);
|
|
113651
|
-
import { existsSync as
|
|
113733
|
+
import { existsSync as existsSync16 } from "fs";
|
|
113652
113734
|
import { rm as rm6 } from "fs/promises";
|
|
113653
113735
|
import { relative as relative8, resolve as resolve20 } from "path";
|
|
113654
113736
|
|
|
@@ -113675,6 +113757,17 @@ var NpmAnalyzer = class {
|
|
|
113675
113757
|
this.state = state;
|
|
113676
113758
|
this.projectDir = projectDir;
|
|
113677
113759
|
}
|
|
113760
|
+
async installDependencies(preinstallDir) {
|
|
113761
|
+
if (existsSync16(resolve20(this.state.subprojectDir, "node_modules")))
|
|
113762
|
+
return [];
|
|
113763
|
+
const artifactIdToArtifact = this.state.workspaceData.type === "coana" ? this.state.workspaceData.data.dependencyTree.transitiveDependencies : Object.fromEntries(this.state.workspaceData.data.artifacts.map((d) => [d.id, d]));
|
|
113764
|
+
const vulnPathPackages = computePackagesOnVulnPath(this.state.vulnerabilities);
|
|
113765
|
+
const vulnerablePackageNames = [
|
|
113766
|
+
...new Set(this.state.vulnerabilities.flatMap((v) => Object.values(v.vulnChainDetails?.transitiveDependencies ?? {}).filter((d) => d.vulnerable === true).map((d) => d.packageName)))
|
|
113767
|
+
];
|
|
113768
|
+
const packagesToInstall = [.../* @__PURE__ */ new Set([...vulnPathPackages, ...vulnerablePackageNames])];
|
|
113769
|
+
return validateNpmDependencyDownloads(artifactIdToArtifact, packagesToInstall, preinstallDir);
|
|
113770
|
+
}
|
|
113678
113771
|
async runPhantomDependencyAnalysis() {
|
|
113679
113772
|
try {
|
|
113680
113773
|
return (await runJellyPhantomDependencyAnalysis(this.projectDir, this.state.reachabilityAnalysisOptions)).map((r) => r.name);
|
|
@@ -113684,7 +113777,7 @@ var NpmAnalyzer = class {
|
|
|
113684
113777
|
}
|
|
113685
113778
|
async runReachabilityAnalysis(vulns, analysisMetadataCollector, statusUpdater) {
|
|
113686
113779
|
const heuristicsInOrder = this.state.otherAnalysisOptions.lightweightReachability ? [heuristics.IGNORE_DEPENDENCIES_AND_MAX_ROUNDS_3] : [heuristics.ONLY_VULN_PATH_PACKAGES_EXCEPT_VULNERABLE_PACKAGE];
|
|
113687
|
-
const nodeModulesAlreadyExisted =
|
|
113780
|
+
const nodeModulesAlreadyExisted = existsSync16(resolve20(this.state.subprojectDir, "node_modules"));
|
|
113688
113781
|
this.preinstalledDependencies = nodeModulesAlreadyExisted ? "YES" : "NO";
|
|
113689
113782
|
const wrappedCollector = (metadata) => {
|
|
113690
113783
|
const jellyDiagnostics = metadata.analysisDiagnostics;
|
|
@@ -113696,6 +113789,7 @@ var NpmAnalyzer = class {
|
|
|
113696
113789
|
try {
|
|
113697
113790
|
const vulnerabilityScanner = new JSCodeAwareVulnerabilityScanner(this.state.rootWorkingDir, this.projectDir, this.state.reachabilityAnalysisOptions);
|
|
113698
113791
|
await vulnerabilityScanner.prepareDependencies(this.state, heuristicsInOrder[0]);
|
|
113792
|
+
checkForInstallErrors(vulnerabilityScanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
113699
113793
|
logger.info(`Running import reachability analysis for ${vulns.length} ${pluralize(vulns.length, "vulnerability")}`);
|
|
113700
113794
|
let reachable;
|
|
113701
113795
|
const ghsaIds = extractGhsaIdsFromVulnUrls(vulns.map((v) => v.url));
|
|
@@ -113809,9 +113903,9 @@ ${e.stack}` : String(e),
|
|
|
113809
113903
|
return res;
|
|
113810
113904
|
} finally {
|
|
113811
113905
|
if (!nodeModulesAlreadyExisted) {
|
|
113812
|
-
if (
|
|
113906
|
+
if (existsSync16(resolve20(this.state.subprojectDir, "node_modules")))
|
|
113813
113907
|
await rm6(resolve20(this.state.subprojectDir, "node_modules"), { recursive: true });
|
|
113814
|
-
if (
|
|
113908
|
+
if (existsSync16(resolve20(this.projectDir, "node_modules")))
|
|
113815
113909
|
await rm6(resolve20(this.projectDir, "node_modules"), { recursive: true });
|
|
113816
113910
|
}
|
|
113817
113911
|
}
|
|
@@ -113852,9 +113946,16 @@ var NugetAnalyzer = class {
|
|
|
113852
113946
|
constructor(state) {
|
|
113853
113947
|
this.state = state;
|
|
113854
113948
|
}
|
|
113949
|
+
async createScanner(tmpDir, statusUpdater) {
|
|
113950
|
+
return this.state.workspaceData.type === "coana" ? DotnetCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, statusUpdater) : DotnetCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.manifestFiles, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
|
|
113951
|
+
}
|
|
113952
|
+
async installDependencies(preinstallDir) {
|
|
113953
|
+
const scanner = await this.createScanner(preinstallDir);
|
|
113954
|
+
return scanner.getPackagesExcludedUnrelatedToHeuristic();
|
|
113955
|
+
}
|
|
113855
113956
|
async runPhantomDependencyAnalysis() {
|
|
113856
113957
|
return withTmpDirectory("nuget-phantom-dependency-analysis", async (tmpDir) => {
|
|
113857
|
-
const scanner =
|
|
113958
|
+
const scanner = await this.createScanner(tmpDir);
|
|
113858
113959
|
return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
|
|
113859
113960
|
});
|
|
113860
113961
|
}
|
|
@@ -113866,11 +113967,17 @@ var NugetAnalyzer = class {
|
|
|
113866
113967
|
}
|
|
113867
113968
|
analysisMetadataCollector?.(metadata);
|
|
113868
113969
|
};
|
|
113869
|
-
|
|
113870
|
-
|
|
113970
|
+
const preinstallDir = this.state.preinstallDir;
|
|
113971
|
+
const runWithTmpDir = async (tmpDir) => {
|
|
113972
|
+
const scanner = await this.createScanner(tmpDir, statusUpdater);
|
|
113973
|
+
checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
113871
113974
|
const heuristicsInOrder = [CocoaHeuristics.ALL_PACKAGES];
|
|
113872
113975
|
return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
|
|
113873
|
-
}
|
|
113976
|
+
};
|
|
113977
|
+
if (preinstallDir) {
|
|
113978
|
+
return runWithTmpDir(preinstallDir);
|
|
113979
|
+
}
|
|
113980
|
+
return withTmpDirectory("nuget-reachability-analysis", runWithTmpDir);
|
|
113874
113981
|
}
|
|
113875
113982
|
async getWorkspaceDiagnostics() {
|
|
113876
113983
|
let sourceFilesDetected;
|
|
@@ -113898,13 +114005,13 @@ var NugetAnalyzer = class {
|
|
|
113898
114005
|
|
|
113899
114006
|
// dist/analyzers/ruby-analyzer.js
|
|
113900
114007
|
var import_lodash21 = __toESM(require_lodash(), 1);
|
|
113901
|
-
import { existsSync as
|
|
114008
|
+
import { existsSync as existsSync18 } from "fs";
|
|
113902
114009
|
import { resolve as resolve21 } from "path";
|
|
113903
114010
|
|
|
113904
114011
|
// dist/whole-program-code-aware-vulnerability-scanner/ruby/ruby-code-aware-vulnerability-scanner.js
|
|
113905
114012
|
var import_lodash20 = __toESM(require_lodash(), 1);
|
|
113906
|
-
import { createWriteStream as createWriteStream5, existsSync as
|
|
113907
|
-
import { mkdir as mkdir9, readdir as
|
|
114013
|
+
import { createWriteStream as createWriteStream5, existsSync as existsSync17 } from "fs";
|
|
114014
|
+
import { mkdir as mkdir9, readdir as readdir7, readFile as readFile13, rm as rm7 } from "fs/promises";
|
|
113908
114015
|
import { join as join18, relative as relative9 } from "path";
|
|
113909
114016
|
import { pipeline as pipeline3 } from "stream/promises";
|
|
113910
114017
|
var PRINT_ANALYSIS_COMMAND = false;
|
|
@@ -113921,12 +114028,12 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
113921
114028
|
this.projectDir = projectDir;
|
|
113922
114029
|
this.options = options;
|
|
113923
114030
|
}
|
|
113924
|
-
async prepareDependencies(preInstalledDepInfos, vulns, heuristic) {
|
|
113925
|
-
const vendorDir = join18(this.projectDir, "vendor");
|
|
113926
|
-
if (
|
|
114031
|
+
async prepareDependencies(preInstalledDepInfos, vulns, heuristic, preinstallDir) {
|
|
114032
|
+
const vendorDir = preinstallDir ?? join18(this.projectDir, "vendor");
|
|
114033
|
+
if (existsSync17(vendorDir)) {
|
|
113927
114034
|
logger.info(`Vendor directory already exists at ${vendorDir}, skipping gem installation`);
|
|
113928
114035
|
this.vendorDir = vendorDir;
|
|
113929
|
-
this.vendorDirWasCreated =
|
|
114036
|
+
this.vendorDirWasCreated = !preinstallDir;
|
|
113930
114037
|
return;
|
|
113931
114038
|
}
|
|
113932
114039
|
const packagesToIncludeNames = heuristic.getPackagesToIncludeInAnalysis?.(vulns)?.map((p) => p.packageName);
|
|
@@ -113957,7 +114064,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
113957
114064
|
if (!this.vendorDir)
|
|
113958
114065
|
throw new Error("Assertion error: The vendor directory is not correctly initialized");
|
|
113959
114066
|
const analyzerPath = ToolPathResolver.callgraphReachabilityAnalyzersCliPath;
|
|
113960
|
-
if (!
|
|
114067
|
+
if (!existsSync17(analyzerPath))
|
|
113961
114068
|
throw new Error(`callgraph-reachability-analyzers CLI not found at ${analyzerPath}`);
|
|
113962
114069
|
const vulnAccPaths = sortedUniq2(vulns.flatMap((v) => v.vulnerabilityAccessPaths).sort());
|
|
113963
114070
|
const vulnsOutputFile = join18(tmpDir, "vulns.json");
|
|
@@ -113968,12 +114075,12 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
113968
114075
|
const loadPaths = Array.from(loadPathsToPackageNames.keys());
|
|
113969
114076
|
if (failedToFindLoadPath.length > 0) {
|
|
113970
114077
|
this.packagesExcludedUnrelatedToHeuristic.push(...failedToFindLoadPath.map((p) => p.packageName));
|
|
113971
|
-
logger.
|
|
114078
|
+
logger.debug(`Failed to find package installation path for ${failedToFindLoadPath.map((p) => p.packageName).join(", ")}`);
|
|
113972
114079
|
}
|
|
113973
114080
|
if (loadPaths.length === 0) {
|
|
113974
114081
|
return {
|
|
113975
114082
|
type: "error",
|
|
113976
|
-
message:
|
|
114083
|
+
message: `${FAILED_TO_INSTALL_PACKAGE_KEY}No load paths found for the packages to analyze`
|
|
113977
114084
|
};
|
|
113978
114085
|
}
|
|
113979
114086
|
const cmd = cmdt`
|
|
@@ -114032,7 +114139,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114032
114139
|
return this.packagesExcludedUnrelatedToHeuristic;
|
|
114033
114140
|
}
|
|
114034
114141
|
async cleanup() {
|
|
114035
|
-
if (this.vendorDirWasCreated && this.vendorDir &&
|
|
114142
|
+
if (this.vendorDirWasCreated && this.vendorDir && existsSync17(this.vendorDir)) {
|
|
114036
114143
|
logger.info(`Deleting auto-generated vendor directory at ${this.vendorDir}`);
|
|
114037
114144
|
await rm7(this.vendorDir, { recursive: true, force: true }).catch(() => {
|
|
114038
114145
|
});
|
|
@@ -114048,7 +114155,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114048
114155
|
if (this.vendorDirWasCreated) {
|
|
114049
114156
|
for (const pkg of packagesToAnalyze) {
|
|
114050
114157
|
const libPath = join18(this.vendorDir, `${pkg.packageName}-${pkg.version}`, "lib");
|
|
114051
|
-
if (
|
|
114158
|
+
if (existsSync17(libPath))
|
|
114052
114159
|
loadPathsToPackageNames.set(libPath, `${pkg.packageName}@${pkg.version}`);
|
|
114053
114160
|
else
|
|
114054
114161
|
failedToFindLoadPath.push(pkg);
|
|
@@ -114056,13 +114163,13 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114056
114163
|
return { loadPathsToPackageNames, failedToFindLoadPath };
|
|
114057
114164
|
}
|
|
114058
114165
|
const bundlerGemsDir = join18(this.vendorDir, "bundle", "ruby");
|
|
114059
|
-
if (
|
|
114060
|
-
const rubyVersions = await
|
|
114166
|
+
if (existsSync17(bundlerGemsDir)) {
|
|
114167
|
+
const rubyVersions = await readdir7(bundlerGemsDir);
|
|
114061
114168
|
for (const rubyVersion of rubyVersions) {
|
|
114062
114169
|
const gemsDir = join18(bundlerGemsDir, rubyVersion, "gems");
|
|
114063
|
-
if (
|
|
114170
|
+
if (existsSync17(gemsDir)) {
|
|
114064
114171
|
const nameToEntry = /* @__PURE__ */ new Map();
|
|
114065
|
-
for (const entry of await
|
|
114172
|
+
for (const entry of await readdir7(gemsDir, { withFileTypes: true }))
|
|
114066
114173
|
if (entry.isDirectory()) {
|
|
114067
114174
|
const match2 = entry.name.match(/^([\w-_]+)-(\d+\.\d+\.\d+)/);
|
|
114068
114175
|
if (match2)
|
|
@@ -114073,7 +114180,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114073
114180
|
if (!entry)
|
|
114074
114181
|
continue;
|
|
114075
114182
|
const libDir = join18(gemsDir, entry, "lib");
|
|
114076
|
-
if (
|
|
114183
|
+
if (existsSync17(libDir))
|
|
114077
114184
|
loadPathsToPackageNames.set(libDir, `${pkg.packageName}@${pkg.version}`);
|
|
114078
114185
|
else
|
|
114079
114186
|
failedToFindLoadPath.push(pkg);
|
|
@@ -114083,7 +114190,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114083
114190
|
} else
|
|
114084
114191
|
for (const pkg of packagesToAnalyze) {
|
|
114085
114192
|
const libPath = join18(this.vendorDir, `${pkg.packageName}-${pkg.version}`, "lib");
|
|
114086
|
-
if (
|
|
114193
|
+
if (existsSync17(libPath))
|
|
114087
114194
|
loadPathsToPackageNames.set(libPath, `${pkg.packageName}@${pkg.version}`);
|
|
114088
114195
|
else
|
|
114089
114196
|
failedToFindLoadPath.push(pkg);
|
|
@@ -114093,7 +114200,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
|
|
|
114093
114200
|
};
|
|
114094
114201
|
async function downloadAndExtractGem(gemName, version3, vendorDir) {
|
|
114095
114202
|
const gemDir = join18(vendorDir, `${gemName}-${version3}`);
|
|
114096
|
-
if (
|
|
114203
|
+
if (existsSync17(gemDir)) {
|
|
114097
114204
|
logger.debug(`Gem ${gemName}@${version3} already extracted`);
|
|
114098
114205
|
return;
|
|
114099
114206
|
}
|
|
@@ -114146,9 +114253,16 @@ var RubyGemsAnalyzer = class {
|
|
|
114146
114253
|
this.scanner = new RubyCodeAwareVulnerabilityScanner(state, projectDir);
|
|
114147
114254
|
}
|
|
114148
114255
|
prepareScanner = once5(async () => {
|
|
114149
|
-
await this.scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), RubyHeuristics.ONLY_VULN_PATH_PACKAGES);
|
|
114256
|
+
await this.scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), RubyHeuristics.ONLY_VULN_PATH_PACKAGES, this.state.preinstallDir);
|
|
114150
114257
|
return this.scanner;
|
|
114151
114258
|
});
|
|
114259
|
+
async installDependencies(preinstallDir) {
|
|
114260
|
+
if (existsSync18(resolve21(this.projectDir, "vendor")))
|
|
114261
|
+
return [];
|
|
114262
|
+
const scanner = new RubyCodeAwareVulnerabilityScanner(this.state, this.projectDir);
|
|
114263
|
+
await scanner.prepareDependencies(this.preInstalledDepInfos, this.state.vulnerabilities.filter((v) => Array.isArray(v.vulnerabilityAccessPaths)), RubyHeuristics.ONLY_VULN_PATH_PACKAGES, preinstallDir);
|
|
114264
|
+
return scanner.getPackagesExcludedUnrelatedToHeuristic();
|
|
114265
|
+
}
|
|
114152
114266
|
async runPhantomDependencyAnalysis() {
|
|
114153
114267
|
return void 0;
|
|
114154
114268
|
}
|
|
@@ -114160,9 +114274,11 @@ var RubyGemsAnalyzer = class {
|
|
|
114160
114274
|
}
|
|
114161
114275
|
analysisMetadataCollector?.(metadata);
|
|
114162
114276
|
};
|
|
114163
|
-
this.preinstalledDependencies =
|
|
114277
|
+
this.preinstalledDependencies = existsSync18(resolve21(this.projectDir, "vendor")) ? "YES" : "NO";
|
|
114164
114278
|
try {
|
|
114165
|
-
|
|
114279
|
+
const scanner = await this.prepareScanner();
|
|
114280
|
+
checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
114281
|
+
return await analyzeWithHeuristics(this.state, vulns, [RubyHeuristics.ONLY_VULN_PATH_PACKAGES], false, scanner, wrappedCollector, statusUpdater);
|
|
114166
114282
|
} finally {
|
|
114167
114283
|
await this.scanner.cleanup();
|
|
114168
114284
|
}
|
|
@@ -114220,9 +114336,16 @@ var RustAnalyzer = class {
|
|
|
114220
114336
|
constructor(state) {
|
|
114221
114337
|
this.state = state;
|
|
114222
114338
|
}
|
|
114339
|
+
async createScanner(tmpDir, statusUpdater) {
|
|
114340
|
+
return this.state.workspaceData.type === "coana" ? RustCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, statusUpdater) : RustCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspacePath, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
|
|
114341
|
+
}
|
|
114342
|
+
async installDependencies(preinstallDir) {
|
|
114343
|
+
const scanner = await this.createScanner(preinstallDir);
|
|
114344
|
+
return scanner.getPackagesExcludedUnrelatedToHeuristic();
|
|
114345
|
+
}
|
|
114223
114346
|
async runPhantomDependencyAnalysis() {
|
|
114224
114347
|
return withTmpDirectory("cargo-phantom-dependency-analysis", async (tmpDir) => {
|
|
114225
|
-
const scanner =
|
|
114348
|
+
const scanner = await this.createScanner(tmpDir);
|
|
114226
114349
|
return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
|
|
114227
114350
|
});
|
|
114228
114351
|
}
|
|
@@ -114234,11 +114357,17 @@ var RustAnalyzer = class {
|
|
|
114234
114357
|
}
|
|
114235
114358
|
analysisMetadataCollector?.(metadata);
|
|
114236
114359
|
};
|
|
114237
|
-
|
|
114238
|
-
|
|
114360
|
+
const preinstallDir = this.state.preinstallDir;
|
|
114361
|
+
const runWithTmpDir = async (tmpDir) => {
|
|
114362
|
+
const scanner = await this.createScanner(tmpDir, statusUpdater);
|
|
114363
|
+
checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
|
|
114239
114364
|
const heuristicsInOrder = [RusticaHeuristics.ALL_PACKAGES];
|
|
114240
114365
|
return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
|
|
114241
|
-
}
|
|
114366
|
+
};
|
|
114367
|
+
if (preinstallDir) {
|
|
114368
|
+
return runWithTmpDir(preinstallDir);
|
|
114369
|
+
}
|
|
114370
|
+
return withTmpDirectory("cargo-reachability-analysis", runWithTmpDir);
|
|
114242
114371
|
}
|
|
114243
114372
|
async getWorkspaceDiagnostics() {
|
|
114244
114373
|
let sourceFilesDetected;
|
|
@@ -114277,6 +114406,17 @@ var ecosystemAnalyzer = {
|
|
|
114277
114406
|
};
|
|
114278
114407
|
var apiKey2 = COANA_API_KEY ? { type: "present", value: COANA_API_KEY } : { type: "missing" };
|
|
114279
114408
|
var dashboardAPI3 = new DashboardAPI(process.env.SOCKET_MODE === "true", process.env.DISABLE_ANALYTICS_SHARING === "true");
|
|
114409
|
+
async function installDependenciesForAnalysis(state, preinstallDir) {
|
|
114410
|
+
const projectDir = resolve22(state.subprojectDir, state.workspacePath);
|
|
114411
|
+
const ecosystem = state.workspaceData.data.type;
|
|
114412
|
+
logger.info(`Pre-installing dependencies for project at "${relative10(state.rootWorkingDir, projectDir) || "."}" (${ecosystem})`);
|
|
114413
|
+
const constructor = ecosystemAnalyzer[ecosystem];
|
|
114414
|
+
if (!constructor)
|
|
114415
|
+
throw Error(`No analyzer associated with ecosystem ${ecosystem}`);
|
|
114416
|
+
const analyzer = new constructor(state, projectDir);
|
|
114417
|
+
const failedPackages = await analyzer.installDependencies(preinstallDir);
|
|
114418
|
+
return { failedPackages };
|
|
114419
|
+
}
|
|
114280
114420
|
async function runReachabilityAnalysis(state) {
|
|
114281
114421
|
const projectDir = resolve22(state.subprojectDir, state.workspacePath);
|
|
114282
114422
|
const ecosystem = state.workspaceData.data.type;
|
|
@@ -114308,9 +114448,30 @@ async function getReachabilityAnalyzersStateFromInput(rootWorkingDir, subproject
|
|
|
114308
114448
|
}
|
|
114309
114449
|
|
|
114310
114450
|
// dist/reachability-analyzers-cli.js
|
|
114311
|
-
var runReachabilityAnalysisCmd = new Command().name("runReachabilityAnalysis").argument("<rootWorkingDir>", "Directory where Coana is run").argument("<subprojectDir>", "Project root of directory being analyzed").argument("<workspacePath>", "Path to directory to analyze relative to subprojectDir").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("--coana-socket-path <socketPath>", "Coana socket path").option("--silent-spinner", "Silence spinner", "CI" in process.env || !process.stdin.isTTY).requiredOption("-i, --input-file <inputFile>", "Input file for data and vulnerabilities").requiredOption("-o, --output-file <outputFile>", "Output file for the results").configureHelp({ sortSubcommands: true, sortOptions: true }).action(async (rootWorkingDir, subprojectDir, workspacePath, options) => withLoggerAndSpinner("Coana Reachability Analyzers", options, async () => {
|
|
114451
|
+
var runReachabilityAnalysisCmd = new Command().name("runReachabilityAnalysis").argument("<rootWorkingDir>", "Directory where Coana is run").argument("<subprojectDir>", "Project root of directory being analyzed").argument("<workspacePath>", "Path to directory to analyze relative to subprojectDir").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("--coana-socket-path <socketPath>", "Coana socket path").option("--silent-spinner", "Silence spinner", "CI" in process.env || !process.stdin.isTTY).option("--preinstall-dir <preinstallDir>", "Directory with pre-installed dependencies").requiredOption("-i, --input-file <inputFile>", "Input file for data and vulnerabilities").requiredOption("-o, --output-file <outputFile>", "Output file for the results").configureHelp({ sortSubcommands: true, sortOptions: true }).action(async (rootWorkingDir, subprojectDir, workspacePath, options) => withLoggerAndSpinner("Coana Reachability Analyzers", options, async () => {
|
|
114452
|
+
try {
|
|
114453
|
+
const state = await getReachabilityAnalyzersStateFromInput(rootWorkingDir, subprojectDir, workspacePath, options.inputFile);
|
|
114454
|
+
if (options.preinstallDir) {
|
|
114455
|
+
state.preinstallDir = options.preinstallDir;
|
|
114456
|
+
}
|
|
114457
|
+
const result = await runReachabilityAnalysis(state);
|
|
114458
|
+
if (options.outputFile) {
|
|
114459
|
+
logger.debug("Writing result to file", options.outputFile);
|
|
114460
|
+
await writeFile10(options.outputFile, JSON.stringify({ result }));
|
|
114461
|
+
} else {
|
|
114462
|
+
logger.info("Result:", JSON.stringify(result, null, 2));
|
|
114463
|
+
}
|
|
114464
|
+
} catch (e) {
|
|
114465
|
+
if (e instanceof InstallError && options.outputFile) {
|
|
114466
|
+
await writeFile10(options.outputFile, JSON.stringify({ error: { type: "InstallError", failedPackages: e.failedPackages } }));
|
|
114467
|
+
return;
|
|
114468
|
+
}
|
|
114469
|
+
throw e;
|
|
114470
|
+
}
|
|
114471
|
+
}, "reachability-analyzer"));
|
|
114472
|
+
var installDependenciesCmd = new Command().name("installDependencies").argument("<rootWorkingDir>", "Directory where Coana is run").argument("<subprojectDir>", "Project root of directory being analyzed").argument("<workspacePath>", "Path to directory to analyze relative to subprojectDir").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("--coana-socket-path <socketPath>", "Coana socket path").option("--silent-spinner", "Silence spinner", "CI" in process.env || !process.stdin.isTTY).requiredOption("-i, --input-file <inputFile>", "Input file for data and vulnerabilities").requiredOption("-o, --output-file <outputFile>", "Output file for the results").requiredOption("--preinstall-dir <preinstallDir>", "Directory to install dependencies into").configureHelp({ sortSubcommands: true, sortOptions: true }).action(async (rootWorkingDir, subprojectDir, workspacePath, options) => withLoggerAndSpinner("Coana Reachability Analyzers - Install Dependencies", options, async () => {
|
|
114312
114473
|
const state = await getReachabilityAnalyzersStateFromInput(rootWorkingDir, subprojectDir, workspacePath, options.inputFile);
|
|
114313
|
-
const result = await
|
|
114474
|
+
const result = await installDependenciesForAnalysis(state, options.preinstallDir);
|
|
114314
114475
|
if (options.outputFile) {
|
|
114315
114476
|
logger.debug("Writing result to file", options.outputFile);
|
|
114316
114477
|
await writeFile10(options.outputFile, JSON.stringify({ result }));
|
|
@@ -114366,7 +114527,7 @@ var runOnPackageRegistryPackageCmd = new Command().name("runOnPackageRegistryPac
|
|
|
114366
114527
|
}
|
|
114367
114528
|
}, "reachability-analyzer");
|
|
114368
114529
|
});
|
|
114369
|
-
new Command().addCommand(runReachabilityAnalysisCmd, { isDefault: true }).addCommand(runOnDependencyChainCmd).addCommand(runOnPackageRegistryPackageCmd).parseAsync();
|
|
114530
|
+
new Command().addCommand(runReachabilityAnalysisCmd, { isDefault: true }).addCommand(installDependenciesCmd).addCommand(runOnDependencyChainCmd).addCommand(runOnPackageRegistryPackageCmd).parseAsync();
|
|
114370
114531
|
/*! Bundled license information:
|
|
114371
114532
|
|
|
114372
114533
|
safe-buffer/index.js:
|