@coana-tech/cli 14.11.7 → 14.11.9

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 CHANGED
@@ -209443,7 +209443,7 @@ function shouldIgnoreDir(dir) {
209443
209443
  return dirsToIgnore.includes(dir);
209444
209444
  }
209445
209445
  function shouldIgnoreDueToExcludeDirsOrChangedFiles({ mainProjectDir, excludeDirs, changedFiles }, fullPath) {
209446
- const relativeToProjectDir = relative9(mainProjectDir, fullPath);
209446
+ const relativeToProjectDir = relative9(mainProjectDir, fullPath) || ".";
209447
209447
  return !!(isMatch3(relativeToProjectDir, excludeDirs) || changedFiles && !changedFiles.some((changedFile) => changedFile.startsWith(relativeToProjectDir)));
209448
209448
  }
209449
209449
 
@@ -210096,7 +210096,7 @@ function inferWorkspaceFromManifestPath(ecosystem, manifestPath, properPythonPro
210096
210096
  return dirname8(manifestPath) || ".";
210097
210097
  }
210098
210098
  default: {
210099
- return void 0;
210099
+ return ".";
210100
210100
  }
210101
210101
  }
210102
210102
  }
@@ -210384,6 +210384,8 @@ function toSocketReachabilitySchema(vulnerability) {
210384
210384
  return { type: "error", error: vulnerability.codeAwareScanResult.message };
210385
210385
  }
210386
210386
  if (vulnerability.codeAwareScanResult.type === "otherError") {
210387
+ if (vulnerability.codeAwareScanResult.message.includes("Reachability analysis for languages using"))
210388
+ return { type: "unknown" };
210387
210389
  return { type: "error", error: vulnerability.codeAwareScanResult.message };
210388
210390
  }
210389
210391
  if (vulnerability.codeAwareScanResult.type === "success") {
@@ -225338,7 +225340,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
225338
225340
  }
225339
225341
 
225340
225342
  // dist/version.js
225341
- var version2 = "14.11.7";
225343
+ var version2 = "14.11.9";
225342
225344
 
225343
225345
  // dist/cli-core.js
225344
225346
  var { mapValues, omit, partition, pick } = import_lodash15.default;
@@ -225423,9 +225425,18 @@ var CliCore = class {
225423
225425
  if (this.options.ecosystems)
225424
225426
  this.options.ecosystems.forEach((ecosystem) => {
225425
225427
  if (!ECOSYSTEMS_WITH_TRADITIONAL_SCA_SUPPORT.includes(ecosystem)) {
225426
- throw new Error(`Invalid ecosystem: ${ecosystem}.`);
225428
+ throw new Error(`Invalid ecosystem: ${ecosystem}. Supported ecosystems are: ${ECOSYSTEMS_WITH_TRADITIONAL_SCA_SUPPORT.join(", ")}`);
225427
225429
  }
225428
225430
  });
225431
+ if (this.options.purlTypes) {
225432
+ this.options.purlTypes.forEach((purlType) => {
225433
+ try {
225434
+ getAdvisoryEcosystemFromPurlType(purlType);
225435
+ } catch (e) {
225436
+ throw new Error(`Invalid purl type: ${purlType}. Supported purl types are: ${ECOSYSTEMS_WITH_TRADITIONAL_SCA_SUPPORT.map((ecosystem) => getPurlType(ecosystem)).join(", ")}`);
225437
+ }
225438
+ });
225439
+ }
225429
225440
  if (this.options.manifestsTarHash && !this.options.socketMode) {
225430
225441
  throw new Error("The --manifests-tar-hash option is only supported when using --socket-mode");
225431
225442
  }
@@ -225494,6 +225505,10 @@ var CliCore = class {
225494
225505
  const vulnsWithResults = [];
225495
225506
  for (const [ecosystem, workspaceToAnalysisData] of Object.entries(ecosystemToWorkspaceToAnalysisData)) {
225496
225507
  this.sendProgress("RUN_ON_SUBPROJECT", true, this.rootWorkingDirectory);
225508
+ const isEcosystemToAnalyze = !this.options.purlTypes || this.options.purlTypes.some((purlType) => getAdvisoryEcosystemFromPurlType(purlType) === ecosystem);
225509
+ if (!isEcosystemToAnalyze) {
225510
+ logger.info(`Skipping reachability analysis for ecosystem ${getPurlType(ecosystem)} due to it not being included in the list of ecosystems to analyze.`);
225511
+ }
225497
225512
  vulnsWithResults.push(...Object.values(await this.runReachabilityAnalysisForWorkspaces(
225498
225513
  workspaceToAnalysisData,
225499
225514
  ecosystemToWorkspaceToVulnerabilities[ecosystem] ?? {},
@@ -225502,7 +225517,7 @@ var CliCore = class {
225502
225517
  otherModulesCommunicator,
225503
225518
  this.rootWorkingDirectory,
225504
225519
  ecosystem,
225505
- true
225520
+ ["NPM", "PIP"].includes(ecosystem) && isEcosystemToAnalyze
225506
225521
  )).flat());
225507
225522
  this.sendProgress("RUN_ON_SUBPROJECT", false, this.rootWorkingDirectory);
225508
225523
  }
@@ -225760,10 +225775,10 @@ Subproject: ${subproject}`);
225760
225775
  }
225761
225776
  async runReachabilityAnalysisForWorkspaces(workspacePathToDataForAnalysis, workspaceToVulnerabilities, workspaceToDirectDependencies, otherModulesCommunicator, subprojectPath, ecosystem, reachabilitySupported) {
225762
225777
  const workspaceToAugmentedVulnerabilities = Object.fromEntries(await asyncMap(Object.keys(workspacePathToDataForAnalysis), async (workspacePath) => {
225778
+ const vulnerabilities = workspaceToVulnerabilities[workspacePath];
225763
225779
  try {
225764
225780
  const dataForAnalysis = workspacePathToDataForAnalysis[workspacePath];
225765
- const vulnerabilities = workspaceToVulnerabilities[workspacePath];
225766
- const augmentedVulnerabilities = reachabilitySupported ? await this.runReachabilityAnalysis(otherModulesCommunicator, subprojectPath, workspacePath, dataForAnalysis, ecosystem, vulnerabilities) : vulnerabilities.map((v) => ({
225781
+ const augmentedVulnerabilities = reachabilitySupported && !this.shouldExcludeAnalyzingWorkspace(subprojectPath, workspacePath) ? await this.runReachabilityAnalysis(otherModulesCommunicator, subprojectPath, workspacePath, dataForAnalysis, ecosystem, vulnerabilities) : vulnerabilities.map((v) => ({
225767
225782
  ...v,
225768
225783
  results: {
225769
225784
  type: "otherError",
@@ -225773,17 +225788,16 @@ Subproject: ${subproject}`);
225773
225788
  return [workspacePath, augmentedVulnerabilities];
225774
225789
  } catch (e) {
225775
225790
  logger.error(`Reachability analysis failed for workspace ${workspacePath} in subproject ${subprojectPath}: ${e.message}`);
225776
- if (this.options.ignoreFailingWorkspaces) {
225777
- const relativeSubprojectPath = relative11(this.rootWorkingDirectory, subprojectPath) || ".";
225778
- this.failedWorkspaces.push({
225779
- subproject: relativeSubprojectPath,
225780
- workspace: workspacePath,
225781
- error: e.message || "Unknown error",
225782
- phase: "reachability-analysis"
225783
- });
225784
- return [workspacePath, void 0];
225785
- }
225786
- throw e;
225791
+ return [
225792
+ workspacePath,
225793
+ vulnerabilities.map((v) => ({
225794
+ ...v,
225795
+ results: {
225796
+ type: "otherError",
225797
+ message: e.message || "Unknown error"
225798
+ }
225799
+ }))
225800
+ ];
225787
225801
  }
225788
225802
  }));
225789
225803
  const successfulWorkspaceToAugmentedVulnerabilities = Object.fromEntries(Object.entries(workspaceToAugmentedVulnerabilities).filter(([_, vulns]) => vulns !== void 0));
@@ -225838,6 +225852,18 @@ Subproject: ${subproject}`);
225838
225852
  }
225839
225853
  }
225840
225854
  }
225855
+ shouldExcludeAnalyzingWorkspace(subprojectPath, workspacePath) {
225856
+ const shouldExcludeWorkspaceForAnalysis = shouldIgnoreDueToExcludeDirsOrChangedFiles({
225857
+ mainProjectDir: this.rootWorkingDirectory,
225858
+ excludeDirs: this.options.excludeDirs ?? [],
225859
+ changedFiles: this.options.changedFiles,
225860
+ includeDirs: this.options.includeDirs ?? []
225861
+ }, resolve25(subprojectPath, workspacePath));
225862
+ if (shouldExcludeWorkspaceForAnalysis) {
225863
+ logger.info(`Skipping reachability analysis for workspace ${workspacePath} due to it being excluded.`);
225864
+ }
225865
+ return shouldExcludeWorkspaceForAnalysis;
225866
+ }
225841
225867
  async runReachabilityAnalysis(otherModulesCommunicator, subprojectPath, workspacePath, workspaceData, ecosystem, vulnerabilities) {
225842
225868
  const [vulnsWithActualAPIPatterns, result] = partition(vulnerabilities, (v) => Array.isArray(v.vulnerabilityAccessPaths));
225843
225869
  for (const v of result)
@@ -226255,9 +226281,10 @@ function computeSBOMTaskArtifacts(dependencyTrees) {
226255
226281
  // dist/index.js
226256
226282
  var program2 = new Command();
226257
226283
  var run2 = new Command();
226258
- run2.name("run").argument("<path>", "File system path to folder containing the project").option("-o, --output-dir <path>", "Write json report to <path>/coana-report.json").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("-p, --print-report", "Print the report to the console", false).option("--offline-database <path>", "Path to a coana-offline-db.json file for running the CLI without internet connectivity", void 0).option("-t, --timeout <timeout>", "Set API <timeout> in milliseconds to Coana backend.", "300000").option("-a, --analysis-timeout <timeout>", "Set <timeout> in seconds for each reachability analysis run").option("--memory-limit <memoryInMB>", "Set memory limit for analysis to <memoryInMB> megabytes of memory.", "8192").option("-c, --concurrency <concurrency>", "Set the maximum number of concurrent reachability analysis runs. It's recommended to choose a concurrency level that ensures that each analysis run has at least the --memory-limit amount of memory available.", "1").option("--api-key <key>", "Set the Coana dashboard API key. By setting you also enable the dashboard integration.").addOption(new Option("--write-report-to-file", "Write the report dashboard-compatible report to dashboard-report.json. This report may help the Coana team debug issues with the report insertion mechanism.").default(false).hideHelp()).option("--project-name <repoName>", "Set the name of the repository. Used for dashboard integration.").option("--repo-url <repoUrl>", "Set the URL of the repository. Used for dashboard integration.").option("--include-dirs <relativeDirs...>", "globs for directories to include from the detection of subprojects (space-separated)(use relative paths from the project root). Notice, projects that are not included may still be scanned if they are referenced from included projects.").option("--exclude-dirs <relativeDirs...>", "globs for directories to exclude from the detection of subprojects (space-separated)(use relative paths from the project root). Notice, excluded projects may still be scanned if they are referenced from non-excluded projects.").option("--disable-analysis-splitting", "Limits Coana to at most 1 reachability analysis run per workspace").option("--print-analysis-log-file", "Store log output from the JavaScript/TypeScript reachability analysis in the file js-analysis.log file in the root of each workspace", false).option("--entry-points <entryPoints...>", "List of files to analyze for root workspace. The reachability analysis automatically analyzes all files used by the entry points. If not provided, all JavaScript and TypeScript files are considered entry points. For non-root workspaces, all JavaScript and TypeScript files are analyzed as well.").option("--include-projects-with-no-reachability-support", "Also runs Coana on projects where we support traditional SCA, but does not yet support reachability analysis.", false).option("--ecosystems <ecosystems...>", "List of ecosystems to analyze (space-separated). Currently NPM, PIP, MAVEN, NUGET and GO are supported. Default is all supported ecosystems.").option("--changed-files <files...>", "List of files that have changed. If provided, Coana only analyzes workspaces and modules that contain changed files.").option("--disable-report-submission", "Disable the submission of the report to the Coana dashboard. Used by the pipeline blocking feature.", false).option("--disable-analytics-sharing", "Disable analytics sharing.", false).option("--provider-project <path>", "File system path to folder containing the provider project (Only supported for Maven, Gradle, and SBT)").option("--provider-workspaces <dirs...>", "List of workspaces that build the provided runtime environment (Only supported for Maven, Gradle, and SBT)", (paths) => paths.split(" ")).option("--lightweight-reachability", "Runs Coana in lightweight mode. This increases analysis speed but also raises the risk of Coana misclassifying the reachability of certain complex vulnerabilities. Recommended only for use with Coana Guardrail mode.", false).addOption(new Option("--run-without-docker", "Run package managers and reachability analyzers without using docker").default(process.env.RUN_WITHOUT_DOCKER === "true").hideHelp()).addOption(new Option("--run-env <env>", "Specifies the environment in which the CLI is run. So far only MANAGED_SCAN and UNKNOWN are supported.").default("UNKNOWN").choices(["UNKNOWN", "MANAGED_SCAN"]).hideHelp()).addOption(new Option("--guardrail-mode", "Run Coana in guardrail mode. This mode is used to prevent new reachable vulnerabilities from being introduced into the codebase. Usually run as a CI check when pushing new commits to a pull request.")).option("--ignore-failing-workspaces", "Continue processing when a workspace fails instead of exiting. Failed workspaces will be logged at termination.", false).addOption(new Option("--socket-mode <output-file>", "Run Coana in socket mode and write report to <output-file>").hideHelp()).addOption(new Option("--manifests-tar-hash <hash>", "Hash of the tarball containing all manifest files already uploaded to Socket. If provided, Socket will be used for computing dependency trees.").hideHelp()).version(version2).configureHelp({ sortOptions: true }).action(async (path2, options) => {
226284
+ run2.name("run").argument("<path>", "File system path to folder containing the project").option("-o, --output-dir <path>", "Write json report to <path>/coana-report.json").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("-p, --print-report", "Print the report to the console", false).option("--offline-database <path>", "Path to a coana-offline-db.json file for running the CLI without internet connectivity", void 0).option("-t, --timeout <timeout>", "Set API <timeout> in milliseconds to Coana backend.", "300000").option("-a, --analysis-timeout <timeout>", "Set <timeout> in seconds for each reachability analysis run").option("--memory-limit <memoryInMB>", "Set memory limit for analysis to <memoryInMB> megabytes of memory.", "8192").option("-c, --concurrency <concurrency>", "Set the maximum number of concurrent reachability analysis runs. It's recommended to choose a concurrency level that ensures that each analysis run has at least the --memory-limit amount of memory available.", "1").option("--api-key <key>", "Set the Coana dashboard API key. By setting you also enable the dashboard integration.").addOption(new Option("--write-report-to-file", "Write the report dashboard-compatible report to dashboard-report.json. This report may help the Coana team debug issues with the report insertion mechanism.").default(false).hideHelp()).option("--project-name <repoName>", "Set the name of the repository. Used for dashboard integration.").option("--repo-url <repoUrl>", "Set the URL of the repository. Used for dashboard integration.").option("--include-dirs <relativeDirs...>", "globs for directories to include from the detection of subprojects (space-separated)(use relative paths from the project root). Notice, projects that are not included may still be scanned if they are referenced from included projects.").option("--exclude-dirs <relativeDirs...>", "globs for directories to exclude from the detection of subprojects (space-separated)(use relative paths from the project root). Notice, excluded projects may still be scanned if they are referenced from non-excluded projects.").option("--disable-analysis-splitting", "Limits Coana to at most 1 reachability analysis run per workspace").option("--print-analysis-log-file", "Store log output from the JavaScript/TypeScript reachability analysis in the file js-analysis.log file in the root of each workspace", false).option("--entry-points <entryPoints...>", "List of files to analyze for root workspace. The reachability analysis automatically analyzes all files used by the entry points. If not provided, all JavaScript and TypeScript files are considered entry points. For non-root workspaces, all JavaScript and TypeScript files are analyzed as well.").option("--include-projects-with-no-reachability-support", "Also runs Coana on projects where we support traditional SCA, but does not yet support reachability analysis.", false).option("--ecosystems <ecosystems...>", "List of ecosystems to analyze (space-separated). Currently NPM, PIP, MAVEN, NUGET and GO are supported. Default is all supported ecosystems.").addOption(new Option("--purl-types <purlTypes...>", "List of PURL types to analyze (space-separated). Currently npm, pypi, maven, nuget, golang and cargo are supported. Default is all supported purl types.").hideHelp()).option("--changed-files <files...>", "List of files that have changed. If provided, Coana only analyzes workspaces and modules that contain changed files.").option("--disable-report-submission", "Disable the submission of the report to the Coana dashboard. Used by the pipeline blocking feature.", false).option("--disable-analytics-sharing", "Disable analytics sharing.", false).option("--provider-project <path>", "File system path to folder containing the provider project (Only supported for Maven, Gradle, and SBT)").option("--provider-workspaces <dirs...>", "List of workspaces that build the provided runtime environment (Only supported for Maven, Gradle, and SBT)", (paths) => paths.split(" ")).option("--lightweight-reachability", "Runs Coana in lightweight mode. This increases analysis speed but also raises the risk of Coana misclassifying the reachability of certain complex vulnerabilities. Recommended only for use with Coana Guardrail mode.", false).addOption(new Option("--run-without-docker", "Run package managers and reachability analyzers without using docker").default(process.env.RUN_WITHOUT_DOCKER === "true").hideHelp()).addOption(new Option("--run-env <env>", "Specifies the environment in which the CLI is run. So far only MANAGED_SCAN and UNKNOWN are supported.").default("UNKNOWN").choices(["UNKNOWN", "MANAGED_SCAN"]).hideHelp()).addOption(new Option("--guardrail-mode", "Run Coana in guardrail mode. This mode is used to prevent new reachable vulnerabilities from being introduced into the codebase. Usually run as a CI check when pushing new commits to a pull request.")).option("--ignore-failing-workspaces", "Continue processing when a workspace fails instead of exiting. Failed workspaces will be logged at termination.", false).addOption(new Option("--socket-mode <output-file>", "Run Coana in socket mode and write report to <output-file>").hideHelp()).addOption(new Option("--manifests-tar-hash <hash>", "Hash of the tarball containing all manifest files already uploaded to Socket. If provided, Socket will be used for computing dependency trees.").hideHelp()).version(version2).configureHelp({ sortOptions: true }).action(async (path2, options) => {
226259
226285
  process.env.DOCKER_IMAGE_TAG ??= version2;
226260
226286
  options.ecosystems = options.ecosystems?.map((e) => e.toUpperCase());
226287
+ options.purlTypes = options.purlTypes?.map((e) => e.toLowerCase());
226261
226288
  await new CliCore(path2, options).main();
226262
226289
  });
226263
226290
  var applyFixes = new Command();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.11.7",
3
+ "version": "14.11.9",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -64950,7 +64950,7 @@ var require_comparator = __commonJS({
64950
64950
  var require_satisfies = __commonJS({
64951
64951
  "../../node_modules/.pnpm/semver@7.7.1/node_modules/semver/functions/satisfies.js"(exports, module) {
64952
64952
  var Range = require_range2();
64953
- var satisfies2 = (version3, range, options) => {
64953
+ var satisfies3 = (version3, range, options) => {
64954
64954
  try {
64955
64955
  range = new Range(range, options);
64956
64956
  } catch (er) {
@@ -64958,7 +64958,7 @@ var require_satisfies = __commonJS({
64958
64958
  }
64959
64959
  return range.test(version3);
64960
64960
  };
64961
- module.exports = satisfies2;
64961
+ module.exports = satisfies3;
64962
64962
  }
64963
64963
  });
64964
64964
 
@@ -65107,7 +65107,7 @@ var require_outside = __commonJS({
65107
65107
  var Comparator = require_comparator();
65108
65108
  var { ANY } = Comparator;
65109
65109
  var Range = require_range2();
65110
- var satisfies2 = require_satisfies();
65110
+ var satisfies3 = require_satisfies();
65111
65111
  var gt = require_gt();
65112
65112
  var lt2 = require_lt();
65113
65113
  var lte = require_lte();
@@ -65134,7 +65134,7 @@ var require_outside = __commonJS({
65134
65134
  default:
65135
65135
  throw new TypeError('Must provide a hilo val of "<" or ">"');
65136
65136
  }
65137
- if (satisfies2(version3, range, options)) {
65137
+ if (satisfies3(version3, range, options)) {
65138
65138
  return false;
65139
65139
  }
65140
65140
  for (let i2 = 0; i2 < range.set.length; ++i2) {
@@ -65202,7 +65202,7 @@ var require_intersects = __commonJS({
65202
65202
  // ../../node_modules/.pnpm/semver@7.7.1/node_modules/semver/ranges/simplify.js
65203
65203
  var require_simplify = __commonJS({
65204
65204
  "../../node_modules/.pnpm/semver@7.7.1/node_modules/semver/ranges/simplify.js"(exports, module) {
65205
- var satisfies2 = require_satisfies();
65205
+ var satisfies3 = require_satisfies();
65206
65206
  var compare = require_compare();
65207
65207
  module.exports = (versions, range, options) => {
65208
65208
  const set = [];
@@ -65210,7 +65210,7 @@ var require_simplify = __commonJS({
65210
65210
  let prev2 = null;
65211
65211
  const v = versions.sort((a2, b) => compare(a2, b, options));
65212
65212
  for (const version3 of v) {
65213
- const included = satisfies2(version3, range, options);
65213
+ const included = satisfies3(version3, range, options);
65214
65214
  if (included) {
65215
65215
  prev2 = version3;
65216
65216
  if (!first2) {
@@ -65254,7 +65254,7 @@ var require_subset = __commonJS({
65254
65254
  var Range = require_range2();
65255
65255
  var Comparator = require_comparator();
65256
65256
  var { ANY } = Comparator;
65257
- var satisfies2 = require_satisfies();
65257
+ var satisfies3 = require_satisfies();
65258
65258
  var compare = require_compare();
65259
65259
  var subset = (sub, dom, options = {}) => {
65260
65260
  if (sub === dom) {
@@ -65323,14 +65323,14 @@ var require_subset = __commonJS({
65323
65323
  }
65324
65324
  }
65325
65325
  for (const eq2 of eqSet) {
65326
- if (gt && !satisfies2(eq2, String(gt), options)) {
65326
+ if (gt && !satisfies3(eq2, String(gt), options)) {
65327
65327
  return null;
65328
65328
  }
65329
- if (lt2 && !satisfies2(eq2, String(lt2), options)) {
65329
+ if (lt2 && !satisfies3(eq2, String(lt2), options)) {
65330
65330
  return null;
65331
65331
  }
65332
65332
  for (const c of dom) {
65333
- if (!satisfies2(eq2, String(c), options)) {
65333
+ if (!satisfies3(eq2, String(c), options)) {
65334
65334
  return false;
65335
65335
  }
65336
65336
  }
@@ -65357,7 +65357,7 @@ var require_subset = __commonJS({
65357
65357
  if (higher === c && higher !== gt) {
65358
65358
  return false;
65359
65359
  }
65360
- } else if (gt.operator === ">=" && !satisfies2(gt.semver, String(c), options)) {
65360
+ } else if (gt.operator === ">=" && !satisfies3(gt.semver, String(c), options)) {
65361
65361
  return false;
65362
65362
  }
65363
65363
  }
@@ -65372,7 +65372,7 @@ var require_subset = __commonJS({
65372
65372
  if (lower === c && lower !== lt2) {
65373
65373
  return false;
65374
65374
  }
65375
- } else if (lt2.operator === "<=" && !satisfies2(lt2.semver, String(c), options)) {
65375
+ } else if (lt2.operator === "<=" && !satisfies3(lt2.semver, String(c), options)) {
65376
65376
  return false;
65377
65377
  }
65378
65378
  }
@@ -65441,7 +65441,7 @@ var require_semver2 = __commonJS({
65441
65441
  var coerce = require_coerce();
65442
65442
  var Comparator = require_comparator();
65443
65443
  var Range = require_range2();
65444
- var satisfies2 = require_satisfies();
65444
+ var satisfies3 = require_satisfies();
65445
65445
  var toComparators = require_to_comparators();
65446
65446
  var maxSatisfying = require_max_satisfying();
65447
65447
  var minSatisfying = require_min_satisfying();
@@ -65479,7 +65479,7 @@ var require_semver2 = __commonJS({
65479
65479
  coerce,
65480
65480
  Comparator,
65481
65481
  Range,
65482
- satisfies: satisfies2,
65482
+ satisfies: satisfies3,
65483
65483
  toComparators,
65484
65484
  maxSatisfying,
65485
65485
  minSatisfying,
@@ -73697,7 +73697,7 @@ ${error.message}`);
73697
73697
 
73698
73698
  // dist/whole-program-code-aware-vulnerability-scanner/analyze-in-buckets.js
73699
73699
  var import_lodash17 = __toESM(require_lodash(), 1);
73700
- var import_semver2 = __toESM(require_semver2(), 1);
73700
+ var import_semver3 = __toESM(require_semver2(), 1);
73701
73701
  import assert8 from "assert";
73702
73702
  import { relative as relative5 } from "path";
73703
73703
 
@@ -96268,6 +96268,7 @@ async function getVersion(analysisName) {
96268
96268
  }
96269
96269
 
96270
96270
  // dist/whole-program-code-aware-vulnerability-scanner/python/python-code-aware-vulnerability-scanner.js
96271
+ var import_semver2 = __toESM(require_semver2(), 1);
96271
96272
  var { omit, once: once3, pick, sortedUniq, uniqBy } = import_lodash14.default;
96272
96273
  var PythonCodeAwareVulnerabilityScanner = class _PythonCodeAwareVulnerabilityScanner {
96273
96274
  state;
@@ -96276,6 +96277,7 @@ var PythonCodeAwareVulnerabilityScanner = class _PythonCodeAwareVulnerabilitySca
96276
96277
  numberAnalysesRun = 0;
96277
96278
  virtualEnvInfo;
96278
96279
  vm;
96280
+ mambaladeVenvPath;
96279
96281
  constructor(state, projectDir, _statusUpdater) {
96280
96282
  this.state = state;
96281
96283
  this.projectDir = projectDir;
@@ -96293,6 +96295,9 @@ var PythonCodeAwareVulnerabilityScanner = class _PythonCodeAwareVulnerabilitySca
96293
96295
  async runAnalysis(vulns, heuristic, analyzesAllVulns) {
96294
96296
  if (!this.virtualEnvInfo)
96295
96297
  throw new Error("Virtual environment not set up");
96298
+ if (!this.mambaladeVenvPath) {
96299
+ await this.setupMambalade();
96300
+ }
96296
96301
  logger.info("Started instantiating Python code-aware analysis");
96297
96302
  logger.debug(`Trying to find files to analyze from projectDir: ${this.projectDir}`);
96298
96303
  const { rootWorkingDir, reachabilityAnalysisOptions } = this.state;
@@ -96326,7 +96331,7 @@ runpy.run_module("mambalade", alter_sys=True)
96326
96331
  const excludeDistributionsOption = packagesToExclude?.size ? ["--exclude-distributions", ...packagesToExclude] : [];
96327
96332
  const timeout = reachabilityAnalysisOptions.timeoutInSeconds ?? // 10 minutes for the first analysis, 1 minute for subsequent analyses
96328
96333
  (analyzesAllVulns ? 60 * 10 : 60);
96329
- const pythonExecutable = resolve12(COANA_REPOS_PATH(), "mambalade", ".venv", "bin", "python");
96334
+ const pythonExecutable = join15(this.mambaladeVenvPath, "bin", "python");
96330
96335
  const mambaladeArgs = [
96331
96336
  pythonExecutable,
96332
96337
  wrapperPath,
@@ -96603,12 +96608,34 @@ ${msg}`;
96603
96608
  getVirtualEnvInfo() {
96604
96609
  return this.virtualEnvInfo;
96605
96610
  }
96611
+ async setupMambalade() {
96612
+ const venvDir = await createTmpDirectory("mambalade-venv");
96613
+ logger.info("Creating Mambalade virtual environment");
96614
+ const pythonInterpreter = await getPythonInterpreter();
96615
+ await exec(cmdt`${pythonInterpreter} -SIm venv ${venvDir}`);
96616
+ const mambaladeWheelsPath = join15(COANA_REPOS_PATH(), "mambalade", "dist");
96617
+ const wheelFiles = await readdir3(mambaladeWheelsPath);
96618
+ const mambaladeWheels = wheelFiles.filter((f2) => f2.endsWith(".whl")).map((f2) => join15(mambaladeWheelsPath, f2));
96619
+ if (mambaladeWheels.length === 0) {
96620
+ throw new Error(`No mambalade wheel files found in ${mambaladeWheelsPath}`);
96621
+ }
96622
+ logger.info(`Installing mambalade wheels: ${mambaladeWheels.join(", ")}`);
96623
+ await exec(cmdt`${venvDir}/bin/pip install --no-deps ${mambaladeWheels}`);
96624
+ this.mambaladeVenvPath = venvDir;
96625
+ logger.info("Mambalade virtual environment setup complete");
96626
+ }
96606
96627
  // async [Symbol.asyncDispose]() {
96607
96628
  async cleanup() {
96608
96629
  if (this.virtualEnvInfo?.temporary) {
96609
- await rm5(this.virtualEnvInfo.virtualEnvFolder, { recursive: true, force: true });
96630
+ await rm5(this.virtualEnvInfo.virtualEnvFolder, { recursive: true, force: true }).catch(() => {
96631
+ });
96610
96632
  this.virtualEnvInfo = void 0;
96611
96633
  }
96634
+ if (this.mambaladeVenvPath) {
96635
+ await rm5(this.mambaladeVenvPath, { recursive: true, force: true }).catch(() => {
96636
+ });
96637
+ this.mambaladeVenvPath = void 0;
96638
+ }
96612
96639
  }
96613
96640
  };
96614
96641
  async function findFilesToAnalyze(projectDir) {
@@ -96647,6 +96674,16 @@ function transformSourceLocations2(appPath, fileMappings, detectedOccurrences) {
96647
96674
  }
96648
96675
  return detectedOccurrences;
96649
96676
  }
96677
+ async function getPythonInterpreter() {
96678
+ const pythonVersionRequired = ">=3.11.0";
96679
+ const pypyVersion = await getPythonVersion("pypy3").catch(() => void 0);
96680
+ if (pypyVersion && (0, import_semver2.satisfies)(pypyVersion, pythonVersionRequired))
96681
+ return "pypy3";
96682
+ const pythonVersion = await getPythonVersion("python3").catch(() => void 0);
96683
+ if (pythonVersion && (0, import_semver2.satisfies)(pythonVersion, pythonVersionRequired))
96684
+ return "python3";
96685
+ throw new Error(`No Python ${pythonVersionRequired} interpreter found`);
96686
+ }
96650
96687
 
96651
96688
  // dist/whole-program-code-aware-vulnerability-scanner/python/phantom-deps.js
96652
96689
  var { uniq: uniq8 } = import_lodash15.default;
@@ -96890,7 +96927,7 @@ async function analyzeWithHeuristics(state, vulns, heuristicsInOrder, doNotRecom
96890
96927
  if (bucketsFromLastAnalysis.some((b) => b.heuristicName === heuristics.IGNORE_DEPENDENCIES_AND_MAX_ROUNDS_3.name))
96891
96928
  return;
96892
96929
  try {
96893
- if ((0, import_semver2.lt)(cliVersion, CLI_VERSION_TO_USE_CACHING_FROM[ecosystem] ?? CLI_VERSION_TO_USE_CACHING_FROM_DEFAULT))
96930
+ if ((0, import_semver3.lt)(cliVersion, CLI_VERSION_TO_USE_CACHING_FROM[ecosystem] ?? CLI_VERSION_TO_USE_CACHING_FROM_DEFAULT))
96894
96931
  return void 0;
96895
96932
  } catch (e) {
96896
96933
  return void 0;