@coana-tech/cli 14.11.15 → 14.11.16

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
@@ -197870,6 +197870,41 @@ async function registerAnalysisMetadataSocket(subprojectPath, workspacePath, eco
197870
197870
  handleError(error, "Error registering analysis metadata", false);
197871
197871
  }
197872
197872
  }
197873
+ async function getLatestBucketsSocket(subprojectPath, workspacePath) {
197874
+ try {
197875
+ const url2 = getSocketApiUrl("tier1-reachability-scan/latest-buckets");
197876
+ const params = {
197877
+ workspacePath,
197878
+ subprojectPath,
197879
+ repoName: process.env.SOCKET_REPO_NAME,
197880
+ branchName: process.env.SOCKET_BRANCH_NAME
197881
+ };
197882
+ const response = await axios2.get(url2, {
197883
+ headers: getAuthHeaders(),
197884
+ params
197885
+ });
197886
+ const responseData = response.data;
197887
+ if (responseData.type !== "success") {
197888
+ throw new Error(response.data.reason);
197889
+ }
197890
+ return {
197891
+ cliVersion: responseData.value.coana_cli_version,
197892
+ buckets: responseData.value.buckets.map((b) => ({
197893
+ vulnUrls: b.ghsas,
197894
+ heuristicName: b.heuristicName
197895
+ }))
197896
+ };
197897
+ } catch (error) {
197898
+ if (error?.response?.data?.message === "No successful report found") {
197899
+ return void 0;
197900
+ }
197901
+ logger.warn(
197902
+ "Unable to retrieve cached analysis configuration. Will continue with default configuration.",
197903
+ error?.message
197904
+ );
197905
+ return void 0;
197906
+ }
197907
+ }
197873
197908
  async function useSocketComputeFixEndpoint(artifacts, vulnerableArtifactIdsForGhsas) {
197874
197909
  try {
197875
197910
  const url2 = getSocketApiUrl("fixes/compute-fixes");
@@ -197945,7 +197980,8 @@ function getSocketAPI() {
197945
197980
  sendErrorReportToSocketDashboard,
197946
197981
  registerSubprojectsSocket,
197947
197982
  registerCLIProgressSocket,
197948
- registerAnalysisMetadataSocket
197983
+ registerAnalysisMetadataSocket,
197984
+ getLatestBucketsSocket
197949
197985
  };
197950
197986
  }
197951
197987
 
@@ -208053,6 +208089,28 @@ async function registerAnalysisMetadataCoana(subprojectPath, workspacePath, ecos
208053
208089
  handleError(e, "Unable to create analysis metadata");
208054
208090
  }
208055
208091
  }
208092
+ async function getBucketsForLastReport(subprojectPath, workspacePath, ecosystem, newReportId, apiKey) {
208093
+ if (!newReportId || apiKey.type === "missing") return;
208094
+ try {
208095
+ return (await axios_default.get(coanaAPIUrls.GET_LATEST_BUCKETS, {
208096
+ headers: {
208097
+ "Content-Type": "application/json",
208098
+ apiKey: apiKey.value
208099
+ },
208100
+ params: { newReportId, subprojectPath, workspacePath, ecosystem }
208101
+ })).data;
208102
+ } catch (e) {
208103
+ if (e.response?.data?.message === "No successful report found") return;
208104
+ sendWarningToDashboard(
208105
+ "Unable to get latest buckets",
208106
+ { subprojectPath, workspacePath, newReportId },
208107
+ void 0,
208108
+ newReportId,
208109
+ apiKey
208110
+ );
208111
+ logger.warn("Unable to get latest buckets:", e.message);
208112
+ }
208113
+ }
208056
208114
  async function registerCLIProgressCoana(cliProgressEvent, isStartEvent, reportId, apiKey) {
208057
208115
  if (!reportId || apiKey.type === "missing") return;
208058
208116
  try {
@@ -208172,7 +208230,8 @@ function getCoanaAPI() {
208172
208230
  registerSubprojectsCoana,
208173
208231
  registerAnalysisMetadataCoana,
208174
208232
  registerCLIProgressCoana,
208175
- sendErrorReportToCoanaDashboard
208233
+ sendErrorReportToCoanaDashboard,
208234
+ getBucketsForLastReport
208176
208235
  };
208177
208236
  }
208178
208237
 
@@ -209739,6 +209798,19 @@ var DashboardAPI = class {
209739
209798
  );
209740
209799
  }
209741
209800
  }
209801
+ async getBucketsForLastReport(subprojectPath, workspacePath, ecosystem, reportId, apiKey) {
209802
+ if (this.socketMode) {
209803
+ return await this.socketAPI.getLatestBucketsSocket(subprojectPath, workspacePath);
209804
+ } else {
209805
+ return await this.coanaAPI.getBucketsForLastReport(
209806
+ subprojectPath,
209807
+ workspacePath,
209808
+ ecosystem,
209809
+ reportId,
209810
+ apiKey
209811
+ );
209812
+ }
209813
+ }
209742
209814
  };
209743
209815
 
209744
209816
  // ../utils/src/promise-queue.ts
@@ -225421,7 +225493,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
225421
225493
  }
225422
225494
 
225423
225495
  // dist/version.js
225424
- var version2 = "14.11.15";
225496
+ var version2 = "14.11.16";
225425
225497
 
225426
225498
  // dist/cli-core.js
225427
225499
  var { mapValues, omit, partition, pick } = import_lodash15.default;
@@ -226224,43 +226296,44 @@ ${vulnerabilityFixes.map((fix) => ` ${fix.dependencyName} from ${fix.currentVers
226224
226296
 
226225
226297
  // dist/cli-compute-fixes-and-upgrade-purls.js
226226
226298
  async function computeFixesAndUpgradePurls(path2, options) {
226227
- const { artifacts, vulnerableArtifactIdsPerVulnerability } = await computeInputForComputingFixes(path2, options);
226228
- if (vulnerableArtifactIdsPerVulnerability.size === 0) {
226299
+ const { artifacts, ghsaToVulnerableArtifactIds } = await computeInputForComputingFixes(path2, options);
226300
+ if (Object.keys(ghsaToVulnerableArtifactIds).length === 0) {
226229
226301
  logger.info("No vulnerabilities to compute fixes for");
226230
226302
  return;
226231
226303
  }
226232
226304
  if (options.applyFixesTo.length === 0) {
226233
- logger.info("Vulnerabilities found:", Array.from(vulnerableArtifactIdsPerVulnerability.keys()).join(", "));
226305
+ logger.info("Vulnerabilities found:", Object.keys(ghsaToVulnerableArtifactIds).join(", "));
226234
226306
  logger.info("Run again with --apply-fixes-to GHSA_IDS to fix those vulnerabilities by computing packages to upgrade and apply them");
226235
226307
  return;
226236
226308
  }
226237
- const vulnerableArtifactIdsForGhsas = options.applyFixesTo.includes("all") ? Array.from(vulnerableArtifactIdsPerVulnerability.values()).flatMap((ids) => Array.from(ids)) : options.applyFixesTo.flatMap((ghsa) => [...vulnerableArtifactIdsPerVulnerability.get(ghsa)?.values() ?? []]);
226238
- const computedFix = await useSocketComputeFixEndpoint(artifacts, vulnerableArtifactIdsForGhsas);
226309
+ const ghsaToVulnerableArtifactIdsToApply = options.applyFixesTo.includes("all") ? ghsaToVulnerableArtifactIds : Object.fromEntries(Object.entries(ghsaToVulnerableArtifactIds).filter(([ghsa]) => options.applyFixesTo.includes(ghsa)));
226310
+ const computedFix = await useSocketComputeFixEndpoint(artifacts, ghsaToVulnerableArtifactIdsToApply);
226239
226311
  if (computedFix.type !== "success") {
226240
226312
  throw new Error(`No fix found for the given vulnerabilities`);
226241
226313
  }
226242
- if (computedFix.failedArtifacts) {
226243
- const ghsasFailedToFix = options.applyFixesTo.filter((ghsa) => {
226244
- const artifactIds = vulnerableArtifactIdsPerVulnerability.get(ghsa);
226245
- if (!artifactIds)
226246
- return false;
226247
- return Array.from(artifactIds).some((vuln) => computedFix.failedArtifacts?.includes(vuln));
226248
- });
226314
+ const ghsasFailedToFix = options.applyFixesTo.filter((ghsa) => {
226315
+ const artifactIds = ghsaToVulnerableArtifactIdsToApply[ghsa];
226316
+ if (!artifactIds)
226317
+ return false;
226318
+ return artifactIds.some((artifactId) => computedFix.ghsaToResult[ghsa].failedArtifacts?.includes(artifactId));
226319
+ });
226320
+ if (ghsasFailedToFix.length > 0) {
226249
226321
  logger.info("Failed to compute fixes for the following vulnerabilities:");
226250
- for (const ghsa of ghsasFailedToFix) {
226251
- logger.info(` - ${ghsa} (${Array.from(vulnerableArtifactIdsPerVulnerability.get(ghsa)).map((id) => simplePurl(artifacts[id].type, artifacts[id].namespace ?? null, artifacts[id].name ?? "", artifacts[id].version ?? null)).join(", ")})`);
226252
- }
226253
226322
  }
226323
+ for (const ghsa of ghsasFailedToFix) {
226324
+ logger.info(` - ${ghsa} (${ghsaToVulnerableArtifactIdsToApply[ghsa].map((id) => simplePurl(artifacts[id].type, artifacts[id].namespace ?? null, artifacts[id].name ?? "", artifacts[id].version ?? null)).join(", ")})`);
226325
+ }
226326
+ const combinedFixes = Object.values(computedFix.ghsaToResult).filter((result) => result.failedArtifacts === void 0 || result.failedArtifacts.length === 0).flatMap((result) => result.fixes);
226254
226327
  if (options.dryRun) {
226255
226328
  logger.info("Fixes found:");
226256
- for (const fix of computedFix.fixes) {
226329
+ for (const fix of combinedFixes) {
226257
226330
  logger.info(` - ${fix.purl} -> ${fix.fixedVersion}`);
226258
226331
  }
226259
226332
  logger.info("Run again without --dry-run to apply the fixes");
226260
226333
  return;
226261
226334
  }
226262
226335
  try {
226263
- await upgradePurl(path2, computedFix.fixes.map((fix) => ({ purl: fix.purl, upgradeVersion: fix.fixedVersion })), {
226336
+ await upgradePurl(path2, combinedFixes.map((fix) => ({ purl: fix.purl, upgradeVersion: fix.fixedVersion })), {
226264
226337
  debug: options.debug,
226265
226338
  silent: options.silent,
226266
226339
  runWithoutDocker: options.runWithoutDocker,
@@ -226276,13 +226349,13 @@ async function computeFixesAndUpgradePurls(path2, options) {
226276
226349
  async function computeInputForComputingFixes(path2, options) {
226277
226350
  if (options.manifestsTarHash) {
226278
226351
  const { artifacts: artifacts2 } = await fetchArtifactsFromSocket(path2, options.manifestsTarHash);
226279
- const vulnerableArtifactIdsPerVulnerability2 = /* @__PURE__ */ new Map();
226352
+ const ghsaToVulnerableArtifactIds2 = {};
226280
226353
  for (const [index2, artifact] of artifacts2.entries()) {
226281
- if (artifact.vulnerabilities) {
226282
- for (const vulnerability of artifact.vulnerabilities) {
226283
- if (!vulnerableArtifactIdsPerVulnerability2.has(vulnerability.ghsaId))
226284
- vulnerableArtifactIdsPerVulnerability2.set(vulnerability.ghsaId, /* @__PURE__ */ new Set());
226285
- vulnerableArtifactIdsPerVulnerability2.get(vulnerability.ghsaId).add(index2);
226354
+ if (!artifact.vulnerabilities)
226355
+ continue;
226356
+ for (const vulnerability of artifact.vulnerabilities) {
226357
+ if (!(ghsaToVulnerableArtifactIds2[vulnerability.ghsaId] ??= []).includes(index2)) {
226358
+ ghsaToVulnerableArtifactIds2[vulnerability.ghsaId].push(index2);
226286
226359
  }
226287
226360
  }
226288
226361
  }
@@ -226293,7 +226366,7 @@ async function computeInputForComputingFixes(path2, options) {
226293
226366
  namespace: artifact.namespace ?? void 0,
226294
226367
  adj: artifact.dependencies?.map((dep) => artifacts2.findIndex((a4) => a4.id === dep)) ?? []
226295
226368
  }));
226296
- return { artifacts: sbomTaskArtifacts, vulnerableArtifactIdsPerVulnerability: vulnerableArtifactIdsPerVulnerability2 };
226369
+ return { artifacts: sbomTaskArtifacts, ghsaToVulnerableArtifactIds: ghsaToVulnerableArtifactIds2 };
226297
226370
  }
226298
226371
  const otherModulesCommunicator = new OtherModulesCommunicator(path2, options, {
226299
226372
  type: "missing"
@@ -226307,21 +226380,24 @@ async function computeInputForComputingFixes(path2, options) {
226307
226380
  const cliCore = new CliCore(path2, { ...defaultCliOptions, socketMode: "true" });
226308
226381
  const results = await asyncMap(supportedSubprojects, async (subproject) => cliCore.getDependencyTreeAndVulnerabilities(otherModulesCommunicator, subproject));
226309
226382
  const { artifacts, purlToIndex } = computeSBOMTaskArtifacts(results.flatMap((r2) => Object.values(r2.projectInfo).map((info) => info.dataForAnalysis.data.dependencyTree)));
226310
- const vulnerableArtifactIdsPerVulnerability = computeVulnerableArtifactIdsPerVulnerability(results.flatMap((r2) => Object.values(r2.workspaceToVulnerabilities).flat()), purlToIndex);
226311
- return { artifacts, vulnerableArtifactIdsPerVulnerability };
226383
+ const ghsaToVulnerableArtifactIds = computeVulnerableArtifactIdsPerVulnerability(results.flatMap((r2) => Object.values(r2.workspaceToVulnerabilities).flat()), purlToIndex);
226384
+ return { artifacts, ghsaToVulnerableArtifactIds };
226312
226385
  }
226313
226386
  function computeVulnerableArtifactIdsPerVulnerability(vulnerabilities, purlToIndex) {
226314
- const vulnerableArtifactIdsPerVulnerability = /* @__PURE__ */ new Map();
226387
+ const vulnerableArtifactIdsPerVulnerability = {};
226315
226388
  for (const vulnerability of vulnerabilities) {
226316
- if (!vulnerableArtifactIdsPerVulnerability.has(vulnerability.url)) {
226317
- vulnerableArtifactIdsPerVulnerability.set(vulnerability.url, /* @__PURE__ */ new Set());
226389
+ if (!vulnerableArtifactIdsPerVulnerability[vulnerability.url]) {
226390
+ vulnerableArtifactIdsPerVulnerability[vulnerability.url] = [];
226318
226391
  }
226319
226392
  if (!vulnerability.purl)
226320
226393
  throw new Error(`Vulnerability ${vulnerability.url} has no purl`);
226321
226394
  if (!purlToIndex.has(vulnerability.purl)) {
226322
226395
  throw new Error(`Vulnerability ${vulnerability.url} has no purl in sbomTaskArtifacts`);
226323
226396
  }
226324
- vulnerableArtifactIdsPerVulnerability.get(vulnerability.url).add(purlToIndex.get(vulnerability.purl));
226397
+ const index2 = purlToIndex.get(vulnerability.purl);
226398
+ if (!vulnerableArtifactIdsPerVulnerability[vulnerability.url].includes(index2)) {
226399
+ vulnerableArtifactIdsPerVulnerability[vulnerability.url].push(index2);
226400
+ }
226325
226401
  }
226326
226402
  return vulnerableArtifactIdsPerVulnerability;
226327
226403
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.11.15",
3
+ "version": "14.11.16",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -73178,7 +73178,8 @@ function getCoanaAPI() {
73178
73178
  registerSubprojectsCoana,
73179
73179
  registerAnalysisMetadataCoana,
73180
73180
  registerCLIProgressCoana,
73181
- sendErrorReportToCoanaDashboard
73181
+ sendErrorReportToCoanaDashboard,
73182
+ getBucketsForLastReport
73182
73183
  };
73183
73184
  }
73184
73185
 
@@ -73352,13 +73353,49 @@ async function registerAnalysisMetadataSocket(subprojectPath, workspacePath, eco
73352
73353
  handleError(error, "Error registering analysis metadata", false);
73353
73354
  }
73354
73355
  }
73356
+ async function getLatestBucketsSocket(subprojectPath, workspacePath) {
73357
+ try {
73358
+ const url2 = getSocketApiUrl("tier1-reachability-scan/latest-buckets");
73359
+ const params = {
73360
+ workspacePath,
73361
+ subprojectPath,
73362
+ repoName: process.env.SOCKET_REPO_NAME,
73363
+ branchName: process.env.SOCKET_BRANCH_NAME
73364
+ };
73365
+ const response = await axios2.get(url2, {
73366
+ headers: getAuthHeaders(),
73367
+ params
73368
+ });
73369
+ const responseData = response.data;
73370
+ if (responseData.type !== "success") {
73371
+ throw new Error(response.data.reason);
73372
+ }
73373
+ return {
73374
+ cliVersion: responseData.value.coana_cli_version,
73375
+ buckets: responseData.value.buckets.map((b) => ({
73376
+ vulnUrls: b.ghsas,
73377
+ heuristicName: b.heuristicName
73378
+ }))
73379
+ };
73380
+ } catch (error) {
73381
+ if (error?.response?.data?.message === "No successful report found") {
73382
+ return void 0;
73383
+ }
73384
+ logger.warn(
73385
+ "Unable to retrieve cached analysis configuration. Will continue with default configuration.",
73386
+ error?.message
73387
+ );
73388
+ return void 0;
73389
+ }
73390
+ }
73355
73391
  function getSocketAPI() {
73356
73392
  return {
73357
73393
  createSocketTier1Scan,
73358
73394
  sendErrorReportToSocketDashboard,
73359
73395
  registerSubprojectsSocket,
73360
73396
  registerCLIProgressSocket,
73361
- registerAnalysisMetadataSocket
73397
+ registerAnalysisMetadataSocket,
73398
+ getLatestBucketsSocket
73362
73399
  };
73363
73400
  }
73364
73401
 
@@ -73454,6 +73491,19 @@ var DashboardAPI = class {
73454
73491
  );
73455
73492
  }
73456
73493
  }
73494
+ async getBucketsForLastReport(subprojectPath, workspacePath, ecosystem, reportId, apiKey3) {
73495
+ if (this.socketMode) {
73496
+ return await this.socketAPI.getLatestBucketsSocket(subprojectPath, workspacePath);
73497
+ } else {
73498
+ return await this.coanaAPI.getBucketsForLastReport(
73499
+ subprojectPath,
73500
+ workspacePath,
73501
+ ecosystem,
73502
+ reportId,
73503
+ apiKey3
73504
+ );
73505
+ }
73506
+ }
73457
73507
  };
73458
73508
 
73459
73509
  // dist/analyzers/go-analyzer.js
@@ -96850,6 +96900,7 @@ function assertVulnChainDetails(vs) {
96850
96900
  assert8(vs.every((v) => v.vulnChainDetails));
96851
96901
  }
96852
96902
  var apiKey = COANA_API_KEY ? { type: "present", value: COANA_API_KEY } : { type: "missing" };
96903
+ var dashboardAPI = new DashboardAPI(process.env.SOCKET_MODE === "true", process.env.DISABLE_ANALYTICS_SHARING === "true");
96853
96904
  async function analyzeWithHeuristics(state, vulns, heuristicsInOrder, doNotRecomputeForTimeoutsAndAborts, codeAwareScanner, analysisMetadataCollector, statusUpdater) {
96854
96905
  logger.debug("Starting analyzeWithHeuristics");
96855
96906
  assertVulnChainDetails(vulns);
@@ -96937,9 +96988,9 @@ async function analyzeWithHeuristics(state, vulns, heuristicsInOrder, doNotRecom
96937
96988
  }
96938
96989
  }
96939
96990
  async function getBucketsBasedOnPreviousResults() {
96940
- if (!COANA_REPORT_ID || apiKey.type === "missing")
96991
+ if (process.env.SOCKET_MODE !== "true" && (!COANA_REPORT_ID || apiKey.type === "missing"))
96941
96992
  return void 0;
96942
- const bucketsFromLastAnalysisAndCliVersion = await getBucketsForLastReport(relative5(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, vulnerabilities[0].ecosystem ?? "NPM", COANA_REPORT_ID, apiKey);
96993
+ const bucketsFromLastAnalysisAndCliVersion = await dashboardAPI.getBucketsForLastReport(relative5(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, vulnerabilities[0].ecosystem ?? "NPM", COANA_REPORT_ID, apiKey);
96943
96994
  if (!bucketsFromLastAnalysisAndCliVersion)
96944
96995
  return void 0;
96945
96996
  const { cliVersion, buckets: bucketsFromLastAnalysis } = bucketsFromLastAnalysisAndCliVersion;
@@ -97411,7 +97462,7 @@ var ecosystemAnalyzer = {
97411
97462
  RUST: RustAnalyzer
97412
97463
  };
97413
97464
  var apiKey2 = COANA_API_KEY ? { type: "present", value: COANA_API_KEY } : { type: "missing" };
97414
- var dashboardAPI = new DashboardAPI(process.env.SOCKET_MODE === "true", process.env.DISABLE_ANALYTICS_SHARING === "true");
97465
+ var dashboardAPI2 = new DashboardAPI(process.env.SOCKET_MODE === "true", process.env.DISABLE_ANALYTICS_SHARING === "true");
97415
97466
  async function runReachabilityAnalysis(state) {
97416
97467
  const projectDir = resolve16(state.subprojectDir, state.workspacePath);
97417
97468
  const ecosystem = state.workspaceData.data.type;
@@ -97425,7 +97476,7 @@ async function runReachabilityAnalysis(state) {
97425
97476
  }
97426
97477
  const [vulnerabilitiesWithPrecomputedResults, vulnerabilitiesWithoutPrecomputedResults] = partition3(state.vulnerabilities, (v) => "results" in v);
97427
97478
  const augmentedVulnerabilities = await runWholeProgramCodeAwareVulnerabilityScanner(analyzer, vulnerabilitiesWithoutPrecomputedResults, async (amd) => {
97428
- await dashboardAPI.registerAnalysisMetadata(relative6(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, state.workspaceData.data.type, amd, COANA_REPORT_ID, apiKey2);
97479
+ await dashboardAPI2.registerAnalysisMetadata(relative6(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, state.workspaceData.data.type, amd, COANA_REPORT_ID, apiKey2);
97429
97480
  });
97430
97481
  return [...vulnerabilitiesWithPrecomputedResults, ...augmentedVulnerabilities];
97431
97482
  }