@coana-tech/cli 14.9.29 → 14.9.30

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