socket 1.0.0 → 1.0.2

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 (66) hide show
  1. package/dist/cli.js +618 -887
  2. package/dist/cli.js.map +1 -1
  3. package/dist/constants.js +4 -4
  4. package/dist/constants.js.map +1 -1
  5. package/dist/shadow-npm-inject.js +1 -61
  6. package/dist/shadow-npm-inject.js.map +1 -1
  7. package/dist/types/cli.d.mts +1 -0
  8. package/dist/types/commands/fix/agent-fix.d.mts +36 -0
  9. package/dist/types/commands/fix/agent-fix.d.mts.map +1 -0
  10. package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
  11. package/dist/types/commands/fix/get-actual-tree.d.mts +3 -0
  12. package/dist/types/commands/fix/get-actual-tree.d.mts.map +1 -0
  13. package/dist/types/commands/fix/handle-fix.d.mts +2 -1
  14. package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
  15. package/dist/types/commands/fix/npm-fix.d.mts +2 -10
  16. package/dist/types/commands/fix/npm-fix.d.mts.map +1 -1
  17. package/dist/types/commands/fix/pnpm-fix.d.mts +2 -10
  18. package/dist/types/commands/fix/pnpm-fix.d.mts.map +1 -1
  19. package/dist/types/commands/manifest/convert_gradle_to_maven.d.mts.map +1 -1
  20. package/dist/types/commands/optimize/add-overrides.d.mts.map +1 -1
  21. package/dist/types/commands/optimize/get-overrides-by-agent.d.mts +36 -3
  22. package/dist/types/commands/optimize/get-overrides-by-agent.d.mts.map +1 -1
  23. package/dist/types/commands/repository/output-list-repos.d.mts.map +1 -1
  24. package/dist/types/commands/scan/cmd-scan-create.d.mts.map +1 -1
  25. package/dist/types/commands/scan/cmd-scan-github.d.mts.map +1 -1
  26. package/dist/types/commands/scan/handle-create-github-scan.d.mts.map +1 -1
  27. package/dist/types/commands/scan/output-scan-github.d.mts +3 -0
  28. package/dist/types/commands/scan/output-scan-github.d.mts.map +1 -0
  29. package/dist/types/commands/scan/scan-reachability.d.mts.map +1 -1
  30. package/dist/types/commands/scan/suggest-org-slug.d.mts.map +1 -1
  31. package/dist/types/commands/scan/suggest-to-persist-orgslug.d.mts +2 -0
  32. package/dist/types/commands/scan/suggest-to-persist-orgslug.d.mts.map +1 -0
  33. package/dist/types/utils/cmd.d.mts +1 -0
  34. package/dist/types/utils/cmd.d.mts.map +1 -1
  35. package/dist/types/utils/coana.d.mts +4 -0
  36. package/dist/types/utils/coana.d.mts.map +1 -0
  37. package/dist/types/utils/config.d.mts +2 -1
  38. package/dist/types/utils/config.d.mts.map +1 -1
  39. package/dist/types/utils/determine-org-slug.d.mts.map +1 -1
  40. package/dist/types/utils/lockfile.d.mts +2 -0
  41. package/dist/types/utils/lockfile.d.mts.map +1 -0
  42. package/dist/types/utils/meow-with-subcommands.d.mts +1 -1
  43. package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
  44. package/dist/types/utils/package-environment.d.mts +11 -11
  45. package/dist/types/utils/package-environment.d.mts.map +1 -1
  46. package/dist/types/utils/pnpm.d.mts +1 -1
  47. package/dist/types/utils/pnpm.d.mts.map +1 -1
  48. package/dist/types/utils/semver.d.mts.map +1 -1
  49. package/dist/utils.js +160 -30
  50. package/dist/utils.js.map +1 -1
  51. package/dist/vendor.js +8021 -7993
  52. package/external/@coana-tech/cli/cli.mjs +14035 -3820
  53. package/external/@socketsecurity/registry/external/@npmcli/package-json/index.js +7 -7
  54. package/external/@socketsecurity/registry/external/@socketregistry/packageurl-js.js +12 -8
  55. package/external/@socketsecurity/registry/external/browserslist.js +374 -347
  56. package/external/@socketsecurity/registry/external/cacache.js +6 -6
  57. package/external/@socketsecurity/registry/external/libnpmpack.js +47 -45
  58. package/external/@socketsecurity/registry/external/make-fetch-happen.js +37 -36
  59. package/external/@socketsecurity/registry/external/pacote.js +45 -44
  60. package/external/@socketsecurity/registry/lib/spawn.js +11 -2
  61. package/external/@socketsecurity/registry/manifest.json +2 -2
  62. package/external/blessed-contrib/lib/widget/charts/bar.js +6 -3
  63. package/external/blessed-contrib/lib/widget/charts/line.js +6 -3
  64. package/package.json +30 -30
  65. package/dist/types/commands/fix/run-fix.d.mts +0 -12
  66. package/dist/types/commands/fix/run-fix.d.mts.map +0 -1
package/dist/cli.js CHANGED
@@ -18,14 +18,14 @@ var registry = require('../external/@socketsecurity/registry');
18
18
  var npm = require('../external/@socketsecurity/registry/lib/npm');
19
19
  var packages = require('../external/@socketsecurity/registry/lib/packages');
20
20
  var sorts = require('../external/@socketsecurity/registry/lib/sorts');
21
+ var strings = require('../external/@socketsecurity/registry/lib/strings');
21
22
  var path$1 = require('../external/@socketsecurity/registry/lib/path');
22
23
  var regexps = require('../external/@socketsecurity/registry/lib/regexps');
23
- var fs$2 = require('../external/@socketsecurity/registry/lib/fs');
24
- var strings = require('../external/@socketsecurity/registry/lib/strings');
25
24
  var shadowNpmInject = require('./shadow-npm-inject.js');
25
+ var fs$2 = require('../external/@socketsecurity/registry/lib/fs');
26
+ var objects = require('../external/@socketsecurity/registry/lib/objects');
26
27
  var words = require('../external/@socketsecurity/registry/lib/words');
27
28
  var shadowNpmBin = require('./shadow-npm-bin.js');
28
- var objects = require('../external/@socketsecurity/registry/lib/objects');
29
29
  var require$$7 = require('../external/@socketsecurity/registry/lib/promises');
30
30
  var require$$1 = require('node:util');
31
31
  var os = require('node:os');
@@ -2966,22 +2966,6 @@ const cmdConfig = {
2966
2966
  }
2967
2967
  };
2968
2968
 
2969
- async function outputFixResult(result, outputKind) {
2970
- if (!result.ok) {
2971
- process.exitCode = result.code ?? 1;
2972
- }
2973
- if (outputKind === 'json') {
2974
- logger.logger.log(utils.serializeResultJson(result));
2975
- return;
2976
- }
2977
- if (!result.ok) {
2978
- logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
2979
- return;
2980
- }
2981
- logger.logger.log('');
2982
- logger.logger.success('Finished!');
2983
- }
2984
-
2985
2969
  function formatBranchName(name) {
2986
2970
  return name.replace(/[^-a-zA-Z0-9/._-]+/g, '+');
2987
2971
  }
@@ -3264,6 +3248,18 @@ function getActiveBranchesForPackage(ciEnv, partialPurl, openPrs) {
3264
3248
  return activeBranches;
3265
3249
  }
3266
3250
 
3251
+ async function getActualTree(cwd = process.cwd()) {
3252
+ // @npmcli/arborist DOES have partial support for pnpm structured node_modules
3253
+ // folders. However, support is iffy resulting in unhappy path errors and hangs.
3254
+ // So, to avoid the unhappy path, we restrict our usage to --dry-run loading
3255
+ // of the node_modules folder.
3256
+ const arb = new shadowNpmInject.Arborist({
3257
+ path: cwd,
3258
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
3259
+ });
3260
+ return await arb.loadActual();
3261
+ }
3262
+
3267
3263
  let _octokit;
3268
3264
  function getOctokit() {
3269
3265
  if (_octokit === undefined) {
@@ -3634,133 +3630,110 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
3634
3630
  }
3635
3631
  }
3636
3632
 
3637
- async function getEnvRepoInfo(cwd) {
3638
- // Lazily access constants.ENV.GITHUB_REPOSITORY.
3639
- const {
3640
- GITHUB_REPOSITORY
3641
- } = constants.ENV;
3642
- if (!GITHUB_REPOSITORY) {
3643
- debug.debugFn('miss: GITHUB_REPOSITORY env var');
3644
- }
3645
- const ownerSlashRepo = GITHUB_REPOSITORY;
3646
- const slashIndex = ownerSlashRepo.indexOf('/');
3647
- if (slashIndex !== -1) {
3648
- return {
3649
- owner: ownerSlashRepo.slice(0, slashIndex),
3650
- repo: ownerSlashRepo.slice(slashIndex + 1)
3651
- };
3652
- }
3653
- return await gitRepoInfo(cwd);
3633
+ const {
3634
+ BUN: BUN$4,
3635
+ NPM: NPM$8,
3636
+ OVERRIDES: OVERRIDES$2,
3637
+ PNPM: PNPM$8,
3638
+ RESOLUTIONS: RESOLUTIONS$1,
3639
+ VLT: VLT$5,
3640
+ YARN_BERRY: YARN_BERRY$4,
3641
+ YARN_CLASSIC: YARN_CLASSIC$4
3642
+ } = constants;
3643
+ function getOverridesDataBun(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3644
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3645
+ return {
3646
+ type: YARN_BERRY$4,
3647
+ overrides
3648
+ };
3654
3649
  }
3655
- async function getCiEnv() {
3656
- const gitEmail = constants.ENV.SOCKET_CLI_GIT_USER_EMAIL;
3657
- const gitUser = constants.ENV.SOCKET_CLI_GIT_USER_NAME;
3658
- const githubToken = constants.ENV.SOCKET_CLI_GITHUB_TOKEN;
3659
- const isCi = !!(constants.ENV.CI && gitEmail && gitUser && githubToken);
3660
- if (!isCi) {
3661
- return null;
3662
- }
3663
- const baseBranch = await getBaseGitBranch();
3664
- if (!baseBranch) {
3665
- return null;
3666
- }
3667
- const repoInfo = await getEnvRepoInfo();
3668
- if (!repoInfo) {
3669
- return null;
3670
- }
3650
+
3651
+ // npm overrides documentation:
3652
+ // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
3653
+ function getOverridesDataNpm(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3654
+ const overrides = pkgJson?.[OVERRIDES$2] ?? {};
3671
3655
  return {
3672
- gitEmail,
3673
- gitUser,
3674
- githubToken,
3675
- repoInfo,
3676
- baseBranch,
3677
- branchParser: createSocketBranchParser()
3656
+ type: NPM$8,
3657
+ overrides
3678
3658
  };
3679
3659
  }
3680
- async function getOpenPrsForEnvironment(env) {
3681
- return env ? await getOpenSocketPrs(env.repoInfo.owner, env.repoInfo.repo, {
3682
- author: env.gitUser
3683
- }) : [];
3660
+
3661
+ // pnpm overrides documentation:
3662
+ // https://pnpm.io/package_json#pnpmoverrides
3663
+ function getOverridesDataPnpm(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3664
+ const overrides = pkgJson?.[PNPM$8]?.[OVERRIDES$2] ?? {};
3665
+ return {
3666
+ type: PNPM$8,
3667
+ overrides
3668
+ };
3669
+ }
3670
+ function getOverridesDataVlt(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3671
+ const overrides = pkgJson?.[OVERRIDES$2] ?? {};
3672
+ return {
3673
+ type: VLT$5,
3674
+ overrides
3675
+ };
3684
3676
  }
3685
3677
 
3686
- const CMD_NAME$1 = 'socket fix';
3687
- function getAlertsMapOptions(options = {}) {
3678
+ // Yarn resolutions documentation:
3679
+ // https://yarnpkg.com/configuration/manifest#resolutions
3680
+ function getOverridesDataYarn(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3681
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3688
3682
  return {
3689
- __proto__: null,
3690
- consolidate: true,
3691
- nothrow: true,
3692
- ...options,
3693
- include: {
3694
- __proto__: null,
3695
- existing: true,
3696
- unfixable: false,
3697
- upgradable: false,
3698
- ...options?.include
3699
- }
3683
+ type: YARN_BERRY$4,
3684
+ overrides
3700
3685
  };
3701
3686
  }
3702
3687
 
3703
- async function install$1(arb, options) {
3704
- const {
3705
- cwd = process.cwd()
3706
- } = {
3707
- __proto__: null,
3708
- ...options
3688
+ // Yarn resolutions documentation:
3689
+ // https://classic.yarnpkg.com/en/docs/selective-version-resolutions
3690
+ function getOverridesDataYarnClassic(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3691
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3692
+ return {
3693
+ type: YARN_CLASSIC$4,
3694
+ overrides
3709
3695
  };
3710
- try {
3711
- const newArb = new shadowNpmInject.Arborist({
3712
- path: cwd
3713
- });
3714
- newArb.idealTree = await arb.buildIdealTree();
3715
- const actualTree = await newArb.reify();
3716
- arb.actualTree = actualTree;
3717
- return actualTree;
3718
- } catch {}
3719
- return null;
3720
3696
  }
3721
- async function npmFix(pkgEnvDetails, {
3722
- autoMerge,
3723
- cwd,
3724
- limit,
3725
- purls,
3726
- rangeStyle,
3727
- test,
3728
- testScript
3729
- }) {
3730
- // Lazily access constants.spinner.
3697
+ function getOverridesData(pkgEnvDetails, pkgJson) {
3698
+ switch (pkgEnvDetails.agent) {
3699
+ case BUN$4:
3700
+ return getOverridesDataBun(pkgEnvDetails, pkgJson);
3701
+ case PNPM$8:
3702
+ return getOverridesDataPnpm(pkgEnvDetails, pkgJson);
3703
+ case VLT$5:
3704
+ return getOverridesDataVlt(pkgEnvDetails, pkgJson);
3705
+ case YARN_BERRY$4:
3706
+ return getOverridesDataYarn(pkgEnvDetails, pkgJson);
3707
+ case YARN_CLASSIC$4:
3708
+ return getOverridesDataYarnClassic(pkgEnvDetails, pkgJson);
3709
+ case NPM$8:
3710
+ default:
3711
+ return getOverridesDataNpm(pkgEnvDetails, pkgJson);
3712
+ }
3713
+ }
3714
+
3715
+ const noopHandler = () => {};
3716
+ async function agentFix(pkgEnvDetails, actualTree, alertsMap, installer, {
3717
+ beforeInstall = noopHandler,
3718
+ // eslint-disable-next-line sort-destructure-keys/sort-destructure-keys
3719
+ afterInstall = noopHandler,
3720
+ revertInstall = noopHandler
3721
+ }, ciEnv, openPrs, options) {
3722
+ const {
3723
+ autoMerge,
3724
+ cwd,
3725
+ limit,
3726
+ rangeStyle,
3727
+ test,
3728
+ testScript
3729
+ } = options;
3731
3730
  const {
3732
3731
  spinner
3733
3732
  } = constants;
3734
3733
  const {
3735
3734
  pkgPath: rootPath
3736
3735
  } = pkgEnvDetails;
3737
- spinner?.start();
3738
- const ciEnv = await getCiEnv();
3739
- const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
3740
3736
  let count = 0;
3741
- const arb = new shadowNpmInject.Arborist({
3742
- path: rootPath,
3743
- ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
3744
- });
3745
- // Calling arb.reify() creates the arb.diff object, nulls-out arb.idealTree,
3746
- // and populates arb.actualTree.
3747
- let actualTree = await arb.reify();
3748
- let alertsMap;
3749
- try {
3750
- alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
3751
- limit: Math.max(limit, openPrs.length)
3752
- })) : await shadowNpmInject.getAlertsMapFromArborist(arb, getAlertsMapOptions({
3753
- limit: Math.max(limit, openPrs.length)
3754
- }));
3755
- } catch (e) {
3756
- spinner?.stop();
3757
- debug.debugFn('catch: PURL API\n', e);
3758
- return {
3759
- ok: false,
3760
- message: 'API Error',
3761
- cause: e?.message || 'Unknown Socket batch PURL API error.'
3762
- };
3763
- }
3764
3737
  const infoByPartialPurl = utils.getCveInfoFromAlertsMap(alertsMap, {
3765
3738
  limit: Math.max(limit, openPrs.length)
3766
3739
  });
@@ -3774,6 +3747,9 @@ async function npmFix(pkgEnvDetails, {
3774
3747
  }
3775
3748
  };
3776
3749
  }
3750
+ if (debug.isDebug()) {
3751
+ debug.debugFn('found: cves for', Array.from(infoByPartialPurl.keys()));
3752
+ }
3777
3753
 
3778
3754
  // Lazily access constants.packumentCache.
3779
3755
  const {
@@ -3793,8 +3769,8 @@ async function npmFix(pkgEnvDetails, {
3793
3769
  cleanupInfoEntriesLoop();
3794
3770
  return {
3795
3771
  ok: false,
3796
- message: 'Installation failure',
3797
- cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed.`
3772
+ message: 'Install failed',
3773
+ cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed`
3798
3774
  };
3799
3775
  };
3800
3776
  spinner?.stop();
@@ -3836,7 +3812,33 @@ async function npmFix(pkgEnvDetails, {
3836
3812
  const isWorkspaceRoot = pkgJsonPath === pkgEnvDetails.editablePkgJson.filename;
3837
3813
  const workspace = isWorkspaceRoot ? 'root' : path.relative(rootPath, pkgPath);
3838
3814
  const branchWorkspace = ciEnv ? getSocketBranchWorkspaceComponent(workspace) : '';
3839
- const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.target?.version ?? n.version).filter(Boolean));
3815
+
3816
+ // actualTree may not be defined on the first iteration of pkgJsonPathsLoop.
3817
+ if (!actualTree) {
3818
+ if (!ciEnv) {
3819
+ // eslint-disable-next-line no-await-in-loop
3820
+ await utils.removeNodeModules(cwd);
3821
+ }
3822
+ const maybeActualTree = ciEnv && fs$1.existsSync(path.join(rootPath, 'node_modules')) ?
3823
+ // eslint-disable-next-line no-await-in-loop
3824
+ await getActualTree(cwd) :
3825
+ // eslint-disable-next-line no-await-in-loop
3826
+ await installer(pkgEnvDetails, {
3827
+ cwd,
3828
+ spinner
3829
+ });
3830
+ const maybeLockSrc = maybeActualTree ?
3831
+ // eslint-disable-next-line no-await-in-loop
3832
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
3833
+ if (maybeActualTree && maybeLockSrc) {
3834
+ actualTree = maybeActualTree;
3835
+ }
3836
+ }
3837
+ if (!actualTree) {
3838
+ // Exit early if install fails.
3839
+ return handleInstallFail();
3840
+ }
3841
+ const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.version).filter(Boolean));
3840
3842
  if (!oldVersions.length) {
3841
3843
  debug.debugFn(`skip: ${name} not found\n`);
3842
3844
  // Skip to next package.
@@ -3850,7 +3852,7 @@ async function npmFix(pkgEnvDetails, {
3850
3852
  const editablePkgJson = await packages.readPackageJson(pkgJsonPath, {
3851
3853
  editable: true
3852
3854
  });
3853
- const fixedVersions = new Set();
3855
+ const seenVersions = new Set();
3854
3856
  let hasAnnouncedWorkspace = false;
3855
3857
  let workspaceLogCallCount = logger.logger.logCallCount;
3856
3858
  if (debug.isDebug()) {
@@ -3869,14 +3871,14 @@ async function npmFix(pkgEnvDetails, {
3869
3871
  infosLoop: for (const {
3870
3872
  firstPatchedVersionIdentifier,
3871
3873
  vulnerableVersionRange
3872
- } of infos.values()) {
3874
+ } of infos) {
3873
3875
  const newVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
3874
3876
  const newVersionPackument = newVersion ? packument.versions[newVersion] : undefined;
3875
3877
  if (!(newVersion && newVersionPackument)) {
3876
3878
  warningsForAfter.add(`${oldId} not updated: requires >=${firstPatchedVersionIdentifier}`);
3877
3879
  continue infosLoop;
3878
3880
  }
3879
- if (fixedVersions.has(newVersion)) {
3881
+ if (seenVersions.has(newVersion)) {
3880
3882
  continue infosLoop;
3881
3883
  }
3882
3884
  if (vendor.semverExports.gte(oldVersion, newVersion)) {
@@ -3891,29 +3893,20 @@ async function npmFix(pkgEnvDetails, {
3891
3893
  }
3892
3894
  continue infosLoop;
3893
3895
  }
3894
- const newVersionRange = utils.applyRange(oldVersion, newVersion, rangeStyle);
3895
- const newId = `${name}@${newVersionRange}`;
3896
- const revertData = {
3897
- ...(editablePkgJson.content.dependencies && {
3898
- dependencies: {
3899
- ...editablePkgJson.content.dependencies
3900
- }
3901
- }),
3902
- ...(editablePkgJson.content.optionalDependencies && {
3903
- optionalDependencies: {
3904
- ...editablePkgJson.content.optionalDependencies
3905
- }
3906
- }),
3907
- ...(editablePkgJson.content.peerDependencies && {
3908
- peerDependencies: {
3909
- ...editablePkgJson.content.peerDependencies
3910
- }
3911
- })
3912
- };
3913
- shadowNpmInject.updateNode(node, newVersion, newVersionPackument);
3914
- shadowNpmInject.updatePackageJsonFromNode(editablePkgJson,
3896
+ const {
3897
+ overrides: oldOverrides
3898
+ } = getOverridesData(pkgEnvDetails, editablePkgJson.content);
3899
+ let refRange = oldOverrides?.[`${name}@${vulnerableVersionRange}`];
3900
+ if (!strings.isNonEmptyString(refRange)) {
3901
+ refRange = oldOverrides?.[name];
3902
+ }
3903
+ if (!strings.isNonEmptyString(refRange)) {
3904
+ refRange = oldVersion;
3905
+ }
3906
+
3915
3907
  // eslint-disable-next-line no-await-in-loop
3916
- await arb.buildIdealTree(), node, newVersion, rangeStyle);
3908
+ await beforeInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
3909
+ shadowNpmInject.updatePackageJsonFromNode(editablePkgJson, actualTree, node, newVersion, rangeStyle);
3917
3910
  // eslint-disable-next-line no-await-in-loop
3918
3911
  if (!(await editablePkgJson.save({
3919
3912
  ignoreWhitespace: true
@@ -3930,17 +3923,24 @@ async function npmFix(pkgEnvDetails, {
3930
3923
  hasAnnouncedWorkspace = true;
3931
3924
  workspaceLogCallCount = logger.logger.logCallCount;
3932
3925
  }
3926
+ const newId = `${name}@${utils.applyRange(refRange, newVersion, rangeStyle)}`;
3933
3927
  spinner?.start();
3934
3928
  spinner?.info(`Installing ${newId} in ${workspace}.`);
3935
3929
  let error;
3936
3930
  let errored = false;
3937
3931
  try {
3938
3932
  // eslint-disable-next-line no-await-in-loop
3939
- const maybeActualTree = await install$1(arb, {
3940
- cwd
3933
+ const maybeActualTree = await installer(pkgEnvDetails, {
3934
+ cwd,
3935
+ spinner
3941
3936
  });
3942
- if (maybeActualTree) {
3937
+ const maybeLockSrc = maybeActualTree ?
3938
+ // eslint-disable-next-line no-await-in-loop
3939
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
3940
+ if (maybeActualTree && maybeLockSrc) {
3943
3941
  actualTree = maybeActualTree;
3942
+ // eslint-disable-next-line no-await-in-loop
3943
+ await afterInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
3944
3944
  if (test) {
3945
3945
  spinner?.info(`Testing ${newId} in ${workspace}.`);
3946
3946
  // eslint-disable-next-line no-await-in-loop
@@ -3950,13 +3950,13 @@ async function npmFix(pkgEnvDetails, {
3950
3950
  });
3951
3951
  }
3952
3952
  spinner?.success(`Fixed ${name} in ${workspace}.`);
3953
- fixedVersions.add(newVersion);
3953
+ seenVersions.add(newVersion);
3954
3954
  } else {
3955
3955
  errored = true;
3956
3956
  }
3957
3957
  } catch (e) {
3958
- errored = true;
3959
3958
  error = e;
3959
+ errored = true;
3960
3960
  }
3961
3961
  spinner?.stop();
3962
3962
 
@@ -3966,14 +3966,12 @@ async function npmFix(pkgEnvDetails, {
3966
3966
  // eslint-disable-next-line no-await-in-loop
3967
3967
  const result = await gitUnstagedModifiedFiles(cwd);
3968
3968
  if (!result.ok) {
3969
- // Do we fail if this fails? If this git command
3970
- // fails then probably other git commands do too?
3971
3969
  logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
3972
- continue infosLoop;
3970
+ continue;
3973
3971
  }
3974
- const moddedFilepaths = result.data.filter(p => {
3975
- const basename = path.basename(p);
3976
- return basename === 'package.json' || basename === 'package-lock.json';
3972
+ const moddedFilepaths = result.data.filter(filepath => {
3973
+ const basename = path.basename(filepath);
3974
+ return basename === 'package.json' || basename === pkgEnvDetails.lockName;
3977
3975
  });
3978
3976
  if (!moddedFilepaths.length) {
3979
3977
  logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
@@ -4005,15 +4003,19 @@ async function npmFix(pkgEnvDetails, {
4005
4003
  // eslint-disable-next-line no-await-in-loop
4006
4004
  await gitResetAndClean(ciEnv.baseBranch, cwd);
4007
4005
  // eslint-disable-next-line no-await-in-loop
4008
- const maybeActualTree = await install$1(arb, {
4009
- cwd
4006
+ const maybeActualTree = await installer(pkgEnvDetails, {
4007
+ cwd,
4008
+ spinner
4010
4009
  });
4011
- if (!maybeActualTree) {
4012
- // Exit early if install fails.
4013
- return handleInstallFail();
4010
+ const maybeLockSrc = maybeActualTree ?
4011
+ // eslint-disable-next-line no-await-in-loop
4012
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
4013
+ if (maybeActualTree && maybeLockSrc) {
4014
+ actualTree = maybeActualTree;
4015
+ continue infosLoop;
4014
4016
  }
4015
- actualTree = maybeActualTree;
4016
- continue infosLoop;
4017
+ // Exit early if install fails.
4018
+ return handleInstallFail();
4017
4019
  }
4018
4020
 
4019
4021
  // eslint-disable-next-line no-await-in-loop
@@ -4062,8 +4064,9 @@ async function npmFix(pkgEnvDetails, {
4062
4064
  // eslint-disable-next-line no-await-in-loop
4063
4065
  await gitResetAndClean(ciEnv.baseBranch, cwd);
4064
4066
  // eslint-disable-next-line no-await-in-loop
4065
- const maybeActualTree = await install$1(arb, {
4066
- cwd
4067
+ const maybeActualTree = await installer(pkgEnvDetails, {
4068
+ cwd,
4069
+ spinner
4067
4070
  });
4068
4071
  spinner?.stop();
4069
4072
  if (maybeActualTree) {
@@ -4075,24 +4078,33 @@ async function npmFix(pkgEnvDetails, {
4075
4078
  if (errored) {
4076
4079
  if (!ciEnv) {
4077
4080
  spinner?.start();
4078
- editablePkgJson.update(revertData);
4081
+ // eslint-disable-next-line no-await-in-loop
4082
+ await revertInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
4079
4083
  // eslint-disable-next-line no-await-in-loop
4080
4084
  await Promise.all([utils.removeNodeModules(cwd), editablePkgJson.save({
4081
4085
  ignoreWhitespace: true
4082
4086
  })]);
4083
4087
  // eslint-disable-next-line no-await-in-loop
4084
- const maybeActualTree = await install$1(arb, {
4085
- cwd
4088
+ const maybeActualTree = await installer(pkgEnvDetails, {
4089
+ cwd,
4090
+ spinner
4086
4091
  });
4087
4092
  spinner?.stop();
4088
- if (!maybeActualTree) {
4093
+ if (maybeActualTree) {
4094
+ actualTree = maybeActualTree;
4095
+ } else {
4089
4096
  // Exit early if install fails.
4090
4097
  return handleInstallFail();
4091
4098
  }
4092
- actualTree = maybeActualTree;
4093
4099
  }
4094
- logger.logger.fail(`Update failed for ${oldId} in ${workspace}.`, error);
4100
+ return {
4101
+ ok: false,
4102
+ message: 'Update failed',
4103
+ cause: `Update failed for ${oldId} in ${workspace}${error ? '; ' + error : ''}`
4104
+ };
4095
4105
  }
4106
+ debug.debugFn('name:', name);
4107
+ debug.debugFn('increment: count', count + 1);
4096
4108
  if (++count >= limit) {
4097
4109
  cleanupInfoEntriesLoop();
4098
4110
  break infoEntriesLoop;
@@ -4112,29 +4124,187 @@ async function npmFix(pkgEnvDetails, {
4112
4124
  cleanupInfoEntriesLoop();
4113
4125
  }
4114
4126
  spinner?.stop();
4127
+
4128
+ // Or, did we change anything?
4115
4129
  return {
4116
4130
  ok: true,
4117
4131
  data: {
4118
4132
  fixed: true
4119
4133
  }
4120
- }; // true? did we actually change anything?
4134
+ };
4121
4135
  }
4122
4136
 
4123
- const {
4124
- OVERRIDES: OVERRIDES$2,
4125
- PNPM: PNPM$8
4126
- } = constants;
4127
- async function getActualTree(cwd = process.cwd()) {
4128
- // @npmcli/arborist DOES have partial support for pnpm structured node_modules
4129
- // folders. However, support is iffy resulting in unhappy path errors and hangs.
4130
- // So, to avoid the unhappy path, we restrict our usage to --dry-run loading
4131
- // of the node_modules folder.
4132
- const arb = new shadowNpmInject.Arborist({
4133
- path: cwd,
4134
- ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
4135
- });
4136
- return await arb.loadActual();
4137
+ async function getEnvRepoInfo(cwd) {
4138
+ // Lazily access constants.ENV.GITHUB_REPOSITORY.
4139
+ const {
4140
+ GITHUB_REPOSITORY
4141
+ } = constants.ENV;
4142
+ if (!GITHUB_REPOSITORY) {
4143
+ debug.debugFn('miss: GITHUB_REPOSITORY env var');
4144
+ }
4145
+ const ownerSlashRepo = GITHUB_REPOSITORY;
4146
+ const slashIndex = ownerSlashRepo.indexOf('/');
4147
+ if (slashIndex !== -1) {
4148
+ return {
4149
+ owner: ownerSlashRepo.slice(0, slashIndex),
4150
+ repo: ownerSlashRepo.slice(slashIndex + 1)
4151
+ };
4152
+ }
4153
+ return await gitRepoInfo(cwd);
4154
+ }
4155
+ async function getCiEnv() {
4156
+ const gitEmail = constants.ENV.SOCKET_CLI_GIT_USER_EMAIL;
4157
+ const gitUser = constants.ENV.SOCKET_CLI_GIT_USER_NAME;
4158
+ const githubToken = constants.ENV.SOCKET_CLI_GITHUB_TOKEN;
4159
+ const isCi = !!(constants.ENV.CI && gitEmail && gitUser && githubToken);
4160
+ if (!isCi) {
4161
+ return null;
4162
+ }
4163
+ const baseBranch = await getBaseGitBranch();
4164
+ if (!baseBranch) {
4165
+ return null;
4166
+ }
4167
+ const repoInfo = await getEnvRepoInfo();
4168
+ if (!repoInfo) {
4169
+ return null;
4170
+ }
4171
+ return {
4172
+ gitEmail,
4173
+ gitUser,
4174
+ githubToken,
4175
+ repoInfo,
4176
+ baseBranch,
4177
+ branchParser: createSocketBranchParser()
4178
+ };
4179
+ }
4180
+ async function getOpenPrsForEnvironment(env) {
4181
+ return env ? await getOpenSocketPrs(env.repoInfo.owner, env.repoInfo.repo, {
4182
+ author: env.gitUser
4183
+ }) : [];
4184
+ }
4185
+
4186
+ const CMD_NAME$1 = 'socket fix';
4187
+ function getAlertsMapOptions(options = {}) {
4188
+ return {
4189
+ __proto__: null,
4190
+ consolidate: true,
4191
+ nothrow: true,
4192
+ ...options,
4193
+ include: {
4194
+ __proto__: null,
4195
+ existing: true,
4196
+ unfixable: false,
4197
+ upgradable: false,
4198
+ ...options?.include
4199
+ }
4200
+ };
4201
+ }
4202
+
4203
+ async function install$1(pkgEnvDetails, options) {
4204
+ const {
4205
+ args,
4206
+ cwd,
4207
+ spinner
4208
+ } = {
4209
+ __proto__: null,
4210
+ ...options
4211
+ };
4212
+ try {
4213
+ await utils.runAgentInstall(pkgEnvDetails, {
4214
+ args,
4215
+ spinner,
4216
+ stdio: debug.isDebug() ? 'inherit' : 'ignore'
4217
+ });
4218
+ return await getActualTree(cwd);
4219
+ } catch {}
4220
+ return null;
4221
+ }
4222
+ async function npmFix(pkgEnvDetails, options) {
4223
+ const {
4224
+ limit,
4225
+ purls,
4226
+ spinner
4227
+ } = options;
4228
+ spinner?.start();
4229
+ const ciEnv = await getCiEnv();
4230
+ const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
4231
+ let actualTree;
4232
+ let alertsMap;
4233
+ try {
4234
+ if (purls.length) {
4235
+ alertsMap = await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
4236
+ limit: Math.max(limit, openPrs.length)
4237
+ }));
4238
+ } else {
4239
+ const arb = new shadowNpmInject.Arborist({
4240
+ path: pkgEnvDetails.pkgPath,
4241
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
4242
+ });
4243
+ actualTree = await arb.reify();
4244
+ // Calling arb.reify() creates the arb.diff object, nulls-out arb.idealTree,
4245
+ // and populates arb.actualTree.
4246
+ alertsMap = await shadowNpmInject.getAlertsMapFromArborist(arb, getAlertsMapOptions({
4247
+ limit: Math.max(limit, openPrs.length)
4248
+ }));
4249
+ }
4250
+ } catch (e) {
4251
+ spinner?.stop();
4252
+ debug.debugFn('catch: PURL API\n', e);
4253
+ return {
4254
+ ok: false,
4255
+ message: 'API Error',
4256
+ cause: e?.message || 'Unknown Socket batch PURL API error.'
4257
+ };
4258
+ }
4259
+ let revertData;
4260
+ return await agentFix(pkgEnvDetails, actualTree, alertsMap, install$1, {
4261
+ async beforeInstall(editablePkgJson) {
4262
+ revertData = {
4263
+ ...(editablePkgJson.content.dependencies && {
4264
+ dependencies: {
4265
+ ...editablePkgJson.content.dependencies
4266
+ }
4267
+ }),
4268
+ ...(editablePkgJson.content.optionalDependencies && {
4269
+ optionalDependencies: {
4270
+ ...editablePkgJson.content.optionalDependencies
4271
+ }
4272
+ }),
4273
+ ...(editablePkgJson.content.peerDependencies && {
4274
+ peerDependencies: {
4275
+ ...editablePkgJson.content.peerDependencies
4276
+ }
4277
+ })
4278
+ };
4279
+ },
4280
+ async revertInstall(editablePkgJson) {
4281
+ if (revertData) {
4282
+ editablePkgJson.update(revertData);
4283
+ }
4284
+ }
4285
+ }, ciEnv, openPrs, options);
4286
+ }
4287
+
4288
+ async function outputFixResult(result, outputKind) {
4289
+ if (!result.ok) {
4290
+ process.exitCode = result.code ?? 1;
4291
+ }
4292
+ if (outputKind === 'json') {
4293
+ logger.logger.log(utils.serializeResultJson(result));
4294
+ return;
4295
+ }
4296
+ if (!result.ok) {
4297
+ logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
4298
+ return;
4299
+ }
4300
+ logger.logger.log('');
4301
+ logger.logger.success('Finished!');
4137
4302
  }
4303
+
4304
+ const {
4305
+ OVERRIDES: OVERRIDES$1,
4306
+ PNPM: PNPM$7
4307
+ } = constants;
4138
4308
  async function install(pkgEnvDetails, options) {
4139
4309
  const {
4140
4310
  args,
@@ -4160,64 +4330,40 @@ async function install(pkgEnvDetails, options) {
4160
4330
  } catch {}
4161
4331
  return null;
4162
4332
  }
4163
- async function pnpmFix(pkgEnvDetails, {
4164
- autoMerge,
4165
- cwd,
4166
- limit,
4167
- purls,
4168
- rangeStyle,
4169
- test,
4170
- testScript
4171
- }) {
4172
- // Lazily access constants.spinner.
4333
+ async function pnpmFix(pkgEnvDetails, options) {
4173
4334
  const {
4335
+ cwd,
4336
+ limit,
4337
+ purls,
4174
4338
  spinner
4175
- } = constants;
4176
- const {
4177
- pkgPath: rootPath
4178
- } = pkgEnvDetails;
4339
+ } = options;
4179
4340
  spinner?.start();
4180
- const ciEnv = await getCiEnv();
4181
- const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
4182
- let count = 0;
4183
4341
  let actualTree;
4184
- const lockfilePath = path.join(rootPath, 'pnpm-lock.yaml');
4185
- let lockfileContent = await utils.readPnpmLockfile(lockfilePath);
4186
-
4187
- // If pnpm-lock.yaml does NOT exist then install with pnpm to create it.
4188
- if (!lockfileContent) {
4189
- const maybeActualTree = await install(pkgEnvDetails, {
4190
- cwd,
4191
- spinner
4192
- });
4193
- const maybeLockfileContent = maybeActualTree ? await utils.readPnpmLockfile(lockfilePath) : null;
4194
- if (maybeActualTree) {
4195
- actualTree = maybeActualTree;
4196
- lockfileContent = maybeLockfileContent;
4197
- }
4198
- }
4199
- let lockfile = utils.parsePnpmLockfile(lockfileContent);
4342
+ let {
4343
+ lockSrc
4344
+ } = pkgEnvDetails;
4345
+ let lockfile = utils.parsePnpmLockfile(lockSrc);
4200
4346
  // Update pnpm-lock.yaml if its version is older than what the installed pnpm
4201
4347
  // produces.
4202
- if (lockfileContent && pkgEnvDetails.agentVersion.major >= 10 && (utils.parsePnpmLockfileVersion(lockfile?.lockfileVersion)?.major ?? 0) <= 6) {
4348
+ if (pkgEnvDetails.agentVersion.major >= 10 && (utils.parsePnpmLockfileVersion(lockfile?.lockfileVersion)?.major ?? 0) <= 6) {
4203
4349
  const maybeActualTree = await install(pkgEnvDetails, {
4204
4350
  args: ['--lockfile-only'],
4205
4351
  cwd,
4206
4352
  spinner
4207
4353
  });
4208
- const maybeLockfileContent = maybeActualTree ? await utils.readPnpmLockfile(lockfilePath) : null;
4209
- if (maybeActualTree && maybeLockfileContent) {
4354
+ const maybeLockSrc = maybeActualTree ? await utils.readLockfile(pkgEnvDetails.lockPath) : null;
4355
+ if (maybeActualTree && maybeLockSrc) {
4210
4356
  actualTree = maybeActualTree;
4211
- lockfileContent = maybeLockfileContent;
4212
- lockfile = utils.parsePnpmLockfile(lockfileContent);
4357
+ lockSrc = maybeLockSrc;
4358
+ lockfile = utils.parsePnpmLockfile(lockSrc);
4213
4359
  } else {
4214
4360
  lockfile = null;
4215
4361
  }
4216
4362
  }
4217
4363
 
4218
4364
  // Exit early if pnpm-lock.yaml is not found or usable.
4219
- // Check !lockfileContent to make TypeScript happy.
4220
- if (!lockfile || !lockfileContent) {
4365
+ // Check !lockSrc to make TypeScript happy.
4366
+ if (!lockfile || !lockSrc) {
4221
4367
  spinner?.stop();
4222
4368
  return {
4223
4369
  ok: false,
@@ -4225,6 +4371,8 @@ async function pnpmFix(pkgEnvDetails, {
4225
4371
  cause: 'Required pnpm-lock.yaml not found or usable'
4226
4372
  };
4227
4373
  }
4374
+ const ciEnv = await getCiEnv();
4375
+ const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
4228
4376
  let alertsMap;
4229
4377
  try {
4230
4378
  alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
@@ -4234,550 +4382,186 @@ async function pnpmFix(pkgEnvDetails, {
4234
4382
  }));
4235
4383
  } catch (e) {
4236
4384
  spinner?.stop();
4237
- debug.debugFn('catch: PURL API\n', e);
4238
- return {
4239
- ok: false,
4240
- message: 'API Error',
4241
- cause: e?.message || 'Unknown Socket batch PURL API error.'
4242
- };
4243
- }
4244
- const infoByPartialPurl = utils.getCveInfoFromAlertsMap(alertsMap, {
4245
- limit: Math.max(limit, openPrs.length)
4246
- });
4247
- if (!infoByPartialPurl) {
4248
- spinner?.stop();
4249
- logger.logger.info('No fixable vulns found.');
4250
- return {
4251
- ok: true,
4252
- data: {
4253
- fixed: false
4254
- }
4255
- };
4256
- }
4257
- if (debug.isDebug()) {
4258
- debug.debugFn('found: cves for', Array.from(infoByPartialPurl.keys()));
4259
- }
4260
-
4261
- // Lazily access constants.packumentCache.
4262
- const {
4263
- packumentCache
4264
- } = constants;
4265
- const workspacePkgJsonPaths = await utils.globWorkspace(pkgEnvDetails.agent, rootPath);
4266
- const pkgJsonPaths = [...workspacePkgJsonPaths,
4267
- // Process the workspace root last since it will add an override to package.json.
4268
- pkgEnvDetails.editablePkgJson.filename];
4269
- const sortedInfoEntries = Array.from(infoByPartialPurl.entries()).sort((a, b) => sorts.naturalCompare(a[0], b[0]));
4270
- const cleanupInfoEntriesLoop = () => {
4271
- logger.logger.dedent();
4272
- spinner?.dedent();
4273
- packumentCache.clear();
4274
- };
4275
- const handleInstallFail = () => {
4276
- cleanupInfoEntriesLoop();
4277
- return {
4278
- ok: false,
4279
- message: 'Install failed',
4280
- cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed`
4281
- };
4282
- };
4283
- spinner?.stop();
4284
- infoEntriesLoop: for (let i = 0, {
4285
- length
4286
- } = sortedInfoEntries; i < length; i += 1) {
4287
- const isLastInfoEntry = i === length - 1;
4288
- const infoEntry = sortedInfoEntries[i];
4289
- const partialPurlObj = utils.getPurlObject(infoEntry[0]);
4290
- const name = packages.resolvePackageName(partialPurlObj);
4291
- const infos = Array.from(infoEntry[1].values());
4292
- if (!infos.length) {
4293
- continue infoEntriesLoop;
4294
- }
4295
- logger.logger.log(`Processing vulns for ${name}:`);
4296
- logger.logger.indent();
4297
- spinner?.indent();
4298
- if (registry.getManifestData(partialPurlObj.type, name)) {
4299
- debug.debugFn(`found: Socket Optimize variant for ${name}`);
4300
- }
4301
- // eslint-disable-next-line no-await-in-loop
4302
- const packument = await packages.fetchPackagePackument(name);
4303
- if (!packument) {
4304
- logger.logger.warn(`Unexpected condition: No packument found for ${name}.\n`);
4305
- cleanupInfoEntriesLoop();
4306
- continue infoEntriesLoop;
4307
- }
4308
- const activeBranches = getActiveBranchesForPackage(ciEnv, infoEntry[0], openPrs);
4309
- const availableVersions = Object.keys(packument.versions);
4310
- const warningsForAfter = new Set();
4311
-
4312
- // eslint-disable-next-line no-unused-labels
4313
- for (let j = 0, {
4314
- length: length_j
4315
- } = pkgJsonPaths; j < length_j; j += 1) {
4316
- const isLastPkgJsonPath = j === length_j - 1;
4317
- const pkgJsonPath = pkgJsonPaths[j];
4318
- const pkgPath = path.dirname(pkgJsonPath);
4319
- const isWorkspaceRoot = pkgJsonPath === pkgEnvDetails.editablePkgJson.filename;
4320
- const workspace = isWorkspaceRoot ? 'root' : path.relative(rootPath, pkgPath);
4321
- const branchWorkspace = ciEnv ? getSocketBranchWorkspaceComponent(workspace) : '';
4322
-
4323
- // actualTree may not be defined on the first iteration of pkgJsonPathsLoop.
4324
- if (!actualTree) {
4325
- if (!ciEnv) {
4326
- // eslint-disable-next-line no-await-in-loop
4327
- await utils.removeNodeModules(cwd);
4328
- }
4329
- const maybeActualTree = ciEnv && fs$1.existsSync(path.join(rootPath, 'node_modules')) ?
4330
- // eslint-disable-next-line no-await-in-loop
4331
- await getActualTree(cwd) :
4332
- // eslint-disable-next-line no-await-in-loop
4333
- await install(pkgEnvDetails, {
4334
- cwd,
4335
- spinner
4336
- });
4337
- const maybeLockfileContent = maybeActualTree ?
4338
- // eslint-disable-next-line no-await-in-loop
4339
- await utils.readPnpmLockfile(lockfilePath) : null;
4340
- if (maybeActualTree && maybeLockfileContent) {
4341
- actualTree = maybeActualTree;
4342
- lockfileContent = maybeLockfileContent;
4343
- }
4344
- }
4345
- if (!actualTree) {
4346
- // Exit early if install fails.
4347
- return handleInstallFail();
4348
- }
4349
- const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.version).filter(Boolean));
4350
- if (!oldVersions.length) {
4351
- debug.debugFn(`skip: ${name} not found\n`);
4352
- // Skip to next package.
4353
- cleanupInfoEntriesLoop();
4354
- continue infoEntriesLoop;
4355
- }
4356
-
4357
- // Always re-read the editable package.json to avoid stale mutations
4358
- // across iterations.
4359
- // eslint-disable-next-line no-await-in-loop
4360
- const editablePkgJson = await packages.readPackageJson(pkgJsonPath, {
4361
- editable: true
4362
- });
4363
- const fixedVersions = new Set();
4364
-
4365
- // Get current overrides for revert logic.
4366
- const oldPnpmSection = editablePkgJson.content[PNPM$8];
4367
- const oldOverrides = oldPnpmSection?.[OVERRIDES$2];
4368
- let hasAnnouncedWorkspace = false;
4369
- let workspaceLogCallCount = logger.logger.logCallCount;
4370
- if (debug.isDebug()) {
4371
- debug.debugFn(`check: workspace ${workspace}`);
4372
- hasAnnouncedWorkspace = true;
4373
- workspaceLogCallCount = logger.logger.logCallCount;
4374
- }
4375
- oldVersionsLoop: for (const oldVersion of oldVersions) {
4376
- const oldId = `${name}@${oldVersion}`;
4377
- const oldPurl = utils.idToPurl(oldId, partialPurlObj.type);
4378
- const node = shadowNpmInject.findPackageNode(actualTree, name, oldVersion);
4379
- if (!node) {
4380
- debug.debugFn(`skip: ${oldId} not found`);
4381
- continue oldVersionsLoop;
4382
- }
4383
- infosLoop: for (const {
4384
- firstPatchedVersionIdentifier,
4385
- vulnerableVersionRange
4386
- } of infos) {
4387
- const newVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
4388
- const newVersionPackument = newVersion ? packument.versions[newVersion] : undefined;
4389
- if (!(newVersion && newVersionPackument)) {
4390
- warningsForAfter.add(`${oldId} not updated: requires >=${firstPatchedVersionIdentifier}`);
4391
- continue infosLoop;
4392
- }
4393
- if (fixedVersions.has(newVersion)) {
4394
- continue infosLoop;
4395
- }
4396
- if (vendor.semverExports.gte(oldVersion, newVersion)) {
4397
- debug.debugFn(`skip: ${oldId} is >= ${newVersion}`);
4398
- continue infosLoop;
4399
- }
4400
- if (activeBranches.find(b => b.workspace === branchWorkspace && b.newVersion === newVersion)) {
4401
- debug.debugFn(`skip: open PR found for ${name}@${newVersion}`);
4402
- if (++count >= limit) {
4403
- cleanupInfoEntriesLoop();
4404
- break infoEntriesLoop;
4405
- }
4406
- continue infosLoop;
4407
- }
4408
- const overrideKey = `${name}@${vulnerableVersionRange}`;
4409
- const newVersionRange = utils.applyRange(oldOverrides?.[overrideKey] ?? oldVersion, newVersion, rangeStyle);
4410
- const newId = `${name}@${newVersionRange}`;
4411
- const updateOverrides = isWorkspaceRoot ? {
4412
- [PNPM$8]: {
4413
- ...oldPnpmSection,
4414
- [OVERRIDES$2]: {
4415
- ...oldOverrides,
4416
- [overrideKey]: newVersionRange
4417
- }
4418
- }
4419
- } : undefined;
4420
- const revertOverrides = isWorkspaceRoot ? {
4421
- [PNPM$8]: oldPnpmSection ? {
4422
- ...oldPnpmSection,
4423
- [OVERRIDES$2]: oldOverrides && Object.keys(oldOverrides).length > 1 ? {
4424
- ...oldOverrides,
4425
- [overrideKey]: undefined
4426
- } : undefined
4427
- } : undefined
4428
- } : {};
4429
- const revertData = {
4430
- ...revertOverrides,
4431
- ...(editablePkgJson.content.dependencies && {
4432
- dependencies: {
4433
- ...editablePkgJson.content.dependencies
4434
- }
4435
- }),
4436
- ...(editablePkgJson.content.optionalDependencies && {
4437
- optionalDependencies: {
4438
- ...editablePkgJson.content.optionalDependencies
4439
- }
4440
- }),
4441
- ...(editablePkgJson.content.peerDependencies && {
4442
- peerDependencies: {
4443
- ...editablePkgJson.content.peerDependencies
4444
- }
4445
- })
4446
- };
4447
- if (updateOverrides) {
4448
- // Update overrides in the root package.json so that when `pnpm install`
4449
- // generates pnpm-lock.yaml it updates transitive dependencies too.
4450
- editablePkgJson.update(updateOverrides);
4451
- }
4452
- shadowNpmInject.updatePackageJsonFromNode(editablePkgJson, actualTree, node, newVersion, rangeStyle);
4453
- // eslint-disable-next-line no-await-in-loop
4454
- if (!(await editablePkgJson.save({
4455
- ignoreWhitespace: true
4456
- }))) {
4457
- debug.debugFn(`skip: ${workspace}/package.json unchanged`);
4458
- // Reset things just in case.
4459
- if (ciEnv) {
4460
- // eslint-disable-next-line no-await-in-loop
4461
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4462
- }
4463
- continue infosLoop;
4464
- }
4465
- if (!hasAnnouncedWorkspace) {
4466
- hasAnnouncedWorkspace = true;
4467
- workspaceLogCallCount = logger.logger.logCallCount;
4468
- }
4469
- spinner?.start();
4470
- spinner?.info(`Installing ${newId} in ${workspace}.`);
4471
- let error;
4472
- let errored = false;
4473
- try {
4474
- const revertOverridesContent = utils.extractOverridesFromPnpmLockfileContent(lockfileContent);
4475
- // eslint-disable-next-line no-await-in-loop
4476
- const maybeActualTree = await install(pkgEnvDetails, {
4477
- cwd,
4478
- spinner
4479
- });
4480
- const maybeLockfileContent = maybeActualTree ?
4481
- // eslint-disable-next-line no-await-in-loop
4482
- await utils.readPnpmLockfile(lockfilePath) : null;
4483
- if (maybeActualTree && maybeLockfileContent) {
4484
- actualTree = maybeActualTree;
4485
- lockfileContent = maybeLockfileContent;
4486
- // Revert overrides metadata in package.json now that pnpm-lock.yaml
4487
- // has been updated.
4488
- editablePkgJson.update(revertOverrides);
4489
- // eslint-disable-next-line no-await-in-loop
4490
- await editablePkgJson.save({
4491
- ignoreWhitespace: true
4492
- });
4493
- const updatedOverridesContent = utils.extractOverridesFromPnpmLockfileContent(lockfileContent);
4494
- if (updatedOverridesContent) {
4495
- lockfileContent = lockfileContent.replace(updatedOverridesContent, revertOverridesContent);
4496
- // eslint-disable-next-line no-await-in-loop
4497
- await fs$1.promises.writeFile(lockfilePath, lockfileContent, 'utf8');
4498
- }
4499
- if (test) {
4500
- spinner?.info(`Testing ${newId} in ${workspace}.`);
4501
- // eslint-disable-next-line no-await-in-loop
4502
- await npm.runScript(testScript, [], {
4503
- spinner,
4504
- stdio: 'ignore'
4505
- });
4506
- }
4507
- spinner?.success(`Fixed ${name} in ${workspace}.`);
4508
- fixedVersions.add(newVersion);
4509
- } else {
4510
- errored = true;
4511
- }
4512
- } catch (e) {
4513
- error = e;
4514
- errored = true;
4515
- }
4516
- spinner?.stop();
4517
-
4518
- // Check repoInfo to make TypeScript happy.
4519
- if (!errored && ciEnv?.repoInfo) {
4520
- try {
4521
- // eslint-disable-next-line no-await-in-loop
4522
- const result = await gitUnstagedModifiedFiles(cwd);
4523
- if (!result.ok) {
4524
- logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
4525
- continue;
4526
- }
4527
- const moddedFilepaths = result.data.filter(p => {
4528
- const basename = path.basename(p);
4529
- return basename === 'package.json' || basename === 'pnpm-lock.yaml';
4530
- });
4531
- if (!moddedFilepaths.length) {
4532
- logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
4533
- continue infosLoop;
4534
- }
4535
- const branch = getSocketBranchName(oldPurl, newVersion, workspace);
4536
- let skipPr = false;
4537
- if (
4538
- // eslint-disable-next-line no-await-in-loop
4539
- await prExistForBranch(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, branch)) {
4540
- skipPr = true;
4541
- debug.debugFn(`skip: branch "${branch}" exists`);
4542
- }
4543
- // eslint-disable-next-line no-await-in-loop
4544
- else if (await gitRemoteBranchExists(branch, cwd)) {
4545
- skipPr = true;
4546
- debug.debugFn(`skip: remote branch "${branch}" exists`);
4547
- } else if (
4548
- // eslint-disable-next-line no-await-in-loop
4549
- !(await gitCreateAndPushBranch(branch, getSocketCommitMessage(oldPurl, newVersion, workspace), moddedFilepaths, {
4550
- cwd,
4551
- email: ciEnv.gitEmail,
4552
- user: ciEnv.gitUser
4553
- }))) {
4554
- skipPr = true;
4555
- logger.logger.warn('Unexpected condition: Push failed, skipping PR creation.');
4556
- }
4557
- if (skipPr) {
4558
- // eslint-disable-next-line no-await-in-loop
4559
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4560
- // eslint-disable-next-line no-await-in-loop
4561
- const maybeActualTree = await install(pkgEnvDetails, {
4562
- cwd,
4563
- spinner
4564
- });
4565
- const maybeLockfileContent = maybeActualTree ?
4566
- // eslint-disable-next-line no-await-in-loop
4567
- await utils.readPnpmLockfile(lockfilePath) : null;
4568
- if (maybeActualTree && maybeLockfileContent) {
4569
- actualTree = maybeActualTree;
4570
- lockfileContent = maybeLockfileContent;
4571
- continue infosLoop;
4572
- }
4573
- // Exit early if install fails.
4574
- return handleInstallFail();
4575
- }
4576
-
4577
- // eslint-disable-next-line no-await-in-loop
4578
- await Promise.allSettled([setGitRemoteGithubRepoUrl(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, ciEnv.githubToken, cwd), cleanupOpenPrs(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, {
4579
- newVersion,
4580
- purl: oldPurl,
4581
- workspace
4582
- })]);
4583
- // eslint-disable-next-line no-await-in-loop
4584
- const prResponse = await openPr(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, branch, oldPurl, newVersion, {
4585
- baseBranch: ciEnv.baseBranch,
4586
- cwd,
4587
- workspace
4588
- });
4589
- if (prResponse) {
4590
- const {
4591
- data
4592
- } = prResponse;
4593
- const prRef = `PR #${data.number}`;
4594
- logger.logger.success(`Opened ${prRef}.`);
4595
- if (autoMerge) {
4596
- logger.logger.indent();
4597
- spinner?.indent();
4598
- // eslint-disable-next-line no-await-in-loop
4599
- const {
4600
- details,
4601
- enabled
4602
- } = await enablePrAutoMerge(data);
4603
- if (enabled) {
4604
- logger.logger.info(`Auto-merge enabled for ${prRef}.`);
4605
- } else {
4606
- const message = `Failed to enable auto-merge for ${prRef}${details ? `:\n${details.map(d => ` - ${d}`).join('\n')}` : '.'}`;
4607
- logger.logger.error(message);
4608
- }
4609
- logger.logger.dedent();
4610
- spinner?.dedent();
4611
- }
4612
- }
4613
- } catch (e) {
4614
- error = e;
4615
- errored = true;
4616
- }
4617
- }
4618
- if (ciEnv) {
4619
- spinner?.start();
4620
- // eslint-disable-next-line no-await-in-loop
4621
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4622
- // eslint-disable-next-line no-await-in-loop
4623
- const maybeActualTree = await install(pkgEnvDetails, {
4624
- cwd,
4625
- spinner
4626
- });
4627
- const maybeLockfileContent = maybeActualTree ?
4628
- // eslint-disable-next-line no-await-in-loop
4629
- await utils.readPnpmLockfile(lockfilePath) : null;
4630
- spinner?.stop();
4631
- if (maybeActualTree) {
4632
- actualTree = maybeActualTree;
4633
- lockfileContent = maybeLockfileContent;
4634
- } else {
4635
- errored = true;
4636
- }
4637
- }
4638
- if (errored) {
4639
- if (!ciEnv) {
4640
- spinner?.start();
4641
- editablePkgJson.update(revertData);
4642
- // eslint-disable-next-line no-await-in-loop
4643
- await Promise.all([utils.removeNodeModules(cwd), editablePkgJson.save({
4644
- ignoreWhitespace: true
4645
- })]);
4646
- // eslint-disable-next-line no-await-in-loop
4647
- const maybeActualTree = await install(pkgEnvDetails, {
4648
- cwd,
4649
- spinner
4650
- });
4651
- const maybeLockfileContent = maybeActualTree ?
4652
- // eslint-disable-next-line no-await-in-loop
4653
- await utils.readPnpmLockfile(lockfilePath) : null;
4654
- spinner?.stop();
4655
- if (maybeActualTree) {
4656
- actualTree = maybeActualTree;
4657
- lockfileContent = maybeLockfileContent;
4658
- } else {
4659
- // Exit early if install fails.
4660
- return handleInstallFail();
4661
- }
4385
+ debug.debugFn('catch: PURL API\n', e);
4386
+ return {
4387
+ ok: false,
4388
+ message: 'API Error',
4389
+ cause: e?.message || 'Unknown Socket batch PURL API error.'
4390
+ };
4391
+ }
4392
+ let revertData;
4393
+ let revertOverrides;
4394
+ let revertOverridesSrc;
4395
+ return await agentFix(pkgEnvDetails, actualTree, alertsMap, install, {
4396
+ async beforeInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options) {
4397
+ const isWorkspaceRoot = editablePkgJson.path === pkgEnvDetails.editablePkgJson.filename;
4398
+ // Get current overrides for revert logic.
4399
+ const {
4400
+ overrides: oldOverrides
4401
+ } = getOverridesDataPnpm(pkgEnvDetails, editablePkgJson.content);
4402
+ const oldPnpmSection = editablePkgJson.content[PNPM$7];
4403
+ const overrideKey = `${name}@${vulnerableVersionRange}`;
4404
+ revertOverrides = undefined;
4405
+ revertOverridesSrc = utils.extractOverridesFromPnpmLockSrc(lockSrc);
4406
+ if (isWorkspaceRoot) {
4407
+ revertOverrides = {
4408
+ [PNPM$7]: oldPnpmSection ? {
4409
+ ...oldPnpmSection,
4410
+ [OVERRIDES$1]: objects.hasKeys(oldOverrides) ? {
4411
+ ...oldOverrides,
4412
+ [overrideKey]: undefined
4413
+ } : undefined
4414
+ } : undefined
4415
+ };
4416
+ // Update overrides in the root package.json so that when `pnpm install`
4417
+ // generates pnpm-lock.yaml it updates transitive dependencies too.
4418
+ editablePkgJson.update({
4419
+ [PNPM$7]: {
4420
+ ...oldPnpmSection,
4421
+ [OVERRIDES$1]: {
4422
+ ...oldOverrides,
4423
+ [overrideKey]: utils.applyRange(oldOverrides?.[overrideKey] ?? oldVersion, newVersion, options.rangeStyle)
4662
4424
  }
4663
- return {
4664
- ok: false,
4665
- message: 'Update failed',
4666
- cause: `Update failed for ${oldId} in ${workspace}${error ? '; ' + error : ''}`
4667
- };
4668
4425
  }
4669
- debug.debugFn('name:', name);
4670
- debug.debugFn('increment: count', count + 1);
4671
- if (++count >= limit) {
4672
- cleanupInfoEntriesLoop();
4673
- break infoEntriesLoop;
4426
+ });
4427
+ }
4428
+ revertData = {
4429
+ ...revertOverrides,
4430
+ ...(editablePkgJson.content.dependencies && {
4431
+ dependencies: {
4432
+ ...editablePkgJson.content.dependencies
4674
4433
  }
4675
- }
4434
+ }),
4435
+ ...(editablePkgJson.content.optionalDependencies && {
4436
+ optionalDependencies: {
4437
+ ...editablePkgJson.content.optionalDependencies
4438
+ }
4439
+ }),
4440
+ ...(editablePkgJson.content.peerDependencies && {
4441
+ peerDependencies: {
4442
+ ...editablePkgJson.content.peerDependencies
4443
+ }
4444
+ })
4445
+ };
4446
+ },
4447
+ async afterInstall(editablePkgJson) {
4448
+ if (revertOverrides) {
4449
+ // Revert overrides metadata in package.json now that pnpm-lock.yaml
4450
+ // has been updated.
4451
+ editablePkgJson.update(revertOverrides);
4676
4452
  }
4677
- if (!isLastPkgJsonPath && logger.logger.logCallCount > workspaceLogCallCount) {
4678
- logger.logger.logNewline();
4453
+ await editablePkgJson.save({
4454
+ ignoreWhitespace: true
4455
+ });
4456
+ const updatedOverridesContent = utils.extractOverridesFromPnpmLockSrc(lockSrc);
4457
+ if (updatedOverridesContent && revertOverridesSrc) {
4458
+ lockSrc = lockSrc.replace(updatedOverridesContent, revertOverridesSrc);
4459
+ await fs$1.promises.writeFile(pkgEnvDetails.lockPath, lockSrc, 'utf8');
4460
+ }
4461
+ },
4462
+ async revertInstall(editablePkgJson) {
4463
+ if (revertData) {
4464
+ editablePkgJson.update(revertData);
4679
4465
  }
4680
4466
  }
4681
- for (const warningText of warningsForAfter) {
4682
- logger.logger.warn(warningText);
4683
- }
4684
- if (!isLastInfoEntry) {
4685
- logger.logger.logNewline();
4686
- }
4687
- cleanupInfoEntriesLoop();
4688
- }
4689
- spinner?.stop();
4690
-
4691
- // Or, did we change anything?
4692
- return {
4693
- ok: true,
4694
- data: {
4695
- fixed: true
4696
- }
4697
- };
4467
+ }, ciEnv, openPrs, options);
4698
4468
  }
4699
4469
 
4700
4470
  const {
4701
- NPM: NPM$8,
4702
- PNPM: PNPM$7
4471
+ NPM: NPM$7,
4472
+ PNPM: PNPM$6
4703
4473
  } = constants;
4704
- async function runFix({
4474
+ async function handleFix({
4705
4475
  autoMerge,
4706
4476
  cwd,
4477
+ ghsas,
4707
4478
  limit,
4479
+ outputKind,
4708
4480
  purls,
4709
4481
  rangeStyle,
4710
4482
  test,
4711
4483
  testScript
4712
4484
  }) {
4713
- const result = await utils.detectAndValidatePackageEnvironment(cwd, {
4485
+ let {
4486
+ length: ghsasCount
4487
+ } = ghsas;
4488
+ if (ghsasCount) {
4489
+ // Lazily access constants.spinner.
4490
+ const {
4491
+ spinner
4492
+ } = constants;
4493
+ spinner.start();
4494
+ if (ghsasCount === 1 && ghsas[0] === 'auto') {
4495
+ const autoCResult = await utils.spawnCoana(['compute-fixes-and-upgrade-purls', cwd], {
4496
+ cwd,
4497
+ spinner
4498
+ });
4499
+ if (autoCResult.ok) {
4500
+ ghsas = utils.cmdFlagValueToArray(/(?<=Vulnerabilities found: )[^\n]+/.exec(autoCResult.data)?.[0]);
4501
+ ghsasCount = ghsas.length;
4502
+ } else {
4503
+ ghsas = [];
4504
+ ghsasCount = 0;
4505
+ }
4506
+ }
4507
+ spinner.stop();
4508
+ if (ghsasCount) {
4509
+ spinner.start();
4510
+ await outputFixResult(await utils.spawnCoana(['compute-fixes-and-upgrade-purls', cwd, '--apply-fixes-to', ...ghsas], {
4511
+ cwd,
4512
+ spinner
4513
+ }), outputKind);
4514
+ spinner.stop();
4515
+ return;
4516
+ }
4517
+ }
4518
+ const pkgEnvCResult = await utils.detectAndValidatePackageEnvironment(cwd, {
4714
4519
  cmdName: CMD_NAME$1,
4715
4520
  logger: logger.logger
4716
4521
  });
4717
- if (!result.ok) {
4718
- return result;
4522
+ if (!pkgEnvCResult.ok) {
4523
+ await outputFixResult(pkgEnvCResult, outputKind);
4524
+ return;
4719
4525
  }
4720
- const pkgEnvDetails = result.data;
4526
+ const {
4527
+ data: pkgEnvDetails
4528
+ } = pkgEnvCResult;
4721
4529
  if (!pkgEnvDetails) {
4722
- return {
4530
+ await outputFixResult({
4723
4531
  ok: false,
4724
4532
  message: 'No package found',
4725
4533
  cause: `No valid package environment was found in given cwd (${cwd})`
4726
- };
4534
+ }, outputKind);
4535
+ return;
4727
4536
  }
4728
- logger.logger.info(`Fixing packages for ${pkgEnvDetails.agent}.\n`);
4537
+ logger.logger.info(`Fixing packages for ${pkgEnvDetails.agent} v${pkgEnvDetails.agentVersion}.\n`);
4729
4538
  const {
4730
4539
  agent
4731
4540
  } = pkgEnvDetails;
4732
- if (agent === NPM$8) {
4733
- return await npmFix(pkgEnvDetails, {
4734
- autoMerge,
4735
- cwd,
4736
- limit,
4737
- purls,
4738
- rangeStyle,
4739
- test,
4740
- testScript
4741
- });
4742
- } else if (agent === PNPM$7) {
4743
- return await pnpmFix(pkgEnvDetails, {
4744
- autoMerge,
4745
- cwd,
4746
- limit,
4747
- purls,
4748
- rangeStyle,
4749
- test,
4750
- testScript
4751
- });
4752
- } else {
4753
- return {
4541
+ if (agent !== NPM$7 && agent !== PNPM$6) {
4542
+ await outputFixResult({
4754
4543
  ok: false,
4755
4544
  message: 'Not supported',
4756
4545
  cause: `${agent} is not supported by this command at the moment.`
4757
- };
4546
+ }, outputKind);
4547
+ return;
4758
4548
  }
4759
- }
4760
4549
 
4761
- async function handleFix({
4762
- autoMerge,
4763
- cwd,
4764
- limit,
4765
- outputKind,
4766
- purls,
4767
- rangeStyle,
4768
- test,
4769
- testScript
4770
- }) {
4771
- const result = await runFix({
4550
+ // Lazily access spinner.
4551
+ const {
4552
+ spinner
4553
+ } = constants;
4554
+ const fixer = agent === NPM$7 ? npmFix : pnpmFix;
4555
+ await outputFixResult(await fixer(pkgEnvDetails, {
4772
4556
  autoMerge,
4773
4557
  cwd,
4774
4558
  limit,
4775
4559
  purls,
4776
4560
  rangeStyle,
4561
+ spinner,
4777
4562
  test,
4778
4563
  testScript
4779
- });
4780
- await outputFixResult(result, outputKind);
4564
+ }), outputKind);
4781
4565
  }
4782
4566
 
4783
4567
  const {
@@ -4799,6 +4583,12 @@ const config$H = {
4799
4583
  default: false,
4800
4584
  description: `Shorthand for --autoMerge --test`
4801
4585
  },
4586
+ ghsa: {
4587
+ type: 'string',
4588
+ default: [],
4589
+ description: `Provide a list of ${vendor.terminalLinkExports('GHSA IDs', 'https://docs.github.com/en/code-security/security-advisories/working-with-global-security-advisories-from-the-github-advisory-database/about-the-github-advisory-database#about-ghsa-ids')} to compute fixes for, as either a comma separated value or as multiple flags`,
4590
+ isMultiple: true
4591
+ },
4802
4592
  limit: {
4803
4593
  type: 'number',
4804
4594
  default: Infinity,
@@ -4807,7 +4597,7 @@ const config$H = {
4807
4597
  purl: {
4808
4598
  type: 'string',
4809
4599
  default: [],
4810
- description: `Provide a list of ${vendor.terminalLinkExports('package URLs', 'https://github.com/package-url/purl-spec?tab=readme-ov-file#purl')} (PURLs) to fix, as either a comma separated value or as multiple flags,\n instead of querying the Socket API`,
4600
+ description: `Provide a list of ${vendor.terminalLinkExports('PURLs', 'https://github.com/package-url/purl-spec?tab=readme-ov-file#purl')} to compute fixes for, as either a comma separated value or as multiple flags,\n instead of querying the Socket API`,
4811
4601
  isMultiple: true,
4812
4602
  shortFlag: 'p'
4813
4603
  },
@@ -4869,25 +4659,16 @@ async function run$H(argv, importMeta, {
4869
4659
  json,
4870
4660
  markdown
4871
4661
  } = cli.flags;
4872
- let {
4873
- autoMerge,
4874
- rangeStyle,
4875
- test
4876
- } = cli.flags;
4877
4662
  const outputKind = utils.getOutputKind(json, markdown);
4878
- let [cwd = '.'] = cli.input;
4879
- // Note: path.resolve vs .join:
4880
- // If given path is absolute then cwd should not affect it.
4881
- cwd = path.resolve(process.cwd(), cwd);
4882
- if (autopilot) {
4883
- autoMerge = true;
4884
- test = true;
4663
+ let rangeStyle = cli.flags['rangeStyle'];
4664
+ if (!rangeStyle) {
4665
+ rangeStyle = 'preserve';
4885
4666
  }
4886
4667
  const wasValidInput = utils.checkCommandInput(outputKind, {
4887
- test: utils.RangeStyles.includes(cli.flags['rangeStyle']),
4668
+ test: utils.RangeStyles.includes(rangeStyle),
4888
4669
  message: `Expecting range style of ${arrays.joinOr(utils.RangeStyles)}`,
4889
4670
  pass: 'ok',
4890
- fail: 'missing'
4671
+ fail: 'invalid'
4891
4672
  });
4892
4673
  if (!wasValidInput) {
4893
4674
  return;
@@ -4896,20 +4677,30 @@ async function run$H(argv, importMeta, {
4896
4677
  logger.logger.log(DRY_RUN_NOT_SAVING);
4897
4678
  return;
4898
4679
  }
4899
- let purls = Array.isArray(cli.flags['purl']) ? cli.flags['purl'] : [];
4900
- purls = purls.flatMap(p => p.split(/, */));
4901
- if (!['caret', 'gt', 'gte', 'lt', 'lte', 'pin', 'preserve', 'tilde'].includes(rangeStyle)) {
4902
- rangeStyle = 'preserve';
4680
+ let [cwd = '.'] = cli.input;
4681
+ // Note: path.resolve vs .join:
4682
+ // If given path is absolute then cwd should not affect it.
4683
+ cwd = path.resolve(process.cwd(), cwd);
4684
+ let autoMerge = Boolean(cli.flags['autoMerge']);
4685
+ let test = Boolean(cli.flags['test']);
4686
+ if (autopilot) {
4687
+ autoMerge = true;
4688
+ test = true;
4903
4689
  }
4690
+ const ghsas = utils.cmdFlagValueToArray(cli.flags['ghsa']);
4691
+ const limit = (cli.flags['limit'] ? parseInt(String(cli.flags['limit'] || ''), 10) : Infinity) || Infinity;
4692
+ const purls = utils.cmdFlagValueToArray(cli.flags['purl']);
4693
+ const testScript = String(cli.flags['testScript'] || 'test');
4904
4694
  await handleFix({
4905
- autoMerge: Boolean(autoMerge),
4695
+ autoMerge,
4906
4696
  cwd,
4907
- limit: (cli.flags['limit'] ? parseInt(String(cli.flags['limit'] || ''), 10) : Infinity) || Infinity,
4697
+ ghsas,
4698
+ limit,
4908
4699
  outputKind,
4909
4700
  purls,
4910
- rangeStyle: rangeStyle,
4911
- test: Boolean(test),
4912
- testScript: String(cli.flags['testScript'] || 'test')
4701
+ rangeStyle,
4702
+ test,
4703
+ testScript
4913
4704
  });
4914
4705
  }
4915
4706
 
@@ -5425,14 +5216,14 @@ async function run$D(argv, importMeta, {
5425
5216
  }
5426
5217
 
5427
5218
  const {
5428
- NPM: NPM$7,
5219
+ NPM: NPM$6,
5429
5220
  NPX: NPX$1,
5430
5221
  PACKAGE_LOCK_JSON,
5431
- PNPM: PNPM$6,
5222
+ PNPM: PNPM$5,
5432
5223
  YARN,
5433
5224
  YARN_LOCK
5434
5225
  } = constants;
5435
- const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$7, PNPM$6, 'ts', 'tsx', 'typescript']);
5226
+ const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$6, PNPM$5, 'ts', 'tsx', 'typescript']);
5436
5227
  function argvToArray(argv) {
5437
5228
  if (argv['help']) {
5438
5229
  return ['--help'];
@@ -5474,7 +5265,7 @@ async function runCdxgen(yargvWithYes) {
5474
5265
  const yesArgs = yes ? ['--yes'] : [];
5475
5266
  if (yargv.type !== YARN && nodejsPlatformTypes.has(yargv.type) && fs$1.existsSync(`./${YARN_LOCK}`)) {
5476
5267
  if (fs$1.existsSync(`./${PACKAGE_LOCK_JSON}`)) {
5477
- yargv.type = NPM$7;
5268
+ yargv.type = NPM$6;
5478
5269
  } else {
5479
5270
  // Use synp to create a package-lock.json from the yarn.lock,
5480
5271
  // based on the node_modules folder, for a more accurate SBOM.
@@ -5482,7 +5273,7 @@ async function runCdxgen(yargvWithYes) {
5482
5273
  await shadowNpmBin(NPX$1, [...yesArgs,
5483
5274
  // Lazily access constants.ENV.INLINED_SYNP_VERSION.
5484
5275
  `synp@${constants.ENV.INLINED_SYNP_VERSION}`, '--source-file', `./${YARN_LOCK}`]);
5485
- yargv.type = NPM$7;
5276
+ yargv.type = NPM$6;
5486
5277
  cleanupPackageLock = true;
5487
5278
  } catch {}
5488
5279
  }
@@ -5548,7 +5339,7 @@ const arrayToLower = arg => arg.map(toLower);
5548
5339
  // sable. [boolean] [default: true]
5549
5340
  // --evidence Generate SBOM with evidence for supported languages. [boolean] [default: false]
5550
5341
  // --spec-version CycloneDX Specification version to use. Defaults to 1.6
5551
- // [number] [choices: 1.4, 1.5, 1.6] [default: 1.6]
5342
+ // [number] [choices: 1.4, 1.5, 1.6, 1.7] [default: 1.6]
5552
5343
  // --filter Filter components containing this word in purl or component.properties.value. Multiple va
5553
5344
  // lues allowed. [array]
5554
5345
  // --only Include components only containing this word in purl. Useful to generate BOM with first p
@@ -7190,12 +6981,12 @@ async function run$s(argv, importMeta, {
7190
6981
  }
7191
6982
 
7192
6983
  const {
7193
- BUN: BUN$4,
7194
- NPM: NPM$6,
7195
- PNPM: PNPM$5,
7196
- VLT: VLT$5,
7197
- YARN_BERRY: YARN_BERRY$4,
7198
- YARN_CLASSIC: YARN_CLASSIC$5
6984
+ BUN: BUN$3,
6985
+ NPM: NPM$5,
6986
+ PNPM: PNPM$4,
6987
+ VLT: VLT$4,
6988
+ YARN_BERRY: YARN_BERRY$3,
6989
+ YARN_CLASSIC: YARN_CLASSIC$3
7199
6990
  } = constants;
7200
6991
  function matchLsCmdViewHumanStdout(stdout, name) {
7201
6992
  return stdout.includes(` ${name}@`);
@@ -7203,7 +6994,7 @@ function matchLsCmdViewHumanStdout(stdout, name) {
7203
6994
  function matchQueryCmdStdout(stdout, name) {
7204
6995
  return stdout.includes(`"${name}"`);
7205
6996
  }
7206
- const depsIncludesByAgent = new Map([[BUN$4, matchLsCmdViewHumanStdout], [NPM$6, matchQueryCmdStdout], [PNPM$5, matchQueryCmdStdout], [VLT$5, matchQueryCmdStdout], [YARN_BERRY$4, matchLsCmdViewHumanStdout], [YARN_CLASSIC$5, matchLsCmdViewHumanStdout]]);
6997
+ const depsIncludesByAgent = new Map([[BUN$3, matchLsCmdViewHumanStdout], [NPM$5, matchQueryCmdStdout], [PNPM$4, matchQueryCmdStdout], [VLT$4, matchQueryCmdStdout], [YARN_BERRY$3, matchLsCmdViewHumanStdout], [YARN_CLASSIC$3, matchLsCmdViewHumanStdout]]);
7207
6998
 
7208
6999
  function getDependencyEntries(pkgEnvDetails) {
7209
7000
  const {
@@ -7229,72 +7020,6 @@ function getDependencyEntries(pkgEnvDetails) {
7229
7020
  }) => o);
7230
7021
  }
7231
7022
 
7232
- const {
7233
- BUN: BUN$3,
7234
- NPM: NPM$5,
7235
- OVERRIDES: OVERRIDES$1,
7236
- PNPM: PNPM$4,
7237
- RESOLUTIONS: RESOLUTIONS$1,
7238
- VLT: VLT$4,
7239
- YARN_BERRY: YARN_BERRY$3,
7240
- YARN_CLASSIC: YARN_CLASSIC$4
7241
- } = constants;
7242
- function getOverridesDataBun(pkgEnvDetails) {
7243
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7244
- return {
7245
- type: YARN_BERRY$3,
7246
- overrides
7247
- };
7248
- }
7249
-
7250
- // npm overrides documentation:
7251
- // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
7252
- function getOverridesDataNpm(pkgEnvDetails) {
7253
- const overrides = pkgEnvDetails.editablePkgJson.content?.[OVERRIDES$1] ?? {};
7254
- return {
7255
- type: NPM$5,
7256
- overrides
7257
- };
7258
- }
7259
-
7260
- // pnpm overrides documentation:
7261
- // https://pnpm.io/package_json#pnpmoverrides
7262
- function getOverridesDataPnpm(pkgEnvDetails) {
7263
- const overrides = pkgEnvDetails.editablePkgJson.content?.[PNPM$4]?.[OVERRIDES$1] ?? {};
7264
- return {
7265
- type: PNPM$4,
7266
- overrides
7267
- };
7268
- }
7269
- function getOverridesDataVlt(pkgEnvDetails) {
7270
- const overrides = pkgEnvDetails.editablePkgJson.content?.[OVERRIDES$1] ?? {};
7271
- return {
7272
- type: VLT$4,
7273
- overrides
7274
- };
7275
- }
7276
-
7277
- // Yarn resolutions documentation:
7278
- // https://yarnpkg.com/configuration/manifest#resolutions
7279
- function getOverridesDataYarn(pkgEnvDetails) {
7280
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7281
- return {
7282
- type: YARN_BERRY$3,
7283
- overrides
7284
- };
7285
- }
7286
-
7287
- // Yarn resolutions documentation:
7288
- // https://classic.yarnpkg.com/en/docs/selective-version-resolutions
7289
- function getOverridesDataYarnClassic(pkgEnvDetails) {
7290
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7291
- return {
7292
- type: YARN_CLASSIC$4,
7293
- overrides
7294
- };
7295
- }
7296
- const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$5, getOverridesDataNpm], [PNPM$4, getOverridesDataPnpm], [VLT$4, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataYarnClassic]]);
7297
-
7298
7023
  const {
7299
7024
  BUN: BUN$2,
7300
7025
  LOCK_EXT,
@@ -7302,7 +7027,7 @@ const {
7302
7027
  PNPM: PNPM$3,
7303
7028
  VLT: VLT$3,
7304
7029
  YARN_BERRY: YARN_BERRY$2,
7305
- YARN_CLASSIC: YARN_CLASSIC$3
7030
+ YARN_CLASSIC: YARN_CLASSIC$2
7306
7031
  } = constants;
7307
7032
  function includesNpm(lockSrc, name) {
7308
7033
  // Detects the package name in the following cases:
@@ -7344,7 +7069,7 @@ function includesYarn(lockSrc, name) {
7344
7069
  // , name@
7345
7070
  `(?<=(?:^\\s*|,\\s*)"?)${escapedName}(?=@)`, 'm').test(lockSrc);
7346
7071
  }
7347
- const lockfileIncludesByAgent = new Map([[BUN$2, includesBun], [NPM$4, includesNpm], [PNPM$3, includesPnpm], [VLT$3, includesVlt], [YARN_BERRY$2, includesYarn], [YARN_CLASSIC$3, includesYarn]]);
7072
+ const lockfileIncludesByAgent = new Map([[BUN$2, includesBun], [NPM$4, includesNpm], [PNPM$3, includesPnpm], [VLT$3, includesVlt], [YARN_BERRY$2, includesYarn], [YARN_CLASSIC$2, includesYarn]]);
7348
7073
 
7349
7074
  const {
7350
7075
  BUN: BUN$1,
@@ -7352,7 +7077,7 @@ const {
7352
7077
  PNPM: PNPM$2,
7353
7078
  VLT: VLT$2,
7354
7079
  YARN_BERRY: YARN_BERRY$1,
7355
- YARN_CLASSIC: YARN_CLASSIC$2
7080
+ YARN_CLASSIC: YARN_CLASSIC$1
7356
7081
  } = constants;
7357
7082
  function cleanupQueryStdout(stdout) {
7358
7083
  if (stdout === '') {
@@ -7481,7 +7206,7 @@ async function lsYarnClassic(pkgEnvDetails, cwd) {
7481
7206
  } catch {}
7482
7207
  return '';
7483
7208
  }
7484
- const lsByAgent = new Map([[BUN$1, lsBun], [NPM$3, lsNpm], [PNPM$2, lsPnpm], [VLT$2, lsVlt], [YARN_BERRY$1, lsYarnBerry], [YARN_CLASSIC$2, lsYarnClassic]]);
7209
+ const lsByAgent = new Map([[BUN$1, lsBun], [NPM$3, lsNpm], [PNPM$2, lsPnpm], [VLT$2, lsVlt], [YARN_BERRY$1, lsYarnBerry], [YARN_CLASSIC$1, lsYarnClassic]]);
7485
7210
 
7486
7211
  const CMD_NAME = 'socket optimize';
7487
7212
 
@@ -7493,7 +7218,7 @@ const {
7493
7218
  RESOLUTIONS,
7494
7219
  VLT: VLT$1,
7495
7220
  YARN_BERRY,
7496
- YARN_CLASSIC: YARN_CLASSIC$1
7221
+ YARN_CLASSIC
7497
7222
  } = constants;
7498
7223
  const depFields = ['dependencies', 'devDependencies', 'peerDependencies', 'peerDependenciesMeta', 'optionalDependencies', 'bundleDependencies'];
7499
7224
  function getEntryIndexes(entries, keys) {
@@ -7595,12 +7320,11 @@ function updateResolutionsField(pkgEnvDetails, overrides) {
7595
7320
  function updatePnpmField(pkgEnvDetails, overrides) {
7596
7321
  updatePkgJsonField(pkgEnvDetails.editablePkgJson, PNPM$1, overrides);
7597
7322
  }
7598
- const updateManifestByAgent = new Map([[BUN, updateResolutionsField], [NPM$2, updateOverridesField], [PNPM$1, updatePnpmField], [VLT$1, updateOverridesField], [YARN_BERRY, updateResolutionsField], [YARN_CLASSIC$1, updateResolutionsField]]);
7323
+ const updateManifestByAgent = new Map([[BUN, updateResolutionsField], [NPM$2, updateOverridesField], [PNPM$1, updatePnpmField], [VLT$1, updateOverridesField], [YARN_BERRY, updateResolutionsField], [YARN_CLASSIC, updateResolutionsField]]);
7599
7324
 
7600
7325
  const {
7601
7326
  NPM: NPM$1,
7602
- PNPM,
7603
- YARN_CLASSIC
7327
+ PNPM
7604
7328
  } = constants;
7605
7329
  const manifestNpmOverrides = registry.getManifestData(NPM$1);
7606
7330
  async function addOverrides(pkgEnvDetails, pkgPath, options) {
@@ -7640,9 +7364,9 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
7640
7364
  }
7641
7365
  const overridesDataObjects = [];
7642
7366
  if (isWorkspace || pkgEnvDetails.editablePkgJson.content['private']) {
7643
- overridesDataObjects.push(overridesDataByAgent.get(agent)(pkgEnvDetails));
7367
+ overridesDataObjects.push(getOverridesData(pkgEnvDetails));
7644
7368
  } else {
7645
- overridesDataObjects.push(overridesDataByAgent.get(NPM$1)(pkgEnvDetails), overridesDataByAgent.get(YARN_CLASSIC)(pkgEnvDetails));
7369
+ overridesDataObjects.push(getOverridesDataNpm(pkgEnvDetails), getOverridesDataYarnClassic(pkgEnvDetails));
7646
7370
  }
7647
7371
  spinner?.setText(`Adding overrides to ${workspace}...`);
7648
7372
  const depAliasMap = new Map();
@@ -9979,7 +9703,7 @@ async function outputListRepos(result, outputKind, page, nextPage, sort, perPage
9979
9703
  logger.logger.log(vendor.srcExports(options, result.data.results));
9980
9704
  if (nextPage) {
9981
9705
  logger.logger.info(`This is page ${page}. Server indicated there are more results available on page ${nextPage}...`);
9982
- logger.logger.info(`(Hint: you can use \`socket repos list --page ${nextPage}\`)`);
9706
+ logger.logger.info(`(Hint: you can use \`socket repository list --page ${nextPage}\`)`);
9983
9707
  } else if (perPage === Infinity) {
9984
9708
  logger.logger.info(`This should be the entire list available on the server.`);
9985
9709
  } else {
@@ -10768,6 +10492,14 @@ async function run$c(argv, importMeta, {
10768
10492
  if (hasApiToken && !dryRun && interactive) {
10769
10493
  if (!orgSlug) {
10770
10494
  const suggestion = await utils.suggestOrgSlug();
10495
+ if (suggestion === undefined) {
10496
+ await outputCreateNewScan({
10497
+ ok: false,
10498
+ message: 'Canceled by user',
10499
+ cause: 'Org selector was canceled by user'
10500
+ }, outputKind, false);
10501
+ return;
10502
+ }
10771
10503
  if (suggestion) {
10772
10504
  orgSlug = suggestion;
10773
10505
  }
@@ -11895,6 +11627,19 @@ async function getRepoBranchTree({
11895
11627
  };
11896
11628
  }
11897
11629
 
11630
+ async function outputScanGithub(result, outputKind) {
11631
+ if (outputKind === 'json') {
11632
+ logger.logger.log(utils.serializeResultJson(result));
11633
+ return;
11634
+ }
11635
+ if (!result.ok) {
11636
+ logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
11637
+ return;
11638
+ }
11639
+ logger.logger.log('');
11640
+ logger.logger.success('Finished!');
11641
+ }
11642
+
11898
11643
  async function handleCreateGithubScan({
11899
11644
  all,
11900
11645
  githubApiUrl,
@@ -11915,16 +11660,7 @@ async function handleCreateGithubScan({
11915
11660
  outputKind,
11916
11661
  repos: String(repos || '')
11917
11662
  });
11918
- if (outputKind === 'json') {
11919
- logger.logger.log(utils.serializeResultJson(result));
11920
- return;
11921
- }
11922
- if (!result.ok) {
11923
- logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
11924
- return;
11925
- }
11926
- logger.logger.log('');
11927
- logger.logger.success('Finished!');
11663
+ await outputScanGithub(result, outputKind);
11928
11664
  }
11929
11665
 
11930
11666
  const {
@@ -12079,6 +11815,14 @@ async function run$9(argv, importMeta, {
12079
11815
  if (hasSocketApiToken && !dryRun && interactive) {
12080
11816
  if (!orgSlug) {
12081
11817
  const suggestion = await utils.suggestOrgSlug();
11818
+ if (suggestion === undefined) {
11819
+ await outputScanGithub({
11820
+ ok: false,
11821
+ message: 'Canceled by user',
11822
+ cause: 'Org selector was canceled by user'
11823
+ }, outputKind);
11824
+ return;
11825
+ }
12082
11826
  if (suggestion) {
12083
11827
  orgSlug = suggestion;
12084
11828
  }
@@ -12540,30 +12284,17 @@ const {
12540
12284
  DOT_SOCKET_DOT_FACTS_JSON
12541
12285
  } = constants;
12542
12286
  async function scanReachability(argv, cwd) {
12543
- try {
12544
- const result = await spawn.spawn(constants.execPath, [
12545
- // Lazily access constants.nodeNoWarningsFlags.
12546
- ...constants.nodeNoWarningsFlags,
12547
- // Lazily access constants.coanaBinPath.
12548
- constants.coanaBinPath, 'run', cwd, '--output-dir', cwd, '--socket-mode', DOT_SOCKET_DOT_FACTS_JSON, '--disable-report-submission', ...argv], {
12549
- cwd,
12550
- env: {
12551
- ...process.env,
12552
- SOCKET_CLI_API_TOKEN: utils.getDefaultToken()
12553
- }
12554
- });
12555
- return {
12556
- ok: true,
12557
- data: result.stdout.trim()
12558
- };
12559
- } catch (e) {
12560
- const message = e?.stdout ?? e?.message;
12561
- return {
12562
- ok: false,
12563
- data: e,
12564
- message
12565
- };
12566
- }
12287
+ // Lazily access constants.spinner.
12288
+ const {
12289
+ spinner
12290
+ } = constants;
12291
+ spinner.start();
12292
+ const result = await utils.spawnCoana(['run', cwd, '--output-dir', cwd, '--socket-mode', DOT_SOCKET_DOT_FACTS_JSON, '--disable-report-submission', ...argv], {
12293
+ cwd,
12294
+ spinner
12295
+ });
12296
+ spinner.stop();
12297
+ return result;
12567
12298
  }
12568
12299
 
12569
12300
  async function handleScanReach(argv, cwd, outputKind) {
@@ -14393,5 +14124,5 @@ void (async () => {
14393
14124
  await utils.captureException(e);
14394
14125
  }
14395
14126
  })();
14396
- //# debugId=13304ad0-96c0-432a-b125-801db7775ab7
14127
+ //# debugId=214e9941-f13a-4601-a726-83de349925db
14397
14128
  //# sourceMappingURL=cli.js.map