@coana-tech/cli 14.12.112 → 14.12.114

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
@@ -206052,6 +206052,8 @@ async function fetchManifestFilesFromManifestsTarHash(manifestsTarHash) {
206052
206052
  }
206053
206053
  }
206054
206054
  async function fetchArtifactsFromManifestsTarHash(manifestsTarHash, includePrecomputedReachabilityResults) {
206055
+ logger.info("Fetching artifacts from Socket backend (this may take a while)");
206056
+ logger.debug("manifests tar hash", manifestsTarHash);
206055
206057
  let responseData;
206056
206058
  try {
206057
206059
  const params = new URLSearchParams({
@@ -231911,6 +231913,8 @@ async function copyForNpmAnalysis(srcDir, prefix) {
231911
231913
  try {
231912
231914
  await cp4(srcDir, tmpDir, {
231913
231915
  recursive: true,
231916
+ verbatimSymlinks: true,
231917
+ // Preserve symlinks as symlinks instead of dereferencing them
231914
231918
  filter: async (src) => {
231915
231919
  const relativePath = relative15(srcDir, src);
231916
231920
  if (relativePath === "") return true;
@@ -231919,6 +231923,9 @@ async function copyForNpmAnalysis(srcDir, prefix) {
231919
231923
  return false;
231920
231924
  }
231921
231925
  const stats = await lstat2(src);
231926
+ if (stats.isSymbolicLink()) {
231927
+ return true;
231928
+ }
231922
231929
  if (stats.isDirectory()) {
231923
231930
  return true;
231924
231931
  }
@@ -234402,310 +234409,10 @@ var signalFixApplied = (_fixId, subprojectPath, workspacePath, vulnerabilityFixe
234402
234409
  ${vulnerabilityFixes.map((fix) => ` ${fix.dependencyName} from ${fix.currentVersion} to ${fix.fixedVersion}`).join("\n")}`);
234403
234410
  };
234404
234411
 
234405
- // dist/internal/socket-mode-helpers-socket-dependency-trees.js
234406
- import { basename as basename9, dirname as dirname26, join as join27, sep as sep6 } from "path";
234407
- var REQUIREMENTS_FILES_SEARCH_DEPTH2 = 3;
234408
- var venvExcludes = [
234409
- "venv",
234410
- ".venv",
234411
- "env",
234412
- ".env",
234413
- "virtualenv",
234414
- ".virtualenv",
234415
- "venvs",
234416
- ".venvs",
234417
- "envs",
234418
- ".envs",
234419
- "__pycache__",
234420
- ".tox",
234421
- ".nox",
234422
- ".pytest_cache",
234423
- "site-packages",
234424
- "dist-packages",
234425
- "conda-meta",
234426
- "conda-bld",
234427
- ".mypy_cache",
234428
- ".ruff_cache",
234429
- ".hypothesis"
234430
- ];
234431
- function inferWorkspaceFromManifestPath(ecosystem, manifestPath, properPythonProjects) {
234432
- switch (ecosystem) {
234433
- case "NPM": {
234434
- const base = basename9(manifestPath);
234435
- const dir = dirname26(manifestPath);
234436
- return base === "package.json" ? dir || "." : void 0;
234437
- }
234438
- case "MAVEN": {
234439
- return ".";
234440
- }
234441
- case "PIP": {
234442
- if (venvExcludes.some((exclude) => manifestPath.startsWith(`${exclude}/`) || manifestPath.includes(`/${exclude}/`))) {
234443
- return void 0;
234444
- }
234445
- const base = basename9(manifestPath);
234446
- const dir = dirname26(manifestPath);
234447
- const workspaceDir = dir === "" ? "." : dir;
234448
- if (properPythonProjects.includes(workspaceDir)) {
234449
- return workspaceDir;
234450
- }
234451
- if (base === "poetry.lock" || base === "Pipfile.lock" || base === "uv.lock") {
234452
- return workspaceDir;
234453
- }
234454
- if (base.endsWith(".txt")) {
234455
- const properProjectDirs = properPythonProjects.filter((properProjectDir) => (properProjectDir === "." || workspaceDir === "." || workspaceDir.startsWith(properProjectDir)) && workspaceDir.replace(properProjectDir, "").split(sep6).length <= REQUIREMENTS_FILES_SEARCH_DEPTH2);
234456
- const longestProperProjectDir = l(properProjectDirs, [(d4) => d4.length, "desc"]);
234457
- if (longestProperProjectDir) {
234458
- return longestProperProjectDir;
234459
- }
234460
- return workspaceDir;
234461
- }
234462
- logger.warn(`No workspace found for manifest file ${manifestPath}`);
234463
- return void 0;
234464
- }
234465
- case "NUGET": {
234466
- return ".";
234467
- }
234468
- case "RUST": {
234469
- return dirname26(manifestPath) || ".";
234470
- }
234471
- case "GO": {
234472
- const base = basename9(manifestPath);
234473
- const dir = dirname26(manifestPath);
234474
- return base === "go.mod" ? dir || "." : void 0;
234475
- }
234476
- case "RUBYGEMS": {
234477
- return dirname26(manifestPath) || ".";
234478
- }
234479
- default: {
234480
- return ".";
234481
- }
234482
- }
234483
- }
234484
- function inferProjectFromManifestPath(ecosystem, manifestPath) {
234485
- switch (ecosystem) {
234486
- case "NPM": {
234487
- const filename = basename9(manifestPath);
234488
- if (["package-lock.json", "pnpm-lock.yaml", "pnpm-lock.yml", "yarn.lock"].includes(filename)) {
234489
- return dirname26(manifestPath) || ".";
234490
- }
234491
- return void 0;
234492
- }
234493
- }
234494
- }
234495
- function getAllToplevelAncestors(artifactMap, artifactId) {
234496
- const visited = /* @__PURE__ */ new Set();
234497
- const toplevelAncestors = /* @__PURE__ */ new Set();
234498
- function findAncestors(currentId) {
234499
- if (visited.has(currentId)) {
234500
- return;
234501
- }
234502
- visited.add(currentId);
234503
- const artifact = artifactMap.get(currentId);
234504
- if (!artifact) {
234505
- return;
234506
- }
234507
- if (artifact.toplevelAncestors && artifact.toplevelAncestors.length > 0) {
234508
- for (const ancestorId of artifact.toplevelAncestors) {
234509
- toplevelAncestors.add(ancestorId);
234510
- findAncestors(ancestorId);
234511
- }
234512
- }
234513
- }
234514
- findAncestors(artifactId);
234515
- return Array.from(toplevelAncestors);
234516
- }
234517
- async function fetchArtifactsFromSocket(rootWorkingDirectory, manifestsTarHash, mode, includePrecomputedReachabilityResults) {
234518
- logger.info("Fetching artifacts from Socket backend (this may take a while)");
234519
- logger.debug("manifests tar hash", manifestsTarHash);
234520
- try {
234521
- const { artifacts } = await fetchArtifactsFromManifestsTarHash(manifestsTarHash, includePrecomputedReachabilityResults);
234522
- const properPythonProjects = [];
234523
- const pipArtifactToRepresentativeManifest = {};
234524
- for (const artifact of artifacts) {
234525
- if (artifact.type === "pypi" && artifact.manifestFiles) {
234526
- pipArtifactToRepresentativeManifest[simplePurl(artifact.type, artifact.namespace ?? "", artifact.name ?? "", artifact.version ?? "")] = artifact;
234527
- }
234528
- }
234529
- const allFiles = await getFilesRelative(rootWorkingDirectory, venvExcludes);
234530
- for (const file of allFiles) {
234531
- const base = basename9(file);
234532
- const workspaceDir = dirname26(file) || ".";
234533
- if (base === "pyproject.toml" || base === "setup.py" && await isSetupPySetuptools(join27(rootWorkingDirectory, file))) {
234534
- if (!properPythonProjects.includes(workspaceDir)) {
234535
- properPythonProjects.push(workspaceDir);
234536
- }
234537
- }
234538
- }
234539
- const dotnetManifestFiles = await glob([
234540
- "*.sln",
234541
- "*.*proj",
234542
- "*.targets",
234543
- "*.props",
234544
- "*.projitems",
234545
- "*.nuspec",
234546
- "packages.config",
234547
- "packages.*.config",
234548
- "packages.lock.json"
234549
- ], { cwd: rootWorkingDirectory, nodir: true, ignore: ["**/obj/**", "**/bin/**"], matchBase: true });
234550
- const artifactMap = new Map(artifacts.map((a4) => [a4.id, a4]));
234551
- const ecosystemToWorkspaceToAnalysisData = {};
234552
- const ecosystemWorkspaceVulnIds = /* @__PURE__ */ new Set();
234553
- const ecosystemToWorkspaceToVulnerabilities = {};
234554
- const purlsFailedToFindWorkspace = /* @__PURE__ */ new Set();
234555
- for (const artifact of artifacts) {
234556
- let processToplevelAncestors2 = function(artifact2) {
234557
- const allAncestorIds = getAllToplevelAncestors(artifactMap, artifact2.id);
234558
- allAncestorIds.forEach((ancestorId) => artifactMap.get(ancestorId)?.manifestFiles?.forEach((ref) => manifestFiles.push(ref.file)));
234559
- };
234560
- var processToplevelAncestors = processToplevelAncestors2;
234561
- const ecosystem = getAdvisoryEcosystemFromPurlType(artifact.type);
234562
- if (!ecosystem)
234563
- continue;
234564
- const manifestFiles = [];
234565
- switch (ecosystem) {
234566
- case "NUGET": {
234567
- manifestFiles.push(...dotnetManifestFiles);
234568
- break;
234569
- }
234570
- case "PIP": {
234571
- const sPurl = simplePurl(artifact.type, artifact.namespace ?? null, artifact.name ?? null, artifact.version ?? null);
234572
- if (pipArtifactToRepresentativeManifest[sPurl]) {
234573
- manifestFiles.push(...(pipArtifactToRepresentativeManifest[sPurl].manifestFiles ?? []).map((ref) => ref.file));
234574
- }
234575
- processToplevelAncestors2(artifact);
234576
- break;
234577
- }
234578
- default: {
234579
- artifact.manifestFiles?.forEach((ref) => manifestFiles.push(ref.file));
234580
- processToplevelAncestors2(artifact);
234581
- break;
234582
- }
234583
- }
234584
- const workspaceToManifestFiles = {};
234585
- manifestFiles.forEach((manifestFile) => {
234586
- const workspace = inferWorkspaceFromManifestPath(ecosystem, manifestFile, properPythonProjects);
234587
- if (!workspace)
234588
- return;
234589
- (workspaceToManifestFiles[workspace] ??= []).push(manifestFile);
234590
- });
234591
- if (Object.keys(workspaceToManifestFiles).length === 0) {
234592
- manifestFiles.forEach((manifestFile) => {
234593
- const workspace = inferProjectFromManifestPath(ecosystem, manifestFile);
234594
- if (!workspace)
234595
- return;
234596
- (workspaceToManifestFiles[workspace] ??= []).push(manifestFile);
234597
- });
234598
- }
234599
- if (Object.keys(workspaceToManifestFiles).length === 0 && artifact.vulnerabilities && artifact.vulnerabilities.length > 0) {
234600
- purlsFailedToFindWorkspace.add(simplePurl(artifact.type, artifact.namespace ?? null, artifact.name ?? null, artifact.version ?? null));
234601
- }
234602
- for (const [workspace, manifestFiles2] of Object.entries(workspaceToManifestFiles)) {
234603
- const workspaceData = (ecosystemToWorkspaceToAnalysisData[ecosystem] ??= {})[workspace] ??= {
234604
- type: "socket",
234605
- data: {
234606
- type: ecosystem,
234607
- manifestFiles: manifestFiles2,
234608
- artifacts: []
234609
- }
234610
- };
234611
- workspaceData.type;
234612
- workspaceData.data.artifacts.push(artifact);
234613
- }
234614
- if (artifact.vulnerabilities && artifact.vulnerabilities.length > 0) {
234615
- for (const workspace of Object.keys(workspaceToManifestFiles)) {
234616
- for (const vuln of artifact.vulnerabilities) {
234617
- const vulnerability = {
234618
- url: vuln.ghsaId,
234619
- severity: vuln.severity,
234620
- purlType: artifact.type,
234621
- range: vuln.range,
234622
- name: artifact.name ?? "",
234623
- dependency: artifact.name ?? "",
234624
- vulnChainDetails: computeVulnChainDetails(artifacts, artifact.id),
234625
- vulnerabilityAccessPaths: vuln.reachabilityData?.undeterminableReachability ? vuln.reachabilityData.publicComment ?? "" : vuln.reachabilityData?.pattern ?? null,
234626
- ecosystem,
234627
- artifactId: artifact.id,
234628
- precomputedReachabilityResult: vuln.reachabilityData?.precomputedReachabilityResult ?? null
234629
- };
234630
- const vulnId = `${ecosystem}-${workspace}-${artifact.namespace}-${artifact.name}-${artifact.version}-${vulnerability.url}`;
234631
- if (!ecosystemWorkspaceVulnIds.has(vulnId)) {
234632
- ecosystemWorkspaceVulnIds.add(vulnId);
234633
- ((ecosystemToWorkspaceToVulnerabilities[ecosystem] ??= {})[workspace] ??= []).push(vulnerability);
234634
- }
234635
- }
234636
- }
234637
- }
234638
- }
234639
- if (purlsFailedToFindWorkspace.size > 0) {
234640
- logger.warn(`Failed to find workspace for the following purls with vulnerabilities: ${Array.from(purlsFailedToFindWorkspace).join(", ")}.
234641
- ${mode === "reachability" ? "This means that we will not do a full reachability analysis for these vulnerabilities, but fallback to the results from the pre-computed reachability analysis." : ""}`);
234642
- }
234643
- return {
234644
- artifacts,
234645
- ecosystemToWorkspaceToAnalysisData,
234646
- ecosystemToWorkspaceToVulnerabilities
234647
- };
234648
- } catch (error) {
234649
- logger.error("Failed to fetch artifacts from Socket backend", error);
234650
- throw error;
234651
- }
234652
- }
234653
- function computeVulnChainDetails(artifacts, vulnerableArtifactId) {
234654
- const artifactMap = new Map(artifacts.map((a4) => [a4.id, a4]));
234655
- const parentsMap = /* @__PURE__ */ new Map();
234656
- for (const artifact of artifacts) {
234657
- if (artifact.dependencies) {
234658
- for (const depId of artifact.dependencies) {
234659
- if (!parentsMap.has(depId)) {
234660
- parentsMap.set(depId, []);
234661
- }
234662
- parentsMap.get(depId).push(artifact.id);
234663
- }
234664
- }
234665
- }
234666
- const res = {
234667
- packageName: "root",
234668
- version: "0.0.0",
234669
- children: [],
234670
- transitiveDependencies: {}
234671
- };
234672
- function addNode(currentId, childId, visited) {
234673
- if (visited.has(currentId))
234674
- return;
234675
- const currentArtifact = artifactMap.get(currentId);
234676
- if (!currentArtifact)
234677
- return;
234678
- const parents4 = parentsMap.get(currentId);
234679
- const newCurrentNode = {
234680
- packageName: getNameFromNamespaceAndName(currentArtifact.type, currentArtifact.namespace, currentArtifact.name),
234681
- version: currentArtifact.version ?? void 0,
234682
- children: []
234683
- };
234684
- res.transitiveDependencies[currentId] = newCurrentNode;
234685
- if (childId && !newCurrentNode.children.includes(childId)) {
234686
- newCurrentNode.children.push(childId);
234687
- }
234688
- if (currentId === vulnerableArtifactId) {
234689
- newCurrentNode.vulnerable = true;
234690
- }
234691
- if (currentArtifact.direct && !res.children.includes(currentId)) {
234692
- res.children.push(currentId);
234693
- }
234694
- visited.add(currentId);
234695
- if (parents4) {
234696
- for (const parentId of parents4) {
234697
- addNode(parentId, currentId, visited);
234698
- }
234699
- }
234700
- }
234701
- addNode(vulnerableArtifactId, void 0, /* @__PURE__ */ new Set());
234702
- return res;
234703
- }
234704
-
234705
234412
  // dist/cli-compute-fixes-and-upgrade-purls.js
234706
234413
  async function computeFixesAndUpgradePurls(path9, options, logFile) {
234707
234414
  const autofixRunId = options.manifestsTarHash && await getSocketAPI().registerAutofixOrUpgradePurlRun(options.manifestsTarHash, options, "autofix");
234708
- const { artifacts, ghsaToVulnerableArtifactIds, socketFactArtifacts } = await computeInputForComputingFixes(path9, options);
234415
+ const { artifacts, ghsaToVulnerableArtifactIds, socketFactArtifacts } = await computeInputForComputingFixes(options);
234709
234416
  if (Object.keys(ghsaToVulnerableArtifactIds).length === 0) {
234710
234417
  logger.info("Found no vulnerabilities in the project");
234711
234418
  return { type: "no-vulnerabilities-found" };
@@ -234715,7 +234422,21 @@ async function computeFixesAndUpgradePurls(path9, options, logFile) {
234715
234422
  logger.info("Consider running the tool again, requesting a fix for one of the detected vulnerabilities");
234716
234423
  return { type: "no-ghsas-fix-requested", ghsas: Object.keys(ghsaToVulnerableArtifactIds) };
234717
234424
  }
234718
- const ghsaToVulnerableArtifactIdsToApply = options.applyFixesTo.includes("all") ? ghsaToVulnerableArtifactIds : Object.fromEntries(Object.entries(ghsaToVulnerableArtifactIds).filter(([ghsa]) => options.applyFixesTo.includes(ghsa)));
234425
+ const ghsaToVulnerableArtifactIdsToApplyBeforePurlTypeFilter = options.applyFixesTo.includes("all") ? ghsaToVulnerableArtifactIds : Object.fromEntries(Object.entries(ghsaToVulnerableArtifactIds).filter(([ghsa]) => options.applyFixesTo.includes(ghsa)));
234426
+ const ghsaToVulnerableArtifactIdsToApply = {};
234427
+ for (const [ghsa, artifactIds] of Object.entries(ghsaToVulnerableArtifactIdsToApplyBeforePurlTypeFilter)) {
234428
+ const filteredIds = artifactIds.filter((id) => {
234429
+ const artifact = socketFactArtifacts[id];
234430
+ if (!options.purlTypes || options.purlTypes.includes(artifact.type)) {
234431
+ return true;
234432
+ }
234433
+ logger.warn(`Skipping upgrade for ${purlToString(artifact)} (${ghsa}) - type '${artifact.type}' not in specified types: ${options.purlTypes.join(", ")}`);
234434
+ return false;
234435
+ });
234436
+ if (filteredIds.length > 0) {
234437
+ ghsaToVulnerableArtifactIdsToApply[ghsa] = filteredIds;
234438
+ }
234439
+ }
234719
234440
  if (Object.keys(ghsaToVulnerableArtifactIdsToApply).length === 0) {
234720
234441
  logger.info("There is no overlap between the requested fixes and the detected vulnerabilities");
234721
234442
  logger.info("Consider running the tool again, requesting a fix for one of the detected vulnerabilities");
@@ -234820,10 +234541,10 @@ async function computeFixesAndUpgradePurls(path9, options, logFile) {
234820
234541
  throw error;
234821
234542
  }
234822
234543
  }
234823
- async function computeInputForComputingFixes(path9, options) {
234544
+ async function computeInputForComputingFixes(options) {
234824
234545
  if (!options.manifestsTarHash)
234825
234546
  throw new Error("Manifests tar hash is required for computing fixes");
234826
- const { artifacts } = await fetchArtifactsFromSocket(path9, options.manifestsTarHash, "autofix");
234547
+ const { artifacts } = await fetchArtifactsFromManifestsTarHash(options.manifestsTarHash);
234827
234548
  const ghsaToVulnerableArtifactIds = {};
234828
234549
  for (const [index2, artifact] of artifacts.entries()) {
234829
234550
  if (!artifact.vulnerabilities)
@@ -234866,7 +234587,6 @@ async function computeDirectDependencyUpgrades(artifacts, fixesFound) {
234866
234587
  } else {
234867
234588
  directUpdates[purl] = { transitiveFixes: [indirectFix] };
234868
234589
  }
234869
- directUpdates[purl] = { transitiveFixes: [indirectFix] };
234870
234590
  }
234871
234591
  }
234872
234592
  packageFixes[ghsa] = {
@@ -235573,7 +235293,7 @@ var DEFAULT_REPORT_FILENAME_BASE = "coana-report";
235573
235293
  // dist/internal/exclude-dirs-from-configuration-files.js
235574
235294
  import { existsSync as existsSync22 } from "fs";
235575
235295
  import { readFile as readFile32 } from "fs/promises";
235576
- import { basename as basename10, resolve as resolve42 } from "path";
235296
+ import { basename as basename9, resolve as resolve42 } from "path";
235577
235297
  var import_yaml2 = __toESM(require_dist12(), 1);
235578
235298
  async function inferExcludeDirsFromConfigurationFiles(rootWorkingDir) {
235579
235299
  const socketYmlConfigFile = resolve42(rootWorkingDir, "socket.yml");
@@ -235593,7 +235313,7 @@ async function inferExcludeDirsFromSocketConfig(socketConfigFile) {
235593
235313
  return void 0;
235594
235314
  if (ignorePaths.some((ignorePath) => ignorePath.includes("!")))
235595
235315
  return void 0;
235596
- logger.info(`Inferring paths to exclude based on Socket config file: ${basename10(socketConfigFile)}`);
235316
+ logger.info(`Inferring paths to exclude based on Socket config file: ${basename9(socketConfigFile)}`);
235597
235317
  return config3.projectIgnorePaths;
235598
235318
  } catch (e) {
235599
235319
  return void 0;
@@ -235701,7 +235421,7 @@ async function scanForVulnerabilitiesSocketMode(dependencyTree) {
235701
235421
  range: vulnerability.range,
235702
235422
  name: dependencyTreeNode.packageName,
235703
235423
  dependency: dependencyTreeNode.packageName,
235704
- vulnChainDetails: computeVulnChainDetails2(dependencyTree, dependencyIdentifier, parentsMap),
235424
+ vulnChainDetails: computeVulnChainDetails(dependencyTree, dependencyIdentifier, parentsMap),
235705
235425
  vulnerabilityAccessPaths: vulnerability.reachabilityData?.pattern ?? null,
235706
235426
  ecosystem: dependencyTree.ecosystem
235707
235427
  });
@@ -235713,7 +235433,7 @@ async function scanForVulnerabilitiesSocketMode(dependencyTree) {
235713
235433
  }
235714
235434
  return vulnerabilities;
235715
235435
  }
235716
- function computeVulnChainDetails2(dependencyTree, dependencyIdentifier, parentsMap) {
235436
+ function computeVulnChainDetails(dependencyTree, dependencyIdentifier, parentsMap) {
235717
235437
  const res = {
235718
235438
  packageName: "root",
235719
235439
  version: "0.0.0",
@@ -235750,6 +235470,304 @@ function transformToVulnChainNode(dependencyTree) {
235750
235470
  };
235751
235471
  }
235752
235472
 
235473
+ // dist/internal/socket-mode-helpers-socket-dependency-trees.js
235474
+ import { basename as basename10, dirname as dirname26, join as join27, sep as sep6 } from "path";
235475
+ var REQUIREMENTS_FILES_SEARCH_DEPTH2 = 3;
235476
+ var venvExcludes = [
235477
+ "venv",
235478
+ ".venv",
235479
+ "env",
235480
+ ".env",
235481
+ "virtualenv",
235482
+ ".virtualenv",
235483
+ "venvs",
235484
+ ".venvs",
235485
+ "envs",
235486
+ ".envs",
235487
+ "__pycache__",
235488
+ ".tox",
235489
+ ".nox",
235490
+ ".pytest_cache",
235491
+ "site-packages",
235492
+ "dist-packages",
235493
+ "conda-meta",
235494
+ "conda-bld",
235495
+ ".mypy_cache",
235496
+ ".ruff_cache",
235497
+ ".hypothesis"
235498
+ ];
235499
+ function inferWorkspaceFromManifestPath(ecosystem, manifestPath, properPythonProjects) {
235500
+ switch (ecosystem) {
235501
+ case "NPM": {
235502
+ const base = basename10(manifestPath);
235503
+ const dir = dirname26(manifestPath);
235504
+ return base === "package.json" ? dir || "." : void 0;
235505
+ }
235506
+ case "MAVEN": {
235507
+ return ".";
235508
+ }
235509
+ case "PIP": {
235510
+ if (venvExcludes.some((exclude) => manifestPath.startsWith(`${exclude}/`) || manifestPath.includes(`/${exclude}/`))) {
235511
+ return void 0;
235512
+ }
235513
+ const base = basename10(manifestPath);
235514
+ const dir = dirname26(manifestPath);
235515
+ const workspaceDir = dir === "" ? "." : dir;
235516
+ if (properPythonProjects.includes(workspaceDir)) {
235517
+ return workspaceDir;
235518
+ }
235519
+ if (base === "poetry.lock" || base === "Pipfile.lock" || base === "uv.lock") {
235520
+ return workspaceDir;
235521
+ }
235522
+ if (base.endsWith(".txt")) {
235523
+ const properProjectDirs = properPythonProjects.filter((properProjectDir) => (properProjectDir === "." || workspaceDir === "." || workspaceDir.startsWith(properProjectDir)) && workspaceDir.replace(properProjectDir, "").split(sep6).length <= REQUIREMENTS_FILES_SEARCH_DEPTH2);
235524
+ const longestProperProjectDir = l(properProjectDirs, [(d4) => d4.length, "desc"]);
235525
+ if (longestProperProjectDir) {
235526
+ return longestProperProjectDir;
235527
+ }
235528
+ return workspaceDir;
235529
+ }
235530
+ logger.warn(`No workspace found for manifest file ${manifestPath}`);
235531
+ return void 0;
235532
+ }
235533
+ case "NUGET": {
235534
+ return ".";
235535
+ }
235536
+ case "RUST": {
235537
+ return dirname26(manifestPath) || ".";
235538
+ }
235539
+ case "GO": {
235540
+ const base = basename10(manifestPath);
235541
+ const dir = dirname26(manifestPath);
235542
+ return base === "go.mod" ? dir || "." : void 0;
235543
+ }
235544
+ case "RUBYGEMS": {
235545
+ return dirname26(manifestPath) || ".";
235546
+ }
235547
+ default: {
235548
+ return ".";
235549
+ }
235550
+ }
235551
+ }
235552
+ function inferProjectFromManifestPath(ecosystem, manifestPath) {
235553
+ switch (ecosystem) {
235554
+ case "NPM": {
235555
+ const filename = basename10(manifestPath);
235556
+ if (["package-lock.json", "pnpm-lock.yaml", "pnpm-lock.yml", "yarn.lock"].includes(filename)) {
235557
+ return dirname26(manifestPath) || ".";
235558
+ }
235559
+ return void 0;
235560
+ }
235561
+ }
235562
+ }
235563
+ function getAllToplevelAncestors(artifactMap, artifactId) {
235564
+ const visited = /* @__PURE__ */ new Set();
235565
+ const toplevelAncestors = /* @__PURE__ */ new Set();
235566
+ function findAncestors(currentId) {
235567
+ if (visited.has(currentId)) {
235568
+ return;
235569
+ }
235570
+ visited.add(currentId);
235571
+ const artifact = artifactMap.get(currentId);
235572
+ if (!artifact) {
235573
+ return;
235574
+ }
235575
+ if (artifact.toplevelAncestors && artifact.toplevelAncestors.length > 0) {
235576
+ for (const ancestorId of artifact.toplevelAncestors) {
235577
+ toplevelAncestors.add(ancestorId);
235578
+ findAncestors(ancestorId);
235579
+ }
235580
+ }
235581
+ }
235582
+ findAncestors(artifactId);
235583
+ return Array.from(toplevelAncestors);
235584
+ }
235585
+ async function fetchArtifactsFromSocket(rootWorkingDirectory, manifestsTarHash, mode, includePrecomputedReachabilityResults) {
235586
+ try {
235587
+ const { artifacts } = await fetchArtifactsFromManifestsTarHash(manifestsTarHash, includePrecomputedReachabilityResults);
235588
+ const properPythonProjects = [];
235589
+ const pipArtifactToRepresentativeManifest = {};
235590
+ for (const artifact of artifacts) {
235591
+ if (artifact.type === "pypi" && artifact.manifestFiles) {
235592
+ pipArtifactToRepresentativeManifest[simplePurl(artifact.type, artifact.namespace ?? "", artifact.name ?? "", artifact.version ?? "")] = artifact;
235593
+ }
235594
+ }
235595
+ const allFiles = await getFilesRelative(rootWorkingDirectory, venvExcludes);
235596
+ for (const file of allFiles) {
235597
+ const base = basename10(file);
235598
+ const workspaceDir = dirname26(file) || ".";
235599
+ if (base === "pyproject.toml" || base === "setup.py" && await isSetupPySetuptools(join27(rootWorkingDirectory, file))) {
235600
+ if (!properPythonProjects.includes(workspaceDir)) {
235601
+ properPythonProjects.push(workspaceDir);
235602
+ }
235603
+ }
235604
+ }
235605
+ const dotnetManifestFiles = await glob([
235606
+ "*.sln",
235607
+ "*.*proj",
235608
+ "*.targets",
235609
+ "*.props",
235610
+ "*.projitems",
235611
+ "*.nuspec",
235612
+ "packages.config",
235613
+ "packages.*.config",
235614
+ "packages.lock.json"
235615
+ ], { cwd: rootWorkingDirectory, nodir: true, ignore: ["**/obj/**", "**/bin/**"], matchBase: true });
235616
+ const artifactMap = new Map(artifacts.map((a4) => [a4.id, a4]));
235617
+ const ecosystemToWorkspaceToAnalysisData = {};
235618
+ const ecosystemWorkspaceVulnIds = /* @__PURE__ */ new Set();
235619
+ const ecosystemToWorkspaceToVulnerabilities = {};
235620
+ const purlsFailedToFindWorkspace = /* @__PURE__ */ new Set();
235621
+ for (const artifact of artifacts) {
235622
+ let processToplevelAncestors2 = function(artifact2) {
235623
+ const allAncestorIds = getAllToplevelAncestors(artifactMap, artifact2.id);
235624
+ allAncestorIds.forEach((ancestorId) => artifactMap.get(ancestorId)?.manifestFiles?.forEach((ref) => manifestFiles.push(ref.file)));
235625
+ };
235626
+ var processToplevelAncestors = processToplevelAncestors2;
235627
+ const ecosystem = getAdvisoryEcosystemFromPurlType(artifact.type);
235628
+ if (!ecosystem)
235629
+ continue;
235630
+ const manifestFiles = [];
235631
+ switch (ecosystem) {
235632
+ case "NUGET": {
235633
+ manifestFiles.push(...dotnetManifestFiles);
235634
+ break;
235635
+ }
235636
+ case "PIP": {
235637
+ const sPurl = simplePurl(artifact.type, artifact.namespace ?? null, artifact.name ?? null, artifact.version ?? null);
235638
+ if (pipArtifactToRepresentativeManifest[sPurl]) {
235639
+ manifestFiles.push(...(pipArtifactToRepresentativeManifest[sPurl].manifestFiles ?? []).map((ref) => ref.file));
235640
+ }
235641
+ processToplevelAncestors2(artifact);
235642
+ break;
235643
+ }
235644
+ default: {
235645
+ artifact.manifestFiles?.forEach((ref) => manifestFiles.push(ref.file));
235646
+ processToplevelAncestors2(artifact);
235647
+ break;
235648
+ }
235649
+ }
235650
+ const workspaceToManifestFiles = {};
235651
+ manifestFiles.forEach((manifestFile) => {
235652
+ const workspace = inferWorkspaceFromManifestPath(ecosystem, manifestFile, properPythonProjects);
235653
+ if (!workspace)
235654
+ return;
235655
+ (workspaceToManifestFiles[workspace] ??= []).push(manifestFile);
235656
+ });
235657
+ if (Object.keys(workspaceToManifestFiles).length === 0) {
235658
+ manifestFiles.forEach((manifestFile) => {
235659
+ const workspace = inferProjectFromManifestPath(ecosystem, manifestFile);
235660
+ if (!workspace)
235661
+ return;
235662
+ (workspaceToManifestFiles[workspace] ??= []).push(manifestFile);
235663
+ });
235664
+ }
235665
+ if (Object.keys(workspaceToManifestFiles).length === 0 && artifact.vulnerabilities && artifact.vulnerabilities.length > 0) {
235666
+ purlsFailedToFindWorkspace.add(simplePurl(artifact.type, artifact.namespace ?? null, artifact.name ?? null, artifact.version ?? null));
235667
+ }
235668
+ for (const [workspace, manifestFiles2] of Object.entries(workspaceToManifestFiles)) {
235669
+ const workspaceData = (ecosystemToWorkspaceToAnalysisData[ecosystem] ??= {})[workspace] ??= {
235670
+ type: "socket",
235671
+ data: {
235672
+ type: ecosystem,
235673
+ manifestFiles: manifestFiles2,
235674
+ artifacts: []
235675
+ }
235676
+ };
235677
+ workspaceData.type;
235678
+ workspaceData.data.artifacts.push(artifact);
235679
+ }
235680
+ if (artifact.vulnerabilities && artifact.vulnerabilities.length > 0) {
235681
+ for (const workspace of Object.keys(workspaceToManifestFiles)) {
235682
+ for (const vuln of artifact.vulnerabilities) {
235683
+ const vulnerability = {
235684
+ url: vuln.ghsaId,
235685
+ severity: vuln.severity,
235686
+ purlType: artifact.type,
235687
+ range: vuln.range,
235688
+ name: artifact.name ?? "",
235689
+ dependency: artifact.name ?? "",
235690
+ vulnChainDetails: computeVulnChainDetails2(artifacts, artifact.id),
235691
+ vulnerabilityAccessPaths: vuln.reachabilityData?.undeterminableReachability ? vuln.reachabilityData.publicComment ?? "" : vuln.reachabilityData?.pattern ?? null,
235692
+ ecosystem,
235693
+ artifactId: artifact.id,
235694
+ precomputedReachabilityResult: vuln.reachabilityData?.precomputedReachabilityResult ?? null
235695
+ };
235696
+ const vulnId = `${ecosystem}-${workspace}-${artifact.namespace}-${artifact.name}-${artifact.version}-${vulnerability.url}`;
235697
+ if (!ecosystemWorkspaceVulnIds.has(vulnId)) {
235698
+ ecosystemWorkspaceVulnIds.add(vulnId);
235699
+ ((ecosystemToWorkspaceToVulnerabilities[ecosystem] ??= {})[workspace] ??= []).push(vulnerability);
235700
+ }
235701
+ }
235702
+ }
235703
+ }
235704
+ }
235705
+ if (purlsFailedToFindWorkspace.size > 0) {
235706
+ logger.warn(`Failed to find workspace for the following purls with vulnerabilities: ${Array.from(purlsFailedToFindWorkspace).join(", ")}.
235707
+ ${mode === "reachability" ? "This means that we will not do a full reachability analysis for these vulnerabilities, but fallback to the results from the pre-computed reachability analysis." : ""}`);
235708
+ }
235709
+ return {
235710
+ artifacts,
235711
+ ecosystemToWorkspaceToAnalysisData,
235712
+ ecosystemToWorkspaceToVulnerabilities
235713
+ };
235714
+ } catch (error) {
235715
+ logger.error("Failed to fetch artifacts from Socket backend", error);
235716
+ throw error;
235717
+ }
235718
+ }
235719
+ function computeVulnChainDetails2(artifacts, vulnerableArtifactId) {
235720
+ const artifactMap = new Map(artifacts.map((a4) => [a4.id, a4]));
235721
+ const parentsMap = /* @__PURE__ */ new Map();
235722
+ for (const artifact of artifacts) {
235723
+ if (artifact.dependencies) {
235724
+ for (const depId of artifact.dependencies) {
235725
+ if (!parentsMap.has(depId)) {
235726
+ parentsMap.set(depId, []);
235727
+ }
235728
+ parentsMap.get(depId).push(artifact.id);
235729
+ }
235730
+ }
235731
+ }
235732
+ const res = {
235733
+ packageName: "root",
235734
+ version: "0.0.0",
235735
+ children: [],
235736
+ transitiveDependencies: {}
235737
+ };
235738
+ function addNode(currentId, childId, visited) {
235739
+ if (visited.has(currentId))
235740
+ return;
235741
+ const currentArtifact = artifactMap.get(currentId);
235742
+ if (!currentArtifact)
235743
+ return;
235744
+ const parents4 = parentsMap.get(currentId);
235745
+ const newCurrentNode = {
235746
+ packageName: getNameFromNamespaceAndName(currentArtifact.type, currentArtifact.namespace, currentArtifact.name),
235747
+ version: currentArtifact.version ?? void 0,
235748
+ children: []
235749
+ };
235750
+ res.transitiveDependencies[currentId] = newCurrentNode;
235751
+ if (childId && !newCurrentNode.children.includes(childId)) {
235752
+ newCurrentNode.children.push(childId);
235753
+ }
235754
+ if (currentId === vulnerableArtifactId) {
235755
+ newCurrentNode.vulnerable = true;
235756
+ }
235757
+ if (currentArtifact.direct && !res.children.includes(currentId)) {
235758
+ res.children.push(currentId);
235759
+ }
235760
+ visited.add(currentId);
235761
+ if (parents4) {
235762
+ for (const parentId of parents4) {
235763
+ addNode(parentId, currentId, visited);
235764
+ }
235765
+ }
235766
+ }
235767
+ addNode(vulnerableArtifactId, void 0, /* @__PURE__ */ new Set());
235768
+ return res;
235769
+ }
235770
+
235753
235771
  // dist/internal/socket-report-coana-dependency-tree.js
235754
235772
  var MAX_STACKS_TO_SEND = 10;
235755
235773
  function toSocketFacts(report, dependencyTrees, subPjToWsPathToDirectDependencies) {
@@ -250816,7 +250834,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
250816
250834
  }
250817
250835
 
250818
250836
  // dist/version.js
250819
- var version3 = "14.12.112";
250837
+ var version3 = "14.12.114";
250820
250838
 
250821
250839
  // dist/cli-core.js
250822
250840
  var { mapValues, omit, partition, pick } = import_lodash15.default;
@@ -251744,7 +251762,7 @@ applyFixes.name("apply-fixes").argument("<path>", "File system path to the folde
251744
251762
  await applyFix(path9, fixIds, options);
251745
251763
  }).configureHelp({ sortOptions: true });
251746
251764
  var computeFixesAndUpgradePurlsCmd = new Command();
251747
- 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. Use "all" to compute fixes for all vulnerabilities.', []).option("--dry-run", "Show what changes would be made without actually making them", false).option("-i, --include <patterns...>", "Glob patterns to include workspaces").option("-e, --exclude <patterns...>", "Glob patterns to exclude workspaces").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("--silent-spinner", "Silence spinner", "CI" in process.env || !process.stdin.isTTY).option("--range-style <style>", 'Range style to use for the output. Currently only "pin" is supported and it only works for npm.').option("--disable-major-updates", "Do not suggest major updates. If only major update are available, the fix will not be applied.", false).option("-o, --output-file <file>", "Writes output to a JSON file").option("--minimum-release-age <minimumReleaseAge>", "Do not allow upgrades to package versions that are newer than minimumReleaseAge. Format is 2m, 5h, 3d or 1w").option("--show-affected-direct-dependencies", "Show the affected direct dependencies for each vulnerability and what upgrades could fix them - does not apply the upgrades.", false).addOption(new Option("--run-without-docker", "Run package managers without using docker").default(process.env.RUN_WITHOUT_DOCKER === "true").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(version3).action(async (path9, options) => {
251765
+ 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. Use "all" to compute fixes for all vulnerabilities.', []).option("--dry-run", "Show what changes would be made without actually making them", false).option("-i, --include <patterns...>", "Glob patterns to include workspaces").option("-e, --exclude <patterns...>", "Glob patterns to exclude workspaces").option("-d, --debug", "Enable debug logging", false).option("-s, --silent", "Silence all debug/warning output", false).option("--silent-spinner", "Silence spinner", "CI" in process.env || !process.stdin.isTTY).option("--range-style <style>", 'Range style to use for the output. Currently only "pin" is supported and it only works for npm.').option("--disable-major-updates", "Do not suggest major updates. If only major update are available, the fix will not be applied.", false).option("-o, --output-file <file>", "Writes output to a JSON file").option("--minimum-release-age <minimumReleaseAge>", "Do not allow upgrades to package versions that are newer than minimumReleaseAge. Format is 2m, 5h, 3d or 1w").option("--show-affected-direct-dependencies", "Show the affected direct dependencies for each vulnerability and what upgrades could fix them - does not apply the upgrades.", false).option("--purl-types <purlTypes...>", "List of PURL types to filter artifacts by (space-separated). Only vulnerabilities from artifacts matching these types will be included.").addOption(new Option("--run-without-docker", "Run package managers without using docker").default(process.env.RUN_WITHOUT_DOCKER === "true").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(version3).action(async (path9, options) => {
251748
251766
  process.env.DOCKER_IMAGE_TAG ??= version3;
251749
251767
  if (options.outputFile && !options.outputFile.endsWith(".json")) {
251750
251768
  throw new Error("Output file must have a .json extension");
@@ -251755,6 +251773,7 @@ computeFixesAndUpgradePurlsCmd.name("compute-fixes-and-upgrade-purls").argument(
251755
251773
  if (options.rangeStyle && options.rangeStyle !== "pin") {
251756
251774
  throw new Error('Range style must be "pin"');
251757
251775
  }
251776
+ options.purlTypes = options.purlTypes?.map((t4) => t4.toLowerCase());
251758
251777
  const tmpDir = await mkdtemp2(join30(tmpdir3(), "compute-fixes-and-upgrade-purls-"));
251759
251778
  const logFile = join30(tmpDir, "compute-fixes-and-upgrade-purls.log");
251760
251779
  logger.initWinstonLogger(options.debug, logFile);
@@ -251806,11 +251825,13 @@ compareReportsCommand.name("compare-reports").argument("<baselineReportPath>", "
251806
251825
  await compareReports(baselineReport, newReport, options);
251807
251826
  });
251808
251827
  var findVulnerabilities = new Command();
251809
- findVulnerabilities.name("find-vulnerabilities").requiredOption("--manifests-tar-hash <hash>", "Hash of the tarball containing all manifest files already uploaded to Socket.").action(async (options) => {
251828
+ findVulnerabilities.name("find-vulnerabilities").requiredOption("--manifests-tar-hash <hash>", "Hash of the tarball containing all manifest files already uploaded to Socket.").option("--purl-types <purlTypes...>", "List of PURL types to filter artifacts by (space-separated). Only vulnerabilities from artifacts matching these types will be included.").action(async (options) => {
251829
+ const purlTypes = options.purlTypes?.map((t4) => t4.toLowerCase());
251810
251830
  const { artifacts } = await fetchArtifactsFromManifestsTarHash(options.manifestsTarHash);
251811
- console.log(JSON.stringify(i(artifacts.flatMap((a4) => a4.vulnerabilities?.map((v) => v.ghsaId) ?? []))));
251831
+ const filteredArtifacts = purlTypes ? artifacts.filter((a4) => purlTypes.includes(a4.type)) : artifacts;
251832
+ console.log(JSON.stringify(i(filteredArtifacts.flatMap((a4) => a4.vulnerabilities?.map((v) => v.ghsaId) ?? []))));
251812
251833
  });
251813
- program2.name("coana-cli").addCommand(run2, { isDefault: true }).addCommand(findVulnerabilities).addCommand(applyFixes).addCommand(compareReportsCommand).addCommand(computeFixesAndUpgradePurlsCmd, { hidden: true }).configureHelp({ sortSubcommands: true }).version(version3);
251834
+ program2.name("coana-cli").addCommand(run2, { isDefault: true }).addCommand(findVulnerabilities, { hidden: true }).addCommand(applyFixes).addCommand(compareReportsCommand).addCommand(computeFixesAndUpgradePurlsCmd, { hidden: true }).configureHelp({ sortSubcommands: true }).version(version3);
251814
251835
  program2.parseAsync();
251815
251836
  var defaultCliOptions = {
251816
251837
  debug: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.12.112",
3
+ "version": "14.12.114",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {