@coana-tech/cli 14.12.127 → 14.12.129

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
@@ -251101,7 +251101,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
251101
251101
  }
251102
251102
 
251103
251103
  // dist/version.js
251104
- var version3 = "14.12.127";
251104
+ var version3 = "14.12.129";
251105
251105
 
251106
251106
  // dist/cli-core.js
251107
251107
  var { mapValues, omit, partition, pickBy: pickBy2 } = import_lodash15.default;
@@ -251282,21 +251282,26 @@ var CliCore = class {
251282
251282
  this.spinner.stop();
251283
251283
  return report;
251284
251284
  }
251285
- await logger.finish();
251286
- if (this.socketLogServer) {
251287
- await this.socketLogServer.close();
251288
- }
251285
+ await this.cleanupLogging();
251289
251286
  } catch (e) {
251290
251287
  await this.spinner.fail();
251291
251288
  logger.error("CLI failed with error:", e);
251292
251289
  await this.shareErrorLogWithBackend(e, true, "cli-error");
251293
- await logger.finish();
251294
- if (this.socketLogServer) {
251295
- await this.socketLogServer.close();
251296
- }
251290
+ await this.cleanupLogging();
251297
251291
  process.exit(1);
251298
251292
  }
251299
251293
  }
251294
+ /**
251295
+ * Clean up logging infrastructure in the correct order:
251296
+ * 1. Close socket server first to ensure all logs are forwarded to the batched HTTP streamer
251297
+ * 2. Then finish logger which flushes the batched HTTP streamer to the backend
251298
+ */
251299
+ async cleanupLogging() {
251300
+ if (this.socketLogServer) {
251301
+ await this.socketLogServer.close();
251302
+ }
251303
+ await logger.finish();
251304
+ }
251300
251305
  async computeAndOutputReportSocketMode(otherModulesCommunicator) {
251301
251306
  logger.info("Fetching artifacts from Socket backend");
251302
251307
  this.sendProgress("SCAN_FOR_VULNERABILITIES", true, ".", ".");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.12.127",
3
+ "version": "14.12.129",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -76315,7 +76315,11 @@ var SocketTransport = class extends import_winston_transport.default {
76315
76315
  this.connect();
76316
76316
  }
76317
76317
  connect() {
76318
+ if (this.socket) {
76319
+ this.socket.destroy();
76320
+ }
76318
76321
  this.socket = new Socket();
76322
+ this.socket.unref();
76319
76323
  this.socket.on("connect", () => {
76320
76324
  this.connected = true;
76321
76325
  const handshake = {
@@ -76341,10 +76345,11 @@ var SocketTransport = class extends import_winston_transport.default {
76341
76345
  if (this.reconnectTimer) return;
76342
76346
  this.reconnectTimer = setTimeout(() => {
76343
76347
  this.reconnectTimer = null;
76344
- if (!this.connected && this.socket) {
76348
+ if (!this.connected) {
76345
76349
  this.connect();
76346
76350
  }
76347
76351
  }, 1e3);
76352
+ this.reconnectTimer.unref();
76348
76353
  }
76349
76354
  sendMessage(message) {
76350
76355
  if (!this.socket || !this.connected) {
@@ -80232,7 +80237,7 @@ async function sendRegressionsToDashboard(regressions, subprojectPath, workspace
80232
80237
  );
80233
80238
  } catch (e) {
80234
80239
  sendWarningToDashboard(
80235
- "Unable to get latest buckets",
80240
+ "Unable to send regressions from experimental runs",
80236
80241
  { subprojectPath, workspacePath, reportId },
80237
80242
  void 0,
80238
80243
  reportId,
@@ -95833,7 +95838,7 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
95833
95838
  const outputFile = resolve10(tmpDir, "output.json");
95834
95839
  await writeFile4(inputFile, JSON.stringify(options));
95835
95840
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
95836
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, { timeout: timeoutMs });
95841
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
95837
95842
  if (result.error)
95838
95843
  return void 0;
95839
95844
  const packageIds = JSON.parse(await readFile6(outputFile, "utf-8")).result;
@@ -95872,7 +95877,7 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
95872
95877
  const outputFile = resolve10(tmpDir, "output.json");
95873
95878
  await writeFile4(inputFile, JSON.stringify(options));
95874
95879
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
95875
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, { timeout: timeoutMs });
95880
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${getCocoaPath()} --tree-sitter-c-sharp ${getTreeSitterCSharpPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
95876
95881
  if (result.error)
95877
95882
  return { type: "error", message: result.error.message ?? "unknown error" };
95878
95883
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile6(outputFile, "utf-8")).result;
@@ -109809,7 +109814,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
109809
109814
  const outputFile = resolve11(tmpDir, "output.json");
109810
109815
  await writeFile5(inputFile, JSON.stringify(options));
109811
109816
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
109812
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runJvmDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${getJavapServicePath()} --tree-sitter-java ${getTreeSitterJavaPath()} --tree-sitter-kotlin ${getTreeSitterKotlinPath()} --tree-sitter-scala ${getTreeSitterScalaPath()}`, void 0, { timeout: timeoutMs });
109817
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runJvmDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${getJavapServicePath()} --tree-sitter-java ${getTreeSitterJavaPath()} --tree-sitter-kotlin ${getTreeSitterKotlinPath()} --tree-sitter-scala ${getTreeSitterScalaPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
109813
109818
  if (result.error)
109814
109819
  return void 0;
109815
109820
  const packageIds = JSON.parse(await readFile7(outputFile, "utf-8")).result;
@@ -109848,7 +109853,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
109848
109853
  const outputFile = resolve11(tmpDir, "output.json");
109849
109854
  await writeFile5(inputFile, JSON.stringify(options));
109850
109855
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
109851
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runJvmReachabilityAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${getJavapServicePath()} --tree-sitter-java ${getTreeSitterJavaPath()} --tree-sitter-kotlin ${getTreeSitterKotlinPath()} --tree-sitter-scala ${getTreeSitterScalaPath()}`, void 0, { timeout: timeoutMs });
109856
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runJvmReachabilityAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${getJavapServicePath()} --tree-sitter-java ${getTreeSitterJavaPath()} --tree-sitter-kotlin ${getTreeSitterKotlinPath()} --tree-sitter-scala ${getTreeSitterScalaPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
109852
109857
  if (result.error)
109853
109858
  return { type: "error", message: result.error.message ?? "unknown error" };
109854
109859
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile7(outputFile, "utf-8")).result;
@@ -110479,9 +110484,8 @@ async function runJellyAnalysis(mainProjectRoot, projectRoot, jellyOptions, reac
110479
110484
  void 0,
110480
110485
  // If experiment is enabled, fail if Jelly exceeds 1.5x the timeout.
110481
110486
  // Otherwise, fail if Jelly exceeds 3x the timeout.
110482
- // This helps avoid pathological cases where hitting the memory cap makes GC dominate execution,
110483
- // causing timeout checks to not trigger promptly.
110484
- { timeout: timeoutInSeconds * 1e3 * (experiment ? 1.5 : 3) }
110487
+ // Use SIGKILL to ensure termination even if the process is unresponsive (e.g., due to GC pressure).
110488
+ { timeout: timeoutInSeconds * 1e3 * (experiment ? 1.5 : 3), killSignal: "SIGKILL" }
110485
110489
  );
110486
110490
  if (reachabilityAnalysisOptions.printLogFile)
110487
110491
  logger.info("JS analysis log file:", await readFile8(logFile, "utf-8"));
@@ -110522,7 +110526,10 @@ async function runJellyPhantomDependencyAnalysis(projectRoot, options) {
110522
110526
  const jellyCmd = cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} --max-old-space-size=${options.memoryLimitInMB}
110523
110527
  ${jellyExecutable} --basedir ${projectRoot} --modules-only --ignore-dependencies
110524
110528
  --reachable-json ${reachablePackagesFile} ${projectRoot}`;
110525
- await runCommandResolveStdOut2(jellyCmd, void 0, { timeout: options.timeoutSeconds.allVulnRuns * 1e3 });
110529
+ await runCommandResolveStdOut2(jellyCmd, void 0, {
110530
+ timeout: options.timeoutSeconds.allVulnRuns * 1e3,
110531
+ killSignal: "SIGKILL"
110532
+ });
110526
110533
  return JSON.parse(await readFile8(reachablePackagesFile, "utf-8")).packages;
110527
110534
  } finally {
110528
110535
  await rm2(tmpFolder, { recursive: true });
@@ -110539,7 +110546,10 @@ async function runJellyImportReachabilityAnalysis(mainProjectRoot, projectRoot,
110539
110546
  ${getExcludes(mainProjectRoot, projectRoot, options)}
110540
110547
  --reachable-json ${reachableModulesFile}
110541
110548
  ${options.entryPoints ?? projectRoot}`;
110542
- await runCommandResolveStdOut2(jellyCmd, void 0, { timeout: options.timeoutSeconds.allVulnRuns * 1e3 });
110549
+ await runCommandResolveStdOut2(jellyCmd, void 0, {
110550
+ timeout: options.timeoutSeconds.allVulnRuns * 1e3,
110551
+ killSignal: "SIGKILL"
110552
+ });
110543
110553
  return JSON.parse(await readFile8(reachableModulesFile, "utf-8"));
110544
110554
  } finally {
110545
110555
  await rm2(tmpFolder, { recursive: true });
@@ -110798,6 +110808,7 @@ var GoCodeAwareVulnerabilityScanner = class {
110798
110808
  -topk=4 ${heuristic.includeTests && "-tests"}
110799
110809
  ${this.projectDir} ${vulnAccPaths}`, void 0, {
110800
110810
  timeout: timeoutInSeconds * 1e3,
110811
+ killSignal: "SIGKILL",
110801
110812
  env: memoryLimitInMB ? { ...process.env, GOMEMLIMIT: `${memoryLimitInMB}MiB` } : void 0
110802
110813
  });
110803
110814
  if (error) {
@@ -111197,7 +111208,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111197
111208
  const outputFile = resolve16(tmpDir, "output.json");
111198
111209
  await writeFile8(inputFile, JSON.stringify(options));
111199
111210
  const timeoutMs = Math.max(timeoutInSeconds * 1.5, timeoutInSeconds + 30) * 1e3;
111200
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runRustDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${getTreeSitterRustPath()}`, void 0, { timeout: timeoutMs });
111211
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runRustDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${getTreeSitterRustPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
111201
111212
  if (result.error)
111202
111213
  return void 0;
111203
111214
  const packageIds = JSON.parse(await readFile10(outputFile, "utf-8")).result;
@@ -111233,7 +111244,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
111233
111244
  const outputFile = resolve16(tmpDir, "output.json");
111234
111245
  await writeFile8(inputFile, JSON.stringify(options));
111235
111246
  const timeoutMs = Math.max(effectiveTimeout * 1.5, effectiveTimeout + 30) * 1e3;
111236
- const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runRustReachabilityAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${getTreeSitterRustPath()}`, void 0, { timeout: timeoutMs });
111247
+ const result = await execNeverFail2(cmdt`${await getNodeExecutable(ToolPathResolver.nodeExecutablePath)} ${getClassGraphAnalysisCliPath()} runRustReachabilityAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${getTreeSitterRustPath()}`, void 0, { timeout: timeoutMs, killSignal: "SIGKILL" });
111237
111248
  if (result.error)
111238
111249
  return { type: "error", message: result.error.message ?? "unknown error" };
111239
111250
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile10(outputFile, "utf-8")).result;
@@ -111760,8 +111771,10 @@ ${vulnAccPaths.join("\n")}`);
111760
111771
  ...process.env,
111761
111772
  PYPY_GC_MAX: `${reachabilityAnalysisOptions.memoryLimitInMB ?? 0}MB`
111762
111773
  },
111763
- // Forcefully kill the process if the internal timeout mechanism fails
111764
- timeout: (timeoutInSeconds * 1.5 + 15) * 1e3
111774
+ // Forcefully kill the process if the internal timeout mechanism fails.
111775
+ // Use SIGKILL to ensure termination even if the process is unresponsive.
111776
+ timeout: (timeoutInSeconds * 1.5 + 15) * 1e3,
111777
+ killSignal: "SIGKILL"
111765
111778
  });
111766
111779
  logger.debug("Done running mambalade");
111767
111780
  const errors = stderr.split("\n").filter((line) => line.startsWith("ERROR:") && !/^ERROR: Excluded distribution/.test(line));
@@ -112420,23 +112433,22 @@ async function analyzeWithHeuristics(state, vulns, heuristicsInOrder, doNotRecom
112420
112433
  const experimentalUrlToReachability = transformVulnsToUrlToReachability(experimentalRes.augmentedVulnerabilities);
112421
112434
  const vulnUrlsWithPotentialRegressions = experimentalRes.augmentedVulnerabilities.filter((v) => previousAnalysisResults.reachabilityResults[v.url] && // If the vulnerability is new we do not have a previous reachability result
112422
112435
  getVulnReachability(v.results) !== previousAnalysisResults.reachabilityResults[v.url]).map((v) => v.url);
112423
- const bucketsToRecompute = experimentalRes.analysisMetadata.filter((am) => am.vulnUrls.some((v) => vulnUrlsWithPotentialRegressions.includes(v)));
112424
- const bucketsNotToRecompute = experimentalRes.analysisMetadata.filter((am) => !am.vulnUrls.some((v) => vulnUrlsWithPotentialRegressions.includes(v)));
112425
- bucketsToRecompute.forEach((b) => {
112426
- analysisMetadataCollector?.(Object.assign({}, b, { finalResult: false }));
112427
- });
112428
- bucketsNotToRecompute.forEach((b) => {
112436
+ const [bucketsToRecompute, bucketsNotToRecompute] = import_lodash17.default.partition(experimentalRes.analysisMetadata, (am) => am.vulnUrls.some((v) => vulnUrlsWithPotentialRegressions.includes(v)));
112437
+ for (const b of bucketsToRecompute)
112438
+ analysisMetadataCollector?.({ ...b, finalResult: false });
112439
+ for (const b of bucketsNotToRecompute)
112429
112440
  analysisMetadataCollector?.(b);
112430
- });
112431
- sendTimeRegressionsToDashboard(expHeuristicName, previousAnalysisResults.analysisMetadata, bucketsNotToRecompute);
112441
+ await sendTimeRegressionsToDashboard(expHeuristicName, previousAnalysisResults.analysisMetadata, bucketsNotToRecompute);
112432
112442
  let resWithoutExperimentalHeuristic;
112433
112443
  if (bucketsToRecompute.length > 0) {
112434
112444
  resWithoutExperimentalHeuristic = await analyzeAndAugmentVulns(bucketsToRecompute.map((b) => ({
112435
112445
  heuristic: getHeuristicFromName(state, b.heuristicName, ecosystem),
112436
112446
  vulnerabilities: b.vulnUrls.map((vUrl) => vulnerabilities.find((v) => v.url === vUrl))
112437
112447
  })), analysisMetadataCollector, true);
112438
- sendTimeRegressionsToDashboard(expHeuristicName, resWithoutExperimentalHeuristic.analysisMetadata, bucketsToRecompute);
112439
- sendReachabilityRegressionsToDashboard(resWithoutExperimentalHeuristic.analysisMetadata[0].heuristicName, expHeuristicName, transformVulnsToUrlToReachability(resWithoutExperimentalHeuristic.augmentedVulnerabilities), experimentalUrlToReachability);
112448
+ await Promise.all([
112449
+ sendTimeRegressionsToDashboard(expHeuristicName, resWithoutExperimentalHeuristic.analysisMetadata, bucketsToRecompute),
112450
+ sendReachabilityRegressionsToDashboard(resWithoutExperimentalHeuristic.analysisMetadata[0].heuristicName, expHeuristicName, transformVulnsToUrlToReachability(resWithoutExperimentalHeuristic.augmentedVulnerabilities), experimentalUrlToReachability)
112451
+ ]);
112440
112452
  }
112441
112453
  const vulnsToGetFromExperimental = bucketsNotToRecompute.flatMap((b) => b.vulnUrls);
112442
112454
  return {
@@ -112610,52 +112622,51 @@ async function analyzeWithHeuristics(state, vulns, heuristicsInOrder, doNotRecom
112610
112622
  return false;
112611
112623
  return oldDiagnostics.timings?.totalTime * 1.3 < newDiagnostics.timings?.totalTime && oldDiagnostics.timings?.totalTime + 5e3 < newDiagnostics.timings?.totalTime;
112612
112624
  }
112613
- function sendTimeRegressionsToDashboard(experimentName, oldAnalysisMetadata, newAnalysisMetadata) {
112625
+ async function sendTimeRegressionsToDashboard(experimentName, oldAnalysisMetadata, newAnalysisMetadata) {
112614
112626
  const regressions = [];
112615
- newAnalysisMetadata.forEach((newMd) => {
112627
+ for (const newMd of newAnalysisMetadata) {
112616
112628
  const oldMd = oldAnalysisMetadata.find((oldMd2) => newMd.vulnUrls.some((vulnUrl) => oldMd2.vulnUrls.includes(vulnUrl)));
112617
112629
  if (!oldMd) {
112618
- sendWarningToDashboard("Could not find corresponding analysis metadata to compare time regressions with", {
112630
+ await sendWarningToDashboard("Could not find corresponding analysis metadata to compare time regressions with", {
112619
112631
  subprojectPath: relative8(state.rootWorkingDir, state.subprojectDir) || ".",
112620
112632
  workspacePath: state.workspacePath
112621
112633
  }, void 0, COANA_REPORT_ID, apiKey);
112622
- return;
112634
+ continue;
112623
112635
  }
112624
- if (!hasTimeRegression(oldMd.analysisDiagnostics, newMd.analysisDiagnostics))
112625
- return;
112626
- regressions.push({
112627
- type: "ANALYSIS_TIME",
112628
- heuristicName: oldMd.heuristicName,
112629
- experimentName,
112630
- vulnUrls: oldMd.vulnUrls,
112631
- analyzerName: codeAwareScanner.name,
112632
- originalResult: {
112633
- timedOut: oldMd.analysisDiagnostics.timeout,
112634
- aborted: oldMd.analysisDiagnostics.aborted,
112635
- totalTime: oldMd.analysisDiagnostics.timings.totalTime
112636
- },
112637
- experimentResult: {
112638
- timedOut: newMd.analysisDiagnostics.timeout,
112639
- aborted: newMd.analysisDiagnostics.aborted,
112640
- totalTime: newMd.analysisDiagnostics.timings.totalTime
112641
- }
112642
- });
112643
- });
112636
+ if (hasTimeRegression(oldMd.analysisDiagnostics, newMd.analysisDiagnostics))
112637
+ regressions.push({
112638
+ type: "ANALYSIS_TIME",
112639
+ heuristicName: oldMd.heuristicName,
112640
+ experimentName,
112641
+ vulnUrls: oldMd.vulnUrls,
112642
+ analyzerName: codeAwareScanner.name,
112643
+ originalResult: {
112644
+ timedOut: oldMd.analysisDiagnostics.timeout,
112645
+ aborted: oldMd.analysisDiagnostics.aborted,
112646
+ totalTime: oldMd.analysisDiagnostics.timings.totalTime
112647
+ },
112648
+ experimentResult: {
112649
+ timedOut: newMd.analysisDiagnostics.timeout,
112650
+ aborted: newMd.analysisDiagnostics.aborted,
112651
+ totalTime: newMd.analysisDiagnostics.timings.totalTime
112652
+ }
112653
+ });
112654
+ }
112644
112655
  if (regressions.length === 0)
112645
112656
  return;
112646
- sendRegressionsToDashboard(regressions, relative8(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, COANA_REPORT_ID, apiKey);
112657
+ await sendRegressionsToDashboard(regressions, relative8(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, COANA_REPORT_ID, apiKey);
112647
112658
  }
112648
- function sendReachabilityRegressionsToDashboard(heuristicName, experimentName, origRes, experimentRes) {
112649
- const regressions = Object.keys(origRes).filter((vulnUrl) => experimentRes[vulnUrl] && origRes[vulnUrl] !== experimentRes[vulnUrl]).map((vulnUrl) => ({
112659
+ async function sendReachabilityRegressionsToDashboard(heuristicName, experimentName, origRes, experimentRes) {
112660
+ const regressions = Object.entries(origRes).filter(([vulnUrl, oRes]) => experimentRes[vulnUrl] && oRes.reachability !== experimentRes[vulnUrl].reachability).map(([vulnUrl, originalResult]) => ({
112650
112661
  type: "REACHABILITY",
112651
112662
  heuristicName,
112652
112663
  experimentName,
112653
112664
  analyzerName: codeAwareScanner.name,
112654
112665
  vulnUrl,
112655
- originalResult: origRes[vulnUrl],
112666
+ originalResult,
112656
112667
  experimentResult: experimentRes[vulnUrl]
112657
112668
  }));
112658
- sendRegressionsToDashboard(regressions, relative8(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, COANA_REPORT_ID, apiKey);
112669
+ await sendRegressionsToDashboard(regressions, relative8(state.rootWorkingDir, state.subprojectDir) || ".", state.workspacePath, COANA_REPORT_ID, apiKey);
112659
112670
  }
112660
112671
  }
112661
112672
  function getHeuristicFromName(state, heuristicName, ecosystem) {
@@ -112738,7 +112749,10 @@ function findDuplicateVulnsInBuckets(bucketsFromLastAnalysis) {
112738
112749
  return duplicateUrls;
112739
112750
  }
112740
112751
  function transformVulnsToUrlToReachability(oldHeuristicAugmentedVulnerabilities) {
112741
- return Object.fromEntries(oldHeuristicAugmentedVulnerabilities.map((v) => [v.url, getVulnReachability(v.results)]));
112752
+ return Object.fromEntries(oldHeuristicAugmentedVulnerabilities.map((v) => [
112753
+ v.url,
112754
+ { reachability: getVulnReachability(v.results), terminatedEarly: v.results.type === "success" && v.results.terminatedEarly }
112755
+ ]));
112742
112756
  }
112743
112757
 
112744
112758
  // dist/analyzers/go-analyzer.js
@@ -116504,7 +116518,10 @@ var RubyCodeAwareVulnerabilityScanner = class {
116504
116518
  logger.info("Ruby analysis command:", cmd.join(" "));
116505
116519
  try {
116506
116520
  this.numberAnalysesRun++;
116507
- await exec2(cmd, this.projectDir, { timeout: (timeoutInSeconds * 1.5 + 10) * 1e3 });
116521
+ await exec2(cmd, this.projectDir, {
116522
+ timeout: (timeoutInSeconds * 1.5 + 10) * 1e3,
116523
+ killSignal: "SIGKILL"
116524
+ });
116508
116525
  const result = JSON.parse(await readFile12(vulnsOutputFile, "utf-8"));
116509
116526
  const relativeLoadPathsToPackageNames = new Map([...loadPathsToPackageNames.entries()].map(([k, v]) => [join17("vendor", relative9(this.vendorDir, k)), v]));
116510
116527
  const { timedOut, ...diagnostics } = JSON.parse(await readFile12(diagnosticsOutputFile, "utf-8"));