@coana-tech/cli 14.12.200 → 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.
@@ -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 existsSync13 } from "fs";
88575
- import { cp as cp7, readdir as readdir4, readFile as readFile12, rm as rm5 } from "fs/promises";
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";
@@ -94244,7 +94252,7 @@ var CocoaHeuristics = {
94244
94252
 
94245
94253
  // dist/whole-program-code-aware-vulnerability-scanner/dotnet/dotnet-code-aware-vulnerability-scanner.js
94246
94254
  var import_adm_zip = __toESM(require_adm_zip(), 1);
94247
- import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
94255
+ import { mkdir as mkdir5, readdir as readdir4, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
94248
94256
  import { randomUUID } from "node:crypto";
94249
94257
 
94250
94258
  // dist/whole-program-code-aware-vulnerability-scanner/dotnet/constants.js
@@ -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);
@@ -96464,7 +96472,13 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
96464
96472
  const outputFile = resolve9(tmpDir, "output.json");
96465
96473
  await writeFile5(inputFile, JSON.stringify(options));
96466
96474
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
96467
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL", heartbeat: HEARTBEATS.dotnet, telemetryHandler, analyzerTelemetryHandler });
96475
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, {
96476
+ timeout: timeoutMs,
96477
+ killSignal: "SIGKILL",
96478
+ heartbeat: HEARTBEATS.dotnet,
96479
+ telemetryHandler,
96480
+ analyzerTelemetryHandler
96481
+ });
96468
96482
  if (result.error)
96469
96483
  return { type: "error", message: result.error.message ?? "unknown error" };
96470
96484
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile7(outputFile, "utf-8")).result;
@@ -96555,18 +96569,29 @@ async function downloadAndExtractNugetPackage(packageName, version3, tmpDir) {
96555
96569
  const packageUrl = getUrlForPackage(packageName, version3);
96556
96570
  const success = await downloadFile(packageUrl, packageFile);
96557
96571
  if (!success) {
96558
- logger.warn(`Failed to download nuget package ${packageName}/${version3}`);
96559
- return void 0;
96572
+ throw new Error(`Failed to download nuget package ${packageName}/${version3}`);
96560
96573
  }
96561
96574
  }
96562
96575
  return extractNugetPackage(packageFile, packageName, version3, tmpDir);
96563
96576
  }
96564
96577
  async function convertDependencyChain(dependencyChain, tmpDir) {
96578
+ const runtimePaths = await getDotnetRuntimeSharedPaths();
96579
+ const runtimeFileIndex = await buildRuntimeFileIndex(runtimePaths);
96565
96580
  const nugetDependencyChain = await asyncMap(dependencyChain, async (dep) => {
96566
- return {
96567
- ...dep,
96568
- bin: dep.version ? await downloadAndExtractNugetPackage(dep.packageName, dep.version, tmpDir) : void 0
96569
- };
96581
+ const binFiles = [];
96582
+ if (dep.version) {
96583
+ try {
96584
+ const extracted = await downloadAndExtractNugetPackage(dep.packageName, dep.version, tmpDir);
96585
+ if (extracted)
96586
+ binFiles.push(...extracted);
96587
+ } catch (e) {
96588
+ logger.warn(`${e.message}`);
96589
+ }
96590
+ const runtimeFiles = findStdlibRuntimeFiles(dep.packageName, runtimeFileIndex);
96591
+ if (runtimeFiles)
96592
+ binFiles.push(...runtimeFiles);
96593
+ }
96594
+ return { ...dep, bin: binFiles.length > 0 ? binFiles : void 0 };
96570
96595
  }, 4);
96571
96596
  return nugetDependencyChain;
96572
96597
  }
@@ -96592,23 +96617,109 @@ async function findNuGetPackageInLocalRepo(repo, packageName, version3, tmpDir)
96592
96617
  const nupkgFile = allFiles.find((file) => basename7(file).toLowerCase() === targetNupkg);
96593
96618
  return nupkgFile ? extractNugetPackage(nupkgFile, packageName, version3, tmpDir) : void 0;
96594
96619
  }
96620
+ async function getDotnetRuntimeSharedPaths() {
96621
+ const result = await execNeverFail2(cmdt`dotnet --list-runtimes`);
96622
+ if (result.error ?? !result.stdout)
96623
+ return [];
96624
+ const paths = [];
96625
+ for (const line of result.stdout.split("\n")) {
96626
+ const match2 = line.trim().match(/^(\S+)\s+(\S+)\s+\[(.+)\]$/);
96627
+ if (match2) {
96628
+ const runtimeDir = resolve9(match2[3], match2[2]);
96629
+ if (existsSync7(runtimeDir)) {
96630
+ paths.push(runtimeDir);
96631
+ }
96632
+ }
96633
+ }
96634
+ return paths;
96635
+ }
96636
+ async function buildRuntimeFileIndex(runtimePaths) {
96637
+ const index2 = /* @__PURE__ */ new Map();
96638
+ for (const runtimePath of runtimePaths) {
96639
+ try {
96640
+ const entries = await readdir4(runtimePath, { withFileTypes: true });
96641
+ for (const entry of entries) {
96642
+ if (!entry.isFile())
96643
+ continue;
96644
+ const name2 = entry.name.toLowerCase();
96645
+ const fullPath = resolve9(runtimePath, entry.name);
96646
+ const existing = index2.get(name2);
96647
+ if (existing) {
96648
+ existing.push(fullPath);
96649
+ } else {
96650
+ index2.set(name2, [fullPath]);
96651
+ }
96652
+ }
96653
+ } catch (e) {
96654
+ logger.debug(`Failed to read runtime path ${runtimePath}: ${e.message}`);
96655
+ }
96656
+ }
96657
+ return index2;
96658
+ }
96659
+ function findStdlibRuntimeFiles(packageName, runtimeFileIndex) {
96660
+ if (runtimeFileIndex.size === 0)
96661
+ return void 0;
96662
+ const possibleFileNames = /* @__PURE__ */ new Set();
96663
+ if (packageName.toLowerCase() === "netstandard.library") {
96664
+ possibleFileNames.add("netstandard.dll");
96665
+ } else {
96666
+ const lowerName = packageName.toLowerCase();
96667
+ const componentName = lowerName.startsWith("runtime.native.") ? lowerName.slice("runtime.native.".length) : lowerName;
96668
+ const nameVariants = [componentName, `${componentName}.Native`];
96669
+ const lastDotIndex = componentName.lastIndexOf(".");
96670
+ if (lastDotIndex !== -1) {
96671
+ nameVariants.push(componentName.slice(0, lastDotIndex) + ".Native" + componentName.slice(lastDotIndex));
96672
+ }
96673
+ for (const name2 of nameVariants) {
96674
+ possibleFileNames.add(`${name2}.dll`.toLowerCase());
96675
+ possibleFileNames.add(`lib${name2}.dylib`.toLowerCase());
96676
+ possibleFileNames.add(`lib${name2}.so`.toLowerCase());
96677
+ }
96678
+ }
96679
+ const matchedFiles = [];
96680
+ for (const fileName2 of possibleFileNames) {
96681
+ const files = runtimeFileIndex.get(fileName2);
96682
+ if (files)
96683
+ matchedFiles.push(...files);
96684
+ }
96685
+ return matchedFiles.length > 0 ? matchedFiles : void 0;
96686
+ }
96595
96687
  async function convertSocketArtifacts(artifacts, tmpDir) {
96596
96688
  const localRepositories = getNuGetLocalRepositoryPaths();
96689
+ const runtimePaths = await getDotnetRuntimeSharedPaths();
96690
+ const runtimeFileIndex = await buildRuntimeFileIndex(runtimePaths);
96597
96691
  async function resolveNuGetPackage(packageName, version3) {
96692
+ const binFiles = [];
96598
96693
  for (const repo of localRepositories) {
96599
96694
  const localPackage = await findNuGetPackageInLocalRepo(repo, packageName, version3, tmpDir);
96600
- if (localPackage)
96601
- return localPackage;
96695
+ if (localPackage) {
96696
+ binFiles.push(...localPackage);
96697
+ break;
96698
+ }
96699
+ }
96700
+ if (binFiles.length === 0) {
96701
+ const downloaded = await downloadAndExtractNugetPackage(packageName, version3, tmpDir);
96702
+ if (downloaded)
96703
+ binFiles.push(...downloaded);
96602
96704
  }
96603
- return await downloadAndExtractNugetPackage(packageName, version3, tmpDir);
96705
+ const runtimeFiles = findStdlibRuntimeFiles(packageName, runtimeFileIndex);
96706
+ if (runtimeFiles)
96707
+ binFiles.push(...runtimeFiles);
96708
+ return binFiles.length > 0 ? binFiles : void 0;
96604
96709
  }
96605
96710
  const deps = {};
96606
96711
  const depIdToPurl = /* @__PURE__ */ new Map();
96607
96712
  await asyncForEach(artifacts, async (artifact) => {
96608
96713
  depIdToPurl.set(artifact.id, getPurlFromSocketFactArtifact(artifact));
96609
- deps[artifact.id] = {
96610
- bin: artifact.name && artifact.version ? await resolveNuGetPackage(artifact.name, artifact.version) : void 0
96611
- };
96714
+ let bin;
96715
+ if (artifact.name && artifact.version) {
96716
+ try {
96717
+ bin = await resolveNuGetPackage(artifact.name, artifact.version);
96718
+ } catch (e) {
96719
+ logger.warn(`${e.message}`);
96720
+ }
96721
+ }
96722
+ deps[artifact.id] = { bin };
96612
96723
  }, 4);
96613
96724
  return { deps, depIdToPurl };
96614
96725
  }
@@ -110405,7 +110516,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
110405
110516
  if (result.error)
110406
110517
  return void 0;
110407
110518
  const packageIds = JSON.parse(await readFile8(outputFile, "utf-8")).result;
110408
- 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}`);
110409
110520
  });
110410
110521
  }
110411
110522
  async runAnalysis(vulnerabilities, heuristic, timeoutInSeconds, _experiment, telemetryHandler, analyzerTelemetryHandler) {
@@ -110415,7 +110526,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
110415
110526
  const packagesToAnalyzeSet = new Set(packagesToAnalyze);
110416
110527
  const filteredDeps = !packagesToAnalyze ? this.deps : Object.fromEntries(Object.entries(this.deps).filter(([packageId]) => {
110417
110528
  const purl = this.depIdToPurl.get(packageId);
110418
- return purl && packagesToAnalyzeSet.has(`${purl.namespace}:${purl.name}}`);
110529
+ return purl && packagesToAnalyzeSet.has(`${purl.namespace}:${purl.name}`);
110419
110530
  }));
110420
110531
  return await this.actuallyRunAnalysis(vulnerabilities.flatMap((v) => v.vulnerabilityAccessPaths), timeoutInSeconds, filteredDeps, telemetryHandler, analyzerTelemetryHandler);
110421
110532
  } catch (e) {
@@ -110488,7 +110599,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
110488
110599
  };
110489
110600
  }
110490
110601
  getPackagesExcludedUnrelatedToHeuristic() {
110491
- 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}`);
110492
110603
  }
110493
110604
  };
110494
110605
  async function convertDependencyChain2(dependencyChain, tmpDir) {
@@ -110557,6 +110668,9 @@ async function convertSocketArtifacts2(rootDir, artifacts, tmpDir) {
110557
110668
  }
110558
110669
  }
110559
110670
  }
110671
+ const artifactFile = getPathToArtifact(tmpDir, groupId, artifactId, type, classifier, version3);
110672
+ if (existsSync9(artifactFile))
110673
+ return artifactFile;
110560
110674
  if (mavenInstalled && pomFile) {
110561
110675
  try {
110562
110676
  const dependencyGetCmd = cmdt`mvn -f=${basename8(resolve10(rootDir, pomFile))} dependency:get -DgroupId=${groupId} -DartifactId=${artifactId} -Dpackaging=${type} -Dclassifier${classifier} -Dversion=${version3} -Dtransitive=false`;
@@ -110567,7 +110681,6 @@ async function convertSocketArtifacts2(rootDir, artifacts, tmpDir) {
110567
110681
  } catch {
110568
110682
  }
110569
110683
  }
110570
- const artifactFile = getPathToArtifact(tmpDir, groupId, artifactId, type, classifier, version3);
110571
110684
  await mkdir6(dirname11(artifactFile), { recursive: true });
110572
110685
  const success = await resolveMavenArtifactFromStandardRepositories(groupId, artifactId, type, classifier, version3, artifactFile);
110573
110686
  return success ? artifactFile : void 0;
@@ -110619,21 +110732,41 @@ import { tmpdir as tmpdir4 } from "os";
110619
110732
  import { join as join15 } from "path";
110620
110733
 
110621
110734
  // dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
110622
- import { existsSync as existsSync10 } from "fs";
110735
+ import { existsSync as existsSync11 } from "fs";
110623
110736
  import { resolve as resolve12 } from "path";
110624
110737
 
110625
110738
  // dist/whole-program-code-aware-vulnerability-scanner/js/setup-npm-dependencies-for-analysis.js
110626
110739
  var import_lodash9 = __toESM(require_lodash(), 1);
110627
- import { link, mkdir as mkdir7 } from "fs/promises";
110740
+ import { existsSync as existsSync10 } from "fs";
110741
+ import { link, mkdir as mkdir7, readdir as readdir5 } from "fs/promises";
110628
110742
  import { availableParallelism } from "os";
110629
110743
  import { dirname as dirname12, join as join14, resolve as resolve11 } from "path";
110630
110744
  var { chunk } = import_lodash9.default;
110631
110745
  var ROOT_PACKAGE_METADATA_NAME = "UNIQUE_ROOT_PACKAGE_METADATA_NAME";
110632
- async function setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, artifactIdToArtifact) {
110746
+ async function setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, artifactIdToArtifact, preinstallDir) {
110633
110747
  return await withTmpDirectory("npm-packages", async (tmpDir) => {
110634
110748
  const dirToInstallDependencies = resolve11(subprojectDir, "node_modules", ".jelly");
110635
- const { installedPackages, failedPackages } = await downloadDependenciesToDir(Object.values(artifactIdToArtifact), tmpDir);
110636
- const augmentedInstalledPackages = await extractDownloadedDependenciesToDir(dirToInstallDependencies, tmpDir, installedPackages);
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);
110637
110770
  const packageMetadatas = convertToPackageMetadatas(workspaceDir, augmentedInstalledPackages, directDependencies, artifactIdToArtifact);
110638
110771
  const packagePlacements = computePackagePlacements(packageMetadatas, resolve11(subprojectDir, "node_modules"));
110639
110772
  await hardlinkPackages(packagePlacements);
@@ -110938,8 +111071,8 @@ function tarjanAndCondensation(packageMetadatas) {
110938
111071
  }
110939
111072
 
110940
111073
  // dist/whole-program-code-aware-vulnerability-scanner/js/dependency-preparation.js
110941
- async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToArtifact, directDependencies, packageNamesToInstall) {
110942
- if (existsSync10(resolve12(subprojectDir, "node_modules")))
111074
+ async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToArtifact, directDependencies, packageNamesToInstall, preinstallDir) {
111075
+ if (existsSync11(resolve12(subprojectDir, "node_modules")))
110943
111076
  return { failedPackages: [], installedPackages: [] };
110944
111077
  const artifactToOriginal = /* @__PURE__ */ new Map();
110945
111078
  const transitiveDependenciesToInstall = Object.fromEntries(Object.entries(artifactIdToArtifact).filter(([_, dep]) => packageNamesToInstall.includes(getPackageName(dep))).map(([depId, dep]) => {
@@ -110947,7 +111080,7 @@ async function prepareNpmDependencies(subprojectDir, workspaceDir, artifactIdToA
110947
111080
  artifactToOriginal.set(artifact, dep);
110948
111081
  return [depId, artifact];
110949
111082
  }));
110950
- const result = await setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, transitiveDependenciesToInstall);
111083
+ const result = await setupDependenciesForAnalysis(subprojectDir, workspaceDir, directDependencies, transitiveDependenciesToInstall, preinstallDir);
110951
111084
  return {
110952
111085
  failedPackages: result.failedPackages.map((artifact) => artifactToOriginal.get(artifact)),
110953
111086
  installedPackages: result.installedPackages.map((artifact) => artifactToOriginal.get(artifact))
@@ -110967,6 +111100,11 @@ function convertToArtifactForInstallation(dep) {
110967
111100
  dependencies: dep.dependencies
110968
111101
  };
110969
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
+ }
110970
111108
 
110971
111109
  // dist/whole-program-code-aware-vulnerability-scanner/js/heuristics.js
110972
111110
  var lazyIndirectionBoundOptions = {
@@ -111230,7 +111368,7 @@ var JSCodeAwareVulnerabilityScanner = class _JSCodeAwareVulnerabilityScanner {
111230
111368
  ...new Set(state.vulnerabilities.flatMap((v) => Object.values(v.vulnChainDetails?.transitiveDependencies ?? {}).filter((d) => d.vulnerable === true).map((d) => d.packageName)))
111231
111369
  ];
111232
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])];
111233
- 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);
111234
111372
  this.packagesExcludedUnrelatedToHeuristic = failedPackages.map((p) => getPackageName(p));
111235
111373
  }
111236
111374
  async runAnalysis(vulnerabilities, heuristic, timeoutInSeconds, experiment, telemetryHandler, analyzerTelemetryHandler) {
@@ -111384,7 +111522,7 @@ function transformSourceLocations(fileMappings, detectedOccurrences) {
111384
111522
  // dist/whole-program-code-aware-vulnerability-scanner/go/go-code-aware-vulnerability-scanner.js
111385
111523
  var import_lodash11 = __toESM(require_lodash(), 1);
111386
111524
  import assert5 from "assert";
111387
- import { existsSync as existsSync11, createReadStream as createReadStream2, createWriteStream as createWriteStream4 } from "fs";
111525
+ import { existsSync as existsSync12, createReadStream as createReadStream2, createWriteStream as createWriteStream4 } from "fs";
111388
111526
  import { readFile as readFile10, rm as rm4, cp as cp6 } from "fs/promises";
111389
111527
  import zlib2 from "zlib";
111390
111528
  import { join as join16, resolve as resolve14, sep as sep3 } from "path";
@@ -111423,7 +111561,7 @@ var GoCodeAwareVulnerabilityScanner = class {
111423
111561
  }
111424
111562
  async runAnalysis(vulns, heuristic, timeoutInSeconds, _experiment, telemetryHandler, analyzerTelemetryHandler) {
111425
111563
  logger.info("Started instantiating Go code-aware analysis");
111426
- if (!existsSync11(join16(this.projectDir, "go.mod")))
111564
+ if (!existsSync12(join16(this.projectDir, "go.mod")))
111427
111565
  throw new Error("go.mod file not found in the project directory");
111428
111566
  const { memoryLimitInMB } = this.options;
111429
111567
  const tmpDir = await createTmpDirectory("goana-output");
@@ -111504,7 +111642,7 @@ ${stderr}`);
111504
111642
  try {
111505
111643
  await cp6(Dir, projectDir, { recursive: true });
111506
111644
  const projGoMod = resolve14(projectDir, "go.mod");
111507
- if (!existsSync11(projGoMod))
111645
+ if (!existsSync12(projGoMod))
111508
111646
  await cp6(GoMod, projGoMod);
111509
111647
  await exec2(cmdt`chmod --recursive +w ${projectDir}`);
111510
111648
  await runGoModTidy(projectDir);
@@ -111532,7 +111670,7 @@ ${stderr}`);
111532
111670
  }
111533
111671
  static async runOnAlreadyDownloadedPackages(packages, vuln, options) {
111534
111672
  for (const pkg of packages)
111535
- assert5(existsSync11(join16(pkg, "go.mod")), `${pkg} does not contain a go.mod file`);
111673
+ assert5(existsSync12(join16(pkg, "go.mod")), `${pkg} does not contain a go.mod file`);
111536
111674
  const [app, ...dependencies] = packages;
111537
111675
  const projectDir = await createTmpDirectory("go-run-on-already-downloaded-packages-");
111538
111676
  try {
@@ -111563,6 +111701,8 @@ ${stderr}`);
111563
111701
  await rm4(projectDir, { recursive: true, force: true });
111564
111702
  }
111565
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.
111566
111706
  getPackagesExcludedUnrelatedToHeuristic() {
111567
111707
  return [];
111568
111708
  }
@@ -111570,7 +111710,7 @@ ${stderr}`);
111570
111710
 
111571
111711
  // dist/whole-program-code-aware-vulnerability-scanner/rust/rust-code-aware-vulnerability-scanner.js
111572
111712
  var import_lodash12 = __toESM(require_lodash(), 1);
111573
- import { existsSync as existsSync12 } from "node:fs";
111713
+ import { existsSync as existsSync13 } from "node:fs";
111574
111714
  import { readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
111575
111715
  import { basename as basename10, dirname as dirname14, resolve as resolve15 } from "node:path";
111576
111716
 
@@ -111671,7 +111811,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111671
111811
  let appCrateName;
111672
111812
  const appSrc = [];
111673
111813
  const dependencies = {};
111674
- const appCrateInfo = existsSync12(cargoTomlPath) ? await getCrateInfo(cargoTomlPath) : void 0;
111814
+ const appCrateInfo = existsSync13(cargoTomlPath) ? await getCrateInfo(cargoTomlPath) : void 0;
111675
111815
  if (appCrateInfo?.name) {
111676
111816
  appSrc.push(...i([appCrateInfo.lib, ...appCrateInfo.examples ?? [], ...appCrateInfo.tests ?? []]));
111677
111817
  appCrateName = appCrateInfo.name.replaceAll("-", "_");
@@ -111783,7 +111923,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111783
111923
  const appDependencies = {};
111784
111924
  if (rustDependencyChain[0].src && rustDependencyChain[0].src.length > 0) {
111785
111925
  const appCargoTomlPath = resolve15(rustDependencyChain[0].src[0], "..", "Cargo.toml");
111786
- if (existsSync12(appCargoTomlPath)) {
111926
+ if (existsSync13(appCargoTomlPath)) {
111787
111927
  const cargoTomlDeps = await extractDependenciesFromCargoToml(appCargoTomlPath);
111788
111928
  for (const [packageName, names] of cargoTomlDeps.entries()) {
111789
111929
  const depId = packageNameToId.get(packageName);
@@ -111810,7 +111950,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111810
111950
  const dependencies = {};
111811
111951
  if (dep.src && dep.src.length > 0) {
111812
111952
  const depCargoTomlPath = resolve15(dep.src[0], "..", "Cargo.toml");
111813
- if (existsSync12(depCargoTomlPath)) {
111953
+ if (existsSync13(depCargoTomlPath)) {
111814
111954
  const cargoTomlDeps = await extractDependenciesFromCargoToml(depCargoTomlPath);
111815
111955
  for (const [packageName, names] of cargoTomlDeps.entries()) {
111816
111956
  const transDepId = packageNameToId.get(packageName);
@@ -111939,7 +112079,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111939
112079
  };
111940
112080
  }
111941
112081
  getPackagesExcludedUnrelatedToHeuristic() {
111942
- return Object.entries(this.deps).filter(([_, { src, bin }]) => !src?.length && (!bin || bin.some((f2) => !existsSync12(f2)))).map(([packageId]) => this.depIdToPurl.get(packageId)?.name).filter((name2) => name2 !== void 0).map((name2) => name2);
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);
111943
112083
  }
111944
112084
  };
111945
112085
  async function convertDependencyChain3(dependencyChain, tmpDir) {
@@ -111971,7 +112111,7 @@ function getCargoLocalRepositoryPaths() {
111971
112111
  // Cargo git dependencies
111972
112112
  { path: resolve15(cargoHome, "git", "checkouts"), type: "git" }
111973
112113
  ];
111974
- return repositories.filter((repo) => existsSync12(repo.path));
112114
+ return repositories.filter((repo) => existsSync13(repo.path));
111975
112115
  }
111976
112116
  async function findCargoPackageInLocalRepo(repo, packageName, version3, tmpDir) {
111977
112117
  try {
@@ -112011,10 +112151,10 @@ async function findCargoPackageInLocalRepo(repo, packageName, version3, tmpDir)
112011
112151
  }
112012
112152
  async function extractCargoCrate(crateFilePath, packageName, version3, tmpDir) {
112013
112153
  const packageDir = resolve15(tmpDir, `${packageName}-${version3}`);
112014
- if (existsSync12(packageDir)) {
112154
+ if (existsSync13(packageDir)) {
112015
112155
  try {
112016
112156
  const cargoTomlPath = resolve15(packageDir, "Cargo.toml");
112017
- if (existsSync12(cargoTomlPath)) {
112157
+ if (existsSync13(cargoTomlPath)) {
112018
112158
  const depCrateInfo = await getCrateInfo(cargoTomlPath);
112019
112159
  return [depCrateInfo.lib];
112020
112160
  }
@@ -112034,7 +112174,7 @@ async function extractCargoCrate(crateFilePath, packageName, version3, tmpDir) {
112034
112174
  }
112035
112175
  async function downloadAndExtractCargoCrate(packageName, version3, tmpDir) {
112036
112176
  const packageFile = resolve15(tmpDir, `${packageName}-${version3}.crate`);
112037
- if (!existsSync12(packageFile)) {
112177
+ if (!existsSync13(packageFile)) {
112038
112178
  const packageUrl = getUrlForCrate(packageName, version3);
112039
112179
  const success = await downloadFile(packageUrl, packageFile);
112040
112180
  if (!success) {
@@ -112067,7 +112207,7 @@ async function convertSocketArtifacts3(artifacts, tmpDir, artifactNameToId) {
112067
112207
  const dependencies = {};
112068
112208
  if (src && src.length > 0) {
112069
112209
  const cargoTomlPath = resolve15(dirname14(src[0]), "Cargo.toml");
112070
- if (existsSync12(cargoTomlPath)) {
112210
+ if (existsSync13(cargoTomlPath)) {
112071
112211
  const cargoTomlDeps = await extractDependenciesFromCargoToml(cargoTomlPath);
112072
112212
  for (const [packageName, names] of cargoTomlDeps.entries()) {
112073
112213
  const depArtifactId = artifactNameToId.get(packageName);
@@ -112340,12 +112480,12 @@ var PythonCodeAwareVulnerabilityScanner = class {
112340
112480
  this.projectDir = projectDir;
112341
112481
  this.vm = new PythonVersionsManager(state.rootWorkingDir);
112342
112482
  }
112343
- async prepareDependencies(preInstalledDepInfos, vulns, heuristic) {
112483
+ async prepareDependencies(preInstalledDepInfos, vulns, heuristic, preinstallDir) {
112344
112484
  const packagesToExclude = heuristic.getPackagesToExcludeFromAnalysis?.(vulns);
112345
112485
  const packagesToInstall = uniqBy(preInstalledDepInfos.filter((n) => !packagesToExclude?.has(n.packageName)), "packageName");
112346
- if (!await this.tryUsingPreinstalledVirtualEnv(packagesToInstall)) {
112486
+ if (!await this.tryUsingPreinstalledVirtualEnv(packagesToInstall) && !(preinstallDir && await this.tryUsingVenvFromPreinstallDir(preinstallDir))) {
112347
112487
  logger.info(`Setting up virtual environment`);
112348
- await this.prepareVirtualEnv(packagesToInstall);
112488
+ await this.prepareVirtualEnv(packagesToInstall, preinstallDir);
112349
112489
  logger.info("Done setting up virtual environment");
112350
112490
  }
112351
112491
  }
@@ -112560,7 +112700,7 @@ ${msg}`;
112560
112700
  // public for testing only
112561
112701
  async tryUsingPreinstalledVirtualEnv(packages) {
112562
112702
  const preinstallVirtualEnvPath = resolve17(this.projectDir, ".venv");
112563
- if (!existsSync13(preinstallVirtualEnvPath))
112703
+ if (!existsSync14(preinstallVirtualEnvPath))
112564
112704
  return false;
112565
112705
  logger.info(`Checking preinstalled virtual environment at ${preinstallVirtualEnvPath}`);
112566
112706
  try {
@@ -112581,12 +112721,20 @@ ${msg}`;
112581
112721
  await this.updateVirtualEnvInfo(this.projectDir);
112582
112722
  return true;
112583
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
+ }
112584
112732
  // public for testing only
112585
- async prepareVirtualEnv(packages) {
112733
+ async prepareVirtualEnv(packages, preinstallDir) {
112586
112734
  const uvCommand = getUvCommand();
112587
112735
  if (!await hasUv())
112588
112736
  throw new Error("uv (https://docs.astral.sh/uv/) is missing, but is required for Python analysis");
112589
- const tmpDir = await createTmpDirectory("coana-python-analysis-venv");
112737
+ const tmpDir = preinstallDir ?? await createTmpDirectory("coana-python-analysis-venv");
112590
112738
  const virtualEnvFolder = join17(tmpDir, ".venv");
112591
112739
  const pythonExecutable = await this.vm.getPythonExecutableForWorkspace(this.projectDir, false);
112592
112740
  await exec2(cmdt`${uvCommand} venv --python ${pythonExecutable} .venv`, tmpDir);
@@ -112659,7 +112807,7 @@ ${msg}`;
112659
112807
  await this.updateVirtualEnvInfo(tmpDir, installStats);
112660
112808
  }
112661
112809
  async updateVirtualEnvInfo(virtualEnvFolder, packageInstallationStats) {
112662
- const entries = await readdir4(join17(virtualEnvFolder, ".venv", "lib"));
112810
+ const entries = await readdir6(join17(virtualEnvFolder, ".venv", "lib"));
112663
112811
  const pydir = entries.find((entry) => entry.startsWith("python"));
112664
112812
  assert6(pydir, `No python* directory found in virtual environment: ${util5.inspect(entries)}`);
112665
112813
  this.virtualEnvInfo = {
@@ -112756,7 +112904,7 @@ async function setupMambalade() {
112756
112904
  logger.debug(`Using Python interpreter: ${python}`);
112757
112905
  await exec2(cmdt`${uvCommand} venv --no-project --no-config --python=${python} .`, venvDir);
112758
112906
  const mambaladeWheelsPath = ToolPathResolver.mambaladeDistPath;
112759
- const mambaladeWheels = (await readdir4(mambaladeWheelsPath)).filter((f2) => f2.endsWith(".whl")).map((f2) => join17(mambaladeWheelsPath, f2));
112907
+ const mambaladeWheels = (await readdir6(mambaladeWheelsPath)).filter((f2) => f2.endsWith(".whl")).map((f2) => join17(mambaladeWheelsPath, f2));
112760
112908
  if (!mambaladeWheels.length)
112761
112909
  throw new Error(`No mambalade wheel files found in ${mambaladeWheelsPath}`);
112762
112910
  logger.debug(`Installing mambalade wheels: ${mambaladeWheels.join(", ")}`);
@@ -112892,6 +113040,13 @@ async function processProject(projectDir) {
112892
113040
  }, 4)).flat());
112893
113041
  }
112894
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
+
112895
113050
  // dist/analyzers/pip-analyzer.js
112896
113051
  var { once: once4 } = import_lodash16.default;
112897
113052
  var PipAnalyzer = class {
@@ -112910,9 +113065,16 @@ var PipAnalyzer = class {
112910
113065
  this.heuristic = MambaladeHeuristics.createOnlyVulnPathPackagesHeuristic(this.preInstalledDepInfos);
112911
113066
  }
112912
113067
  prepareScanner = once4(async () => {
112913
- 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);
112914
113069
  return this.scanner;
112915
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
+ }
112916
113078
  async runPhantomDependencyAnalysis() {
112917
113079
  const info = (await this.prepareScanner()).getVirtualEnvInfo();
112918
113080
  assert7(info !== void 0);
@@ -112935,6 +113097,7 @@ var PipAnalyzer = class {
112935
113097
  };
112936
113098
  try {
112937
113099
  const scanner = await this.prepareScanner();
113100
+ checkForInstallErrors(scanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
112938
113101
  const venvInfo = scanner.getVirtualEnvInfo();
112939
113102
  this.preinstalledDependencies = venvInfo !== void 0 && !venvInfo.temporary ? "YES" : "NO";
112940
113103
  return await analyzeWithHeuristics(this.state, vulns, [this.heuristic], false, scanner, wrappedCollector, statusUpdater);
@@ -113411,6 +113574,15 @@ var GoAnalyzer = class {
113411
113574
  this.state = state;
113412
113575
  this.projectDir = projectDir;
113413
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
+ }
113414
113586
  async runPhantomDependencyAnalysis() {
113415
113587
  return void 0;
113416
113588
  }
@@ -113498,9 +113670,16 @@ var MavenAnalyzer = class {
113498
113670
  constructor(state) {
113499
113671
  this.state = state;
113500
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
+ }
113501
113680
  async runPhantomDependencyAnalysis() {
113502
113681
  return withTmpDirectory("maven-phantom-dependency-analysis", async (tmpDir) => {
113503
- const scanner = this.state.workspaceData.type === "coana" ? await JavaCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, tmpDir) : await JavaCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.artifacts, tmpDir);
113682
+ const scanner = await this.createScanner(tmpDir);
113504
113683
  return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
113505
113684
  });
113506
113685
  }
@@ -113512,11 +113691,17 @@ var MavenAnalyzer = class {
113512
113691
  }
113513
113692
  analysisMetadataCollector?.(metadata);
113514
113693
  };
113515
- return withTmpDirectory("maven-reachability-analysis", async (tmpDir) => {
113516
- const scanner = this.state.workspaceData.type === "coana" ? await JavaCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, tmpDir, statusUpdater) : await JavaCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
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);
113517
113698
  const heuristicsInOrder = [AlucardHeuristics.ALL_PACKAGES];
113518
113699
  return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
113519
- });
113700
+ };
113701
+ if (preinstallDir) {
113702
+ return runWithTmpDir(preinstallDir);
113703
+ }
113704
+ return withTmpDirectory("maven-reachability-analysis", runWithTmpDir);
113520
113705
  }
113521
113706
  async getWorkspaceDiagnostics() {
113522
113707
  let sourceFilesDetected;
@@ -113545,7 +113730,7 @@ var MavenAnalyzer = class {
113545
113730
  // dist/analyzers/npm-analyzer.js
113546
113731
  var import_lodash19 = __toESM(require_lodash(), 1);
113547
113732
  var import_picomatch4 = __toESM(require_picomatch2(), 1);
113548
- import { existsSync as existsSync14 } from "fs";
113733
+ import { existsSync as existsSync16 } from "fs";
113549
113734
  import { rm as rm6 } from "fs/promises";
113550
113735
  import { relative as relative8, resolve as resolve20 } from "path";
113551
113736
 
@@ -113572,6 +113757,17 @@ var NpmAnalyzer = class {
113572
113757
  this.state = state;
113573
113758
  this.projectDir = projectDir;
113574
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
+ }
113575
113771
  async runPhantomDependencyAnalysis() {
113576
113772
  try {
113577
113773
  return (await runJellyPhantomDependencyAnalysis(this.projectDir, this.state.reachabilityAnalysisOptions)).map((r) => r.name);
@@ -113581,7 +113777,7 @@ var NpmAnalyzer = class {
113581
113777
  }
113582
113778
  async runReachabilityAnalysis(vulns, analysisMetadataCollector, statusUpdater) {
113583
113779
  const heuristicsInOrder = this.state.otherAnalysisOptions.lightweightReachability ? [heuristics.IGNORE_DEPENDENCIES_AND_MAX_ROUNDS_3] : [heuristics.ONLY_VULN_PATH_PACKAGES_EXCEPT_VULNERABLE_PACKAGE];
113584
- const nodeModulesAlreadyExisted = existsSync14(resolve20(this.state.subprojectDir, "node_modules"));
113780
+ const nodeModulesAlreadyExisted = existsSync16(resolve20(this.state.subprojectDir, "node_modules"));
113585
113781
  this.preinstalledDependencies = nodeModulesAlreadyExisted ? "YES" : "NO";
113586
113782
  const wrappedCollector = (metadata) => {
113587
113783
  const jellyDiagnostics = metadata.analysisDiagnostics;
@@ -113593,6 +113789,7 @@ var NpmAnalyzer = class {
113593
113789
  try {
113594
113790
  const vulnerabilityScanner = new JSCodeAwareVulnerabilityScanner(this.state.rootWorkingDir, this.projectDir, this.state.reachabilityAnalysisOptions);
113595
113791
  await vulnerabilityScanner.prepareDependencies(this.state, heuristicsInOrder[0]);
113792
+ checkForInstallErrors(vulnerabilityScanner.getPackagesExcludedUnrelatedToHeuristic(), this.state.otherAnalysisOptions);
113596
113793
  logger.info(`Running import reachability analysis for ${vulns.length} ${pluralize(vulns.length, "vulnerability")}`);
113597
113794
  let reachable;
113598
113795
  const ghsaIds = extractGhsaIdsFromVulnUrls(vulns.map((v) => v.url));
@@ -113706,9 +113903,9 @@ ${e.stack}` : String(e),
113706
113903
  return res;
113707
113904
  } finally {
113708
113905
  if (!nodeModulesAlreadyExisted) {
113709
- if (existsSync14(resolve20(this.state.subprojectDir, "node_modules")))
113906
+ if (existsSync16(resolve20(this.state.subprojectDir, "node_modules")))
113710
113907
  await rm6(resolve20(this.state.subprojectDir, "node_modules"), { recursive: true });
113711
- if (existsSync14(resolve20(this.projectDir, "node_modules")))
113908
+ if (existsSync16(resolve20(this.projectDir, "node_modules")))
113712
113909
  await rm6(resolve20(this.projectDir, "node_modules"), { recursive: true });
113713
113910
  }
113714
113911
  }
@@ -113749,9 +113946,16 @@ var NugetAnalyzer = class {
113749
113946
  constructor(state) {
113750
113947
  this.state = state;
113751
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
+ }
113752
113956
  async runPhantomDependencyAnalysis() {
113753
113957
  return withTmpDirectory("nuget-phantom-dependency-analysis", async (tmpDir) => {
113754
- const scanner = this.state.workspaceData.type === "coana" ? DotnetCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree) : await DotnetCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.manifestFiles, this.state.workspaceData.data.artifacts, tmpDir);
113958
+ const scanner = await this.createScanner(tmpDir);
113755
113959
  return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
113756
113960
  });
113757
113961
  }
@@ -113763,11 +113967,17 @@ var NugetAnalyzer = class {
113763
113967
  }
113764
113968
  analysisMetadataCollector?.(metadata);
113765
113969
  };
113766
- return withTmpDirectory("nuget-reachability-analysis", async (tmpDir) => {
113767
- const scanner = this.state.workspaceData.type === "coana" ? DotnetCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, statusUpdater) : await DotnetCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspaceData.data.manifestFiles, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
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);
113768
113974
  const heuristicsInOrder = [CocoaHeuristics.ALL_PACKAGES];
113769
113975
  return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
113770
- });
113976
+ };
113977
+ if (preinstallDir) {
113978
+ return runWithTmpDir(preinstallDir);
113979
+ }
113980
+ return withTmpDirectory("nuget-reachability-analysis", runWithTmpDir);
113771
113981
  }
113772
113982
  async getWorkspaceDiagnostics() {
113773
113983
  let sourceFilesDetected;
@@ -113795,13 +114005,13 @@ var NugetAnalyzer = class {
113795
114005
 
113796
114006
  // dist/analyzers/ruby-analyzer.js
113797
114007
  var import_lodash21 = __toESM(require_lodash(), 1);
113798
- import { existsSync as existsSync16 } from "fs";
114008
+ import { existsSync as existsSync18 } from "fs";
113799
114009
  import { resolve as resolve21 } from "path";
113800
114010
 
113801
114011
  // dist/whole-program-code-aware-vulnerability-scanner/ruby/ruby-code-aware-vulnerability-scanner.js
113802
114012
  var import_lodash20 = __toESM(require_lodash(), 1);
113803
- import { createWriteStream as createWriteStream5, existsSync as existsSync15 } from "fs";
113804
- import { mkdir as mkdir9, readdir as readdir5, readFile as readFile13, rm as rm7 } from "fs/promises";
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";
113805
114015
  import { join as join18, relative as relative9 } from "path";
113806
114016
  import { pipeline as pipeline3 } from "stream/promises";
113807
114017
  var PRINT_ANALYSIS_COMMAND = false;
@@ -113818,12 +114028,12 @@ var RubyCodeAwareVulnerabilityScanner = class {
113818
114028
  this.projectDir = projectDir;
113819
114029
  this.options = options;
113820
114030
  }
113821
- async prepareDependencies(preInstalledDepInfos, vulns, heuristic) {
113822
- const vendorDir = join18(this.projectDir, "vendor");
113823
- if (existsSync15(vendorDir)) {
114031
+ async prepareDependencies(preInstalledDepInfos, vulns, heuristic, preinstallDir) {
114032
+ const vendorDir = preinstallDir ?? join18(this.projectDir, "vendor");
114033
+ if (existsSync17(vendorDir)) {
113824
114034
  logger.info(`Vendor directory already exists at ${vendorDir}, skipping gem installation`);
113825
114035
  this.vendorDir = vendorDir;
113826
- this.vendorDirWasCreated = false;
114036
+ this.vendorDirWasCreated = !preinstallDir;
113827
114037
  return;
113828
114038
  }
113829
114039
  const packagesToIncludeNames = heuristic.getPackagesToIncludeInAnalysis?.(vulns)?.map((p) => p.packageName);
@@ -113854,7 +114064,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113854
114064
  if (!this.vendorDir)
113855
114065
  throw new Error("Assertion error: The vendor directory is not correctly initialized");
113856
114066
  const analyzerPath = ToolPathResolver.callgraphReachabilityAnalyzersCliPath;
113857
- if (!existsSync15(analyzerPath))
114067
+ if (!existsSync17(analyzerPath))
113858
114068
  throw new Error(`callgraph-reachability-analyzers CLI not found at ${analyzerPath}`);
113859
114069
  const vulnAccPaths = sortedUniq2(vulns.flatMap((v) => v.vulnerabilityAccessPaths).sort());
113860
114070
  const vulnsOutputFile = join18(tmpDir, "vulns.json");
@@ -113865,12 +114075,12 @@ var RubyCodeAwareVulnerabilityScanner = class {
113865
114075
  const loadPaths = Array.from(loadPathsToPackageNames.keys());
113866
114076
  if (failedToFindLoadPath.length > 0) {
113867
114077
  this.packagesExcludedUnrelatedToHeuristic.push(...failedToFindLoadPath.map((p) => p.packageName));
113868
- logger.warn(`Failed to find package installation path for ${failedToFindLoadPath.map((p) => p.packageName).join(", ")}`);
114078
+ logger.debug(`Failed to find package installation path for ${failedToFindLoadPath.map((p) => p.packageName).join(", ")}`);
113869
114079
  }
113870
114080
  if (loadPaths.length === 0) {
113871
114081
  return {
113872
114082
  type: "error",
113873
- message: "No load paths found for the packages to analyze"
114083
+ message: `${FAILED_TO_INSTALL_PACKAGE_KEY}No load paths found for the packages to analyze`
113874
114084
  };
113875
114085
  }
113876
114086
  const cmd = cmdt`
@@ -113929,7 +114139,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113929
114139
  return this.packagesExcludedUnrelatedToHeuristic;
113930
114140
  }
113931
114141
  async cleanup() {
113932
- if (this.vendorDirWasCreated && this.vendorDir && existsSync15(this.vendorDir)) {
114142
+ if (this.vendorDirWasCreated && this.vendorDir && existsSync17(this.vendorDir)) {
113933
114143
  logger.info(`Deleting auto-generated vendor directory at ${this.vendorDir}`);
113934
114144
  await rm7(this.vendorDir, { recursive: true, force: true }).catch(() => {
113935
114145
  });
@@ -113945,7 +114155,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113945
114155
  if (this.vendorDirWasCreated) {
113946
114156
  for (const pkg of packagesToAnalyze) {
113947
114157
  const libPath = join18(this.vendorDir, `${pkg.packageName}-${pkg.version}`, "lib");
113948
- if (existsSync15(libPath))
114158
+ if (existsSync17(libPath))
113949
114159
  loadPathsToPackageNames.set(libPath, `${pkg.packageName}@${pkg.version}`);
113950
114160
  else
113951
114161
  failedToFindLoadPath.push(pkg);
@@ -113953,13 +114163,13 @@ var RubyCodeAwareVulnerabilityScanner = class {
113953
114163
  return { loadPathsToPackageNames, failedToFindLoadPath };
113954
114164
  }
113955
114165
  const bundlerGemsDir = join18(this.vendorDir, "bundle", "ruby");
113956
- if (existsSync15(bundlerGemsDir)) {
113957
- const rubyVersions = await readdir5(bundlerGemsDir);
114166
+ if (existsSync17(bundlerGemsDir)) {
114167
+ const rubyVersions = await readdir7(bundlerGemsDir);
113958
114168
  for (const rubyVersion of rubyVersions) {
113959
114169
  const gemsDir = join18(bundlerGemsDir, rubyVersion, "gems");
113960
- if (existsSync15(gemsDir)) {
114170
+ if (existsSync17(gemsDir)) {
113961
114171
  const nameToEntry = /* @__PURE__ */ new Map();
113962
- for (const entry of await readdir5(gemsDir, { withFileTypes: true }))
114172
+ for (const entry of await readdir7(gemsDir, { withFileTypes: true }))
113963
114173
  if (entry.isDirectory()) {
113964
114174
  const match2 = entry.name.match(/^([\w-_]+)-(\d+\.\d+\.\d+)/);
113965
114175
  if (match2)
@@ -113970,7 +114180,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113970
114180
  if (!entry)
113971
114181
  continue;
113972
114182
  const libDir = join18(gemsDir, entry, "lib");
113973
- if (existsSync15(libDir))
114183
+ if (existsSync17(libDir))
113974
114184
  loadPathsToPackageNames.set(libDir, `${pkg.packageName}@${pkg.version}`);
113975
114185
  else
113976
114186
  failedToFindLoadPath.push(pkg);
@@ -113980,7 +114190,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113980
114190
  } else
113981
114191
  for (const pkg of packagesToAnalyze) {
113982
114192
  const libPath = join18(this.vendorDir, `${pkg.packageName}-${pkg.version}`, "lib");
113983
- if (existsSync15(libPath))
114193
+ if (existsSync17(libPath))
113984
114194
  loadPathsToPackageNames.set(libPath, `${pkg.packageName}@${pkg.version}`);
113985
114195
  else
113986
114196
  failedToFindLoadPath.push(pkg);
@@ -113990,7 +114200,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
113990
114200
  };
113991
114201
  async function downloadAndExtractGem(gemName, version3, vendorDir) {
113992
114202
  const gemDir = join18(vendorDir, `${gemName}-${version3}`);
113993
- if (existsSync15(gemDir)) {
114203
+ if (existsSync17(gemDir)) {
113994
114204
  logger.debug(`Gem ${gemName}@${version3} already extracted`);
113995
114205
  return;
113996
114206
  }
@@ -114043,9 +114253,16 @@ var RubyGemsAnalyzer = class {
114043
114253
  this.scanner = new RubyCodeAwareVulnerabilityScanner(state, projectDir);
114044
114254
  }
114045
114255
  prepareScanner = once5(async () => {
114046
- 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);
114047
114257
  return this.scanner;
114048
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
+ }
114049
114266
  async runPhantomDependencyAnalysis() {
114050
114267
  return void 0;
114051
114268
  }
@@ -114057,9 +114274,11 @@ var RubyGemsAnalyzer = class {
114057
114274
  }
114058
114275
  analysisMetadataCollector?.(metadata);
114059
114276
  };
114060
- this.preinstalledDependencies = existsSync16(resolve21(this.projectDir, "vendor")) ? "YES" : "NO";
114277
+ this.preinstalledDependencies = existsSync18(resolve21(this.projectDir, "vendor")) ? "YES" : "NO";
114061
114278
  try {
114062
- return await analyzeWithHeuristics(this.state, vulns, [RubyHeuristics.ONLY_VULN_PATH_PACKAGES], false, await this.prepareScanner(), wrappedCollector, statusUpdater);
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);
114063
114282
  } finally {
114064
114283
  await this.scanner.cleanup();
114065
114284
  }
@@ -114117,9 +114336,16 @@ var RustAnalyzer = class {
114117
114336
  constructor(state) {
114118
114337
  this.state = state;
114119
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
+ }
114120
114346
  async runPhantomDependencyAnalysis() {
114121
114347
  return withTmpDirectory("cargo-phantom-dependency-analysis", async (tmpDir) => {
114122
- const scanner = this.state.workspaceData.type === "coana" ? RustCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree) : await RustCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspacePath, this.state.workspaceData.data.artifacts, tmpDir);
114348
+ const scanner = await this.createScanner(tmpDir);
114123
114349
  return scanner.runPhantomDependencyAnalysis(this.state.reachabilityAnalysisOptions.timeoutSeconds.allVulnRuns);
114124
114350
  });
114125
114351
  }
@@ -114131,11 +114357,17 @@ var RustAnalyzer = class {
114131
114357
  }
114132
114358
  analysisMetadataCollector?.(metadata);
114133
114359
  };
114134
- return withTmpDirectory("cargo-reachability-analysis", async (tmpDir) => {
114135
- const scanner = this.state.workspaceData.type === "coana" ? RustCodeAwareVulnerabilityScanner.initFromDependencyTree(this.state.workspaceData.data.dependencyTree, statusUpdater) : await RustCodeAwareVulnerabilityScanner.initFromSocketArtifacts(this.state.subprojectDir, this.state.workspacePath, this.state.workspaceData.data.artifacts, tmpDir, statusUpdater);
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);
114136
114364
  const heuristicsInOrder = [RusticaHeuristics.ALL_PACKAGES];
114137
114365
  return await analyzeWithHeuristics(this.state, vulns, heuristicsInOrder, false, scanner, wrappedCollector, statusUpdater);
114138
- });
114366
+ };
114367
+ if (preinstallDir) {
114368
+ return runWithTmpDir(preinstallDir);
114369
+ }
114370
+ return withTmpDirectory("cargo-reachability-analysis", runWithTmpDir);
114139
114371
  }
114140
114372
  async getWorkspaceDiagnostics() {
114141
114373
  let sourceFilesDetected;
@@ -114174,6 +114406,17 @@ var ecosystemAnalyzer = {
114174
114406
  };
114175
114407
  var apiKey2 = COANA_API_KEY ? { type: "present", value: COANA_API_KEY } : { type: "missing" };
114176
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
+ }
114177
114420
  async function runReachabilityAnalysis(state) {
114178
114421
  const projectDir = resolve22(state.subprojectDir, state.workspacePath);
114179
114422
  const ecosystem = state.workspaceData.data.type;
@@ -114205,9 +114448,30 @@ async function getReachabilityAnalyzersStateFromInput(rootWorkingDir, subproject
114205
114448
  }
114206
114449
 
114207
114450
  // dist/reachability-analyzers-cli.js
114208
- 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 () => {
114209
114473
  const state = await getReachabilityAnalyzersStateFromInput(rootWorkingDir, subprojectDir, workspacePath, options.inputFile);
114210
- const result = await runReachabilityAnalysis(state);
114474
+ const result = await installDependenciesForAnalysis(state, options.preinstallDir);
114211
114475
  if (options.outputFile) {
114212
114476
  logger.debug("Writing result to file", options.outputFile);
114213
114477
  await writeFile10(options.outputFile, JSON.stringify({ result }));
@@ -114263,7 +114527,7 @@ var runOnPackageRegistryPackageCmd = new Command().name("runOnPackageRegistryPac
114263
114527
  }
114264
114528
  }, "reachability-analyzer");
114265
114529
  });
114266
- 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();
114267
114531
  /*! Bundled license information:
114268
114532
 
114269
114533
  safe-buffer/index.js: