@coana-tech/cli 14.9.29 → 14.9.31

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.
Files changed (2) hide show
  1. package/cli.mjs +209 -48
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -206768,8 +206768,9 @@ function shouldIgnoreDir(dir) {
206768
206768
  "obj",
206769
206769
  ".yarn",
206770
206770
  // created by the yarn package manager
206771
- ".bingo"
206771
+ ".bingo",
206772
206772
  // created by the Bingo package manager, which can be used with Go projects
206773
+ "site-packages"
206773
206774
  ];
206774
206775
  return dirsToIgnore.includes(dir);
206775
206776
  }
@@ -221972,7 +221973,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
221972
221973
  }
221973
221974
 
221974
221975
  // dist/version.js
221975
- var version2 = "14.9.29";
221976
+ var version2 = "14.9.31";
221976
221977
 
221977
221978
  // ../../node_modules/.pnpm/axios@1.9.0/node_modules/axios/lib/helpers/bind.js
221978
221979
  function bind2(fn2, thisArg) {
@@ -225330,7 +225331,7 @@ function getAdvisoryEcosystemFromPurl(purl) {
225330
225331
  function getPurlStrings(dependencyTree) {
225331
225332
  const res = {};
225332
225333
  for (const [depId, node] of Object.entries(dependencyTree.transitiveDependencies)) {
225333
- const type = getPurlType(dependencyTree.ecosystem);
225334
+ const type = getPurlType(dependencyTree.ecosystem ?? "NPM");
225334
225335
  const { namespace: namespace2, name } = getNamespaceAndName(dependencyTree.ecosystem, node.packageName);
225335
225336
  const version3 = node.version;
225336
225337
  const purl = simplePurl(type, namespace2, name, version3);
@@ -225935,10 +225936,6 @@ var CliCore = class {
225935
225936
  };
225936
225937
  }
225937
225938
  async runOnSubproject(otherModulesCommunicator, subProjAndWsPath, reachabilitySupported) {
225938
- const { packageManagerName, subprojectPath, workspacePaths } = subProjAndWsPath;
225939
- this.sendProgress("RUN_ON_SUBPROJECT", true, subprojectPath);
225940
- const rootWorkingDirectory = this.rootWorkingDirectory;
225941
- const ecosystem = subProjAndWsPath.ecosystem;
225942
225939
  try {
225943
225940
  let pruneVulnerablePathsToShortestPathsOnly2 = function(ecosystem2, workspaceToAugmentedVulnerabilities2) {
225944
225941
  const vulnerabilityToWorkspaceToCodeAwareScanSuccess = {};
@@ -225987,43 +225984,8 @@ var CliCore = class {
225987
225984
  }
225988
225985
  };
225989
225986
  var pruneVulnerablePathsToShortestPathsOnly = pruneVulnerablePathsToShortestPathsOnly2;
225990
- this.sendProgress("PREPARE_PROJECT_AND_GET_PROJECT_DATA", true, subprojectPath);
225991
- const projectInfo = await otherModulesCommunicator.prepareProjectAndGetProjectData(packageManagerName, subprojectPath, workspacePaths, this.options.lightweightReachability, this.options.providerProject ? await this.runOnProvider(this.options.providerProject) : void 0);
225992
- this.sendProgress("PREPARE_PROJECT_AND_GET_PROJECT_DATA", false, subprojectPath);
225993
- const workspaceToPlainDependencyTree = Object.fromEntries(workspacePaths.map((workspacePath) => [
225994
- workspacePath,
225995
- toPlainDependencyTree(projectInfo[workspacePath].dataForAnalysis.dependencyTree)
225996
- ]));
225997
- const dependencyTrees = workspacePaths.map((workspacePath) => ({
225998
- treeType: "v1",
225999
- dependencyTree: workspaceToPlainDependencyTree[workspacePath],
226000
- ecosystem: workspaceToPlainDependencyTree[workspacePath].ecosystem ?? "NPM",
226001
- workspacePath,
226002
- subprojectPath: relative10(rootWorkingDirectory, subprojectPath) || "."
226003
- }));
226004
- if (this.options.socketMode)
226005
- this.reportDependencyTrees = dependencyTrees;
226006
- if (this.shareWithDashboard)
226007
- sendDependencyTreesToDashboard(dependencyTrees, this.reportId, this.apiKey);
226008
- const workspaceToVulnerabilities = Object.fromEntries(await asyncMap(workspacePaths, async (workspacePath, idx) => this.spinner.wrap(`Scanning for vulnerabilities: (${subProjAndWsPath.packageManagerName}) (${idx + 1}/${workspacePaths.length}) ${workspacePath}`, async () => {
226009
- const dependencyTree = projectInfo[workspacePath].dataForAnalysis.dependencyTree;
226010
- this.sendProgress("SCAN_FOR_VULNERABILITIES", true, subprojectPath, workspacePath);
226011
- try {
226012
- return [
226013
- workspacePath,
226014
- this.options.socketMode ? await scanForVulnerabilitiesSocketMode(workspaceToPlainDependencyTree[workspacePath]) : (await scanForVulnerabilities(dependencyTree, this.options.offlineDatabase, this.apiKey, Number(this.options.timeout))).vulnerabilities
226015
- ];
226016
- } catch (e) {
226017
- logger.error(`Scanning for vulnerabilities failed for subproject ${subprojectPath} in workspace ${workspacePath}`);
226018
- throw e;
226019
- } finally {
226020
- this.sendProgress("SCAN_FOR_VULNERABILITIES", false, subprojectPath, workspacePath);
226021
- }
226022
- })));
226023
- const workspaceToDependencyTree = Object.fromEntries(workspacePaths.map((workspacePath) => [
226024
- workspacePath,
226025
- projectInfo[workspacePath].dataForAnalysis.dependencyTree
226026
- ]));
225987
+ const { ecosystem, subprojectPath, workspacePaths } = subProjAndWsPath;
225988
+ const { projectInfo, workspaceToVulnerabilities } = await this.getDependencyTreeAndVulnerabilities(otherModulesCommunicator, subProjAndWsPath);
226027
225989
  const workspaceToAugmentedVulnerabilities = Object.fromEntries(await asyncMap(workspacePaths, async (workspacePath) => {
226028
225990
  const dataForAnalysis = projectInfo[workspacePath].dataForAnalysis;
226029
225991
  const vulnerabilities = workspaceToVulnerabilities[workspacePath];
@@ -226041,13 +226003,13 @@ var CliCore = class {
226041
226003
  }
226042
226004
  return workspacePaths.map((workspacePath) => {
226043
226005
  const codeAwareScanResultsForAllPackages = [];
226044
- codeAwareScanResultsForAllPackages.push(...this.transformToReportVulnerabilities(workspaceToAugmentedVulnerabilities[workspacePath], projectInfo[workspacePath].directDependenciesMap ?? {}, subprojectPath, workspacePath, rootWorkingDirectory));
226006
+ codeAwareScanResultsForAllPackages.push(...this.transformToReportVulnerabilities(workspaceToAugmentedVulnerabilities[workspacePath], projectInfo[workspacePath].directDependenciesMap ?? {}, subprojectPath, workspacePath, this.rootWorkingDirectory));
226045
226007
  return {
226046
- subprojectPath: relative10(rootWorkingDirectory, subprojectPath) || ".",
226008
+ subprojectPath: relative10(this.rootWorkingDirectory, subprojectPath) || ".",
226047
226009
  workspacePath,
226048
226010
  directDependencies: projectInfo[workspacePath].directDependenciesMap ?? {},
226049
226011
  vulnerabilities: codeAwareScanResultsForAllPackages,
226050
- dependencyTree: workspaceToDependencyTree[workspacePath]
226012
+ dependencyTree: projectInfo[workspacePath].dataForAnalysis.dependencyTree
226051
226013
  };
226052
226014
  });
226053
226015
  } finally {
@@ -226117,6 +226079,45 @@ var CliCore = class {
226117
226079
  };
226118
226080
  });
226119
226081
  }
226082
+ async getDependencyTreeAndVulnerabilities(otherModulesCommunicator, subProjAndWsPath) {
226083
+ const { packageManagerName, subprojectPath, workspacePaths } = subProjAndWsPath;
226084
+ this.sendProgress("RUN_ON_SUBPROJECT", true, subprojectPath);
226085
+ const rootWorkingDirectory = this.rootWorkingDirectory;
226086
+ this.sendProgress("PREPARE_PROJECT_AND_GET_PROJECT_DATA", true, subprojectPath);
226087
+ const projectInfo = await otherModulesCommunicator.prepareProjectAndGetProjectData(packageManagerName, subprojectPath, workspacePaths, this.options.lightweightReachability, this.options.providerProject ? await this.runOnProvider(this.options.providerProject) : void 0);
226088
+ this.sendProgress("PREPARE_PROJECT_AND_GET_PROJECT_DATA", false, subprojectPath);
226089
+ const workspaceToPlainDependencyTree = Object.fromEntries(workspacePaths.map((workspacePath) => [
226090
+ workspacePath,
226091
+ toPlainDependencyTree(projectInfo[workspacePath].dataForAnalysis.dependencyTree)
226092
+ ]));
226093
+ const dependencyTrees = workspacePaths.map((workspacePath) => ({
226094
+ treeType: "v1",
226095
+ dependencyTree: workspaceToPlainDependencyTree[workspacePath],
226096
+ ecosystem: workspaceToPlainDependencyTree[workspacePath].ecosystem ?? "NPM",
226097
+ workspacePath,
226098
+ subprojectPath: relative10(rootWorkingDirectory, subprojectPath) || "."
226099
+ }));
226100
+ if (this.options.socketMode)
226101
+ this.reportDependencyTrees = dependencyTrees;
226102
+ if (this.shareWithDashboard)
226103
+ sendDependencyTreesToDashboard(dependencyTrees, this.reportId, this.apiKey);
226104
+ const workspaceToVulnerabilities = Object.fromEntries(await asyncMap(workspacePaths, async (workspacePath, idx) => this.spinner.wrap(`Scanning for vulnerabilities: (${subProjAndWsPath.packageManagerName}) (${idx + 1}/${workspacePaths.length}) ${workspacePath}`, async () => {
226105
+ const dependencyTree = projectInfo[workspacePath].dataForAnalysis.dependencyTree;
226106
+ this.sendProgress("SCAN_FOR_VULNERABILITIES", true, subprojectPath, workspacePath);
226107
+ try {
226108
+ return [
226109
+ workspacePath,
226110
+ this.options.socketMode ? await scanForVulnerabilitiesSocketMode(projectInfo[workspacePath].dataForAnalysis.dependencyTree) : (await scanForVulnerabilities(dependencyTree, this.options.offlineDatabase, this.apiKey, Number(this.options.timeout))).vulnerabilities
226111
+ ];
226112
+ } catch (e) {
226113
+ logger.error(`Scanning for vulnerabilities failed for subproject ${subprojectPath} in workspace ${workspacePath}`);
226114
+ throw e;
226115
+ } finally {
226116
+ this.sendProgress("SCAN_FOR_VULNERABILITIES", false, subprojectPath, workspacePath);
226117
+ }
226118
+ })));
226119
+ return { projectInfo, workspaceToVulnerabilities };
226120
+ }
226120
226121
  };
226121
226122
  function getRelativeSubprojectPath(subprojectPath, projectDir) {
226122
226123
  return relative10(projectDir, subprojectPath) || ".";
@@ -226238,6 +226239,140 @@ var signalFixApplied = (_fixId, subprojectPath, workspacePath, vulnerabilityFixe
226238
226239
  ${vulnerabilityFixes.map((fix) => ` ${fix.dependencyName} from ${fix.currentVersion} to ${fix.fixedVersion}`).join("\n")}`);
226239
226240
  };
226240
226241
 
226242
+ // dist/cli-compute-fixes-and-upgrade-purls.js
226243
+ async function computeFixesAndUpgradePurls(path2, options) {
226244
+ const { artifacts, vulnerableArtifactIdsPerVulnerability } = await computeInputForComputingFixes(path2, options);
226245
+ if (vulnerableArtifactIdsPerVulnerability.size === 0) {
226246
+ logger.info("No vulnerabilities to compute fixes for");
226247
+ return;
226248
+ }
226249
+ if (options.applyFixesTo.length === 0) {
226250
+ logger.info("Vulnerabilities found:", Array.from(vulnerableArtifactIdsPerVulnerability.keys()).join(", "));
226251
+ logger.info("Run again with --apply-fixes-to GHSA_IDS to fix those vulnerabilities by computing packages to upgrade and apply them");
226252
+ return;
226253
+ }
226254
+ const vulnerableArtifactIdsForGhsas = options.applyFixesTo.flatMap((ghsa) => [
226255
+ ...vulnerableArtifactIdsPerVulnerability.get(ghsa)?.values() ?? []
226256
+ ]);
226257
+ const computedFix = await useSocketComputeFixEndpoint(artifacts, vulnerableArtifactIdsForGhsas);
226258
+ if (computedFix.type !== "fix_found") {
226259
+ throw new Error(`No fix found for the given vulnerabilities`);
226260
+ }
226261
+ if (options.dryRun) {
226262
+ logger.info("Fixes found:");
226263
+ for (const fix of computedFix.fixes) {
226264
+ logger.info(` - ${fix.purl} -> ${fix.fixedVersion}`);
226265
+ }
226266
+ logger.info("Run again without --dry-run to apply the fixes");
226267
+ return;
226268
+ }
226269
+ try {
226270
+ await upgradePurl(path2, computedFix.fixes.map((fix) => ({ purl: fix.purl, upgradeVersion: fix.fixedVersion })), {
226271
+ debug: options.debug,
226272
+ silent: options.silent,
226273
+ runWithoutDocker: false,
226274
+ concurrency: "1",
226275
+ globPattern: options.globPattern
226276
+ });
226277
+ } catch (error) {
226278
+ logger.error("Error applying fixes:", error);
226279
+ throw error;
226280
+ }
226281
+ }
226282
+ async function computeInputForComputingFixes(path2, options) {
226283
+ const otherModulesCommunicator = new OtherModulesCommunicator(path2, options, {
226284
+ type: "missing"
226285
+ });
226286
+ const manager = await ProjectManager.create(path2, otherModulesCommunicator);
226287
+ const { reachabilitySupport, traditionalScaSupport } = manager.getSubprojectsWithWorkspacePaths();
226288
+ const supportedSubprojects = reachabilitySupport.concat(traditionalScaSupport).filter((p3) => getPackageManagerSupport(p3.packageManagerName).supportsApplyingFixes);
226289
+ if (supportedSubprojects.length === 0) {
226290
+ throw new Error(`No supported projects found in ${path2}.`);
226291
+ }
226292
+ const cliCore = new CliCore(path2, { ...defaultCliOptions, socketMode: "true" });
226293
+ const results = await asyncMap(supportedSubprojects, async (subproject) => cliCore.getDependencyTreeAndVulnerabilities(otherModulesCommunicator, subproject));
226294
+ const { artifacts, purlToIndex } = computeSBOMTaskArtifacts(results.flatMap((r2) => Object.values(r2.projectInfo).map((info) => info.dataForAnalysis.dependencyTree)));
226295
+ const vulnerableArtifactIdsPerVulnerability = computeVulnerableArtifactIdsPerVulnerability(results.flatMap((r2) => Object.values(r2.workspaceToVulnerabilities).flat()), purlToIndex);
226296
+ return { artifacts, vulnerableArtifactIdsPerVulnerability };
226297
+ }
226298
+ function computeVulnerableArtifactIdsPerVulnerability(vulnerabilities, purlToIndex) {
226299
+ const vulnerableArtifactIdsPerVulnerability = /* @__PURE__ */ new Map();
226300
+ for (const vulnerability of vulnerabilities) {
226301
+ if (!vulnerableArtifactIdsPerVulnerability.has(vulnerability.url)) {
226302
+ vulnerableArtifactIdsPerVulnerability.set(vulnerability.url, /* @__PURE__ */ new Set());
226303
+ }
226304
+ if (!vulnerability.purl)
226305
+ throw new Error(`Vulnerability ${vulnerability.url} has no purl`);
226306
+ if (!purlToIndex.has(vulnerability.purl)) {
226307
+ throw new Error(`Vulnerability ${vulnerability.url} has no purl in sbomTaskArtifacts`);
226308
+ }
226309
+ vulnerableArtifactIdsPerVulnerability.get(vulnerability.url).add(purlToIndex.get(vulnerability.purl));
226310
+ }
226311
+ return vulnerableArtifactIdsPerVulnerability;
226312
+ }
226313
+ function computeSBOMTaskArtifacts(dependencyTrees) {
226314
+ const components = [];
226315
+ const purlToIndex = /* @__PURE__ */ new Map();
226316
+ for (const dependencyTree of dependencyTrees) {
226317
+ const depIdentifierToPurl = Object.fromEntries(Object.entries(dependencyTree.transitiveDependencies).filter(([_depIdentifier, dep]) => dep.purlObj).map(([depIdentifier, dep]) => {
226318
+ const purl = dep.purlObj.purlString;
226319
+ if (purl && !purlToIndex.has(purl)) {
226320
+ purlToIndex.set(purl, components.length);
226321
+ const depTreeNode = dependencyTree.transitiveDependencies[depIdentifier];
226322
+ components[purlToIndex.get(purl)] = {
226323
+ type: depTreeNode.purlObj.type,
226324
+ name: depTreeNode.purlObj.name,
226325
+ version: depTreeNode.purlObj.version,
226326
+ namespace: depTreeNode.purlObj.namespace,
226327
+ adj: []
226328
+ };
226329
+ }
226330
+ return [depIdentifier, purl];
226331
+ }));
226332
+ for (const [depIdentifier, purl] of Object.entries(depIdentifierToPurl)) {
226333
+ const depTreeNode = dependencyTree.transitiveDependencies[depIdentifier];
226334
+ if (!depTreeNode.purlObj) {
226335
+ continue;
226336
+ }
226337
+ const component = components[purlToIndex.get(purl)];
226338
+ depTreeNode.dependencies?.forEach((dep) => {
226339
+ const depPurl = depIdentifierToPurl[dep];
226340
+ const depIndex = purlToIndex.get(depPurl);
226341
+ if (depIndex && !component.adj?.includes(depIndex)) {
226342
+ component.adj.push(depIndex);
226343
+ }
226344
+ });
226345
+ }
226346
+ }
226347
+ return { artifacts: components, purlToIndex };
226348
+ }
226349
+ async function useSocketComputeFixEndpoint(artifacts, vulnerableArtifactIdsForGhsas) {
226350
+ let socketBaseUrl = process.env.SOCKET_CLI_API_BASE_URL ?? "https://api.socket.dev/v0/";
226351
+ if (!socketBaseUrl.endsWith("/"))
226352
+ socketBaseUrl += "/";
226353
+ try {
226354
+ const url3 = `${socketBaseUrl}fixes/compute-fixes`;
226355
+ const data2 = {
226356
+ artifacts,
226357
+ vulnerableArtifactIndexes: vulnerableArtifactIdsForGhsas
226358
+ };
226359
+ return (await axios_default2.post(url3, data2, {
226360
+ headers: {
226361
+ "Content-Type": "application/json",
226362
+ Accept: "application/json",
226363
+ Authorization: `Basic ${btoa(`${process.env.SOCKET_CLI_API_TOKEN}:`)}`
226364
+ }
226365
+ })).data;
226366
+ } catch (error) {
226367
+ logger.error("Request to compute fixes failed:", error);
226368
+ return {
226369
+ type: "error during computation",
226370
+ message: "Error during computation",
226371
+ fixes: []
226372
+ };
226373
+ }
226374
+ }
226375
+
226241
226376
  // dist/index.js
226242
226377
  var program2 = new Command();
226243
226378
  var run2 = new Command();
@@ -226264,6 +226399,11 @@ upgradePurls.name("upgrade-purls").argument("<path>", "File system path to the f
226264
226399
  });
226265
226400
  await upgradePurl(path2, upgradeSpecs, options);
226266
226401
  }).configureHelp({ sortOptions: true });
226402
+ var computeFixesAndUpgradePurlsCmd = new Command();
226403
+ computeFixesAndUpgradePurlsCmd.name("compute-fixes-and-upgrade-purls").argument("<path>", "File system path to the folder containing the project").option("-a, --apply-fixes-to <ghsas...>", "GHSA IDs to compute fixes for", []).option("--dry-run", "Show what changes would be made without actually making them", false).option("-g, --glob <pattern>", "Glob pattern to filter workspaces by absolute file path").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).addOption(new Option("--run-without-docker", "Run package managers without using docker").default(process.env.RUN_WITHOUT_DOCKER === "true").hideHelp()).version(version2).action(async (path2, options) => {
226404
+ process.env.DOCKER_IMAGE_TAG ??= version2;
226405
+ await computeFixesAndUpgradePurls(path2, options);
226406
+ }).configureHelp({ sortOptions: true });
226267
226407
  var compareReportsCommand = new Command();
226268
226408
  compareReportsCommand.name("compare-reports").argument("<baselineReportPath>", "Path to the baseline report").argument("<newReportPath>", "Path to the new report").option("--api-key <key>", "Set the Coana dashboard API key.").option("-d, --debug", "Enable debug logging", false).option("--no-pr-comment", "Disable pull request comments (only relevant when run from a PR)", true).option("--no-block", "Do not fail with a non-zero exit code when new reachable vulnerabilities are detected", true).option("--ignore-undeterminable-reachability", "Ignore vulnerabilities with undeterminable reachability", false).action(async (baselineReportPath, newReportPath, options) => {
226269
226409
  async function readReport(reportPath) {
@@ -226273,8 +226413,29 @@ compareReportsCommand.name("compare-reports").argument("<baselineReportPath>", "
226273
226413
  const newReport = await readReport(newReportPath);
226274
226414
  await compareReports(baselineReport, newReport, options);
226275
226415
  });
226276
- program2.name("coana-cli").addCommand(run2, { isDefault: true }).addCommand(applyFixes).addCommand(upgradePurls, { hidden: true }).addCommand(compareReportsCommand).configureHelp({ sortSubcommands: true }).version(version2);
226416
+ program2.name("coana-cli").addCommand(run2, { isDefault: true }).addCommand(applyFixes).addCommand(upgradePurls, { hidden: true }).addCommand(compareReportsCommand).addCommand(computeFixesAndUpgradePurlsCmd, { hidden: true }).configureHelp({ sortSubcommands: true }).version(version2);
226277
226417
  program2.parseAsync();
226418
+ var defaultCliOptions = {
226419
+ debug: false,
226420
+ silent: false,
226421
+ printReport: false,
226422
+ memoryLimit: "8192",
226423
+ timeout: "300000",
226424
+ concurrency: "1",
226425
+ writeReportToFile: false,
226426
+ printAnalysisLogFile: false,
226427
+ includeProjectsWithNoReachabilitySupport: false,
226428
+ providerProject: void 0,
226429
+ providerWorkspaces: void 0,
226430
+ disableReportSubmission: false,
226431
+ runWithoutDocker: false,
226432
+ lightweightReachability: false,
226433
+ runEnv: "UNKNOWN",
226434
+ guardrailMode: false
226435
+ };
226436
+ export {
226437
+ defaultCliOptions
226438
+ };
226278
226439
  /*! Bundled license information:
226279
226440
 
226280
226441
  safe-buffer/index.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.9.29",
3
+ "version": "14.9.31",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {