@socketsecurity/cli-with-sentry 1.8.2 → 1.8.4

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/CHANGELOG.md CHANGED
@@ -4,10 +4,22 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.8.4](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.4) - 2026-10-16
8
+
9
+ ### Changed
10
+ - `socket fix` now exits with code 5 when it computed fixes it could not apply, matching the Coana CLI. Automation can tell this apart from a failed run, which still exits with 1. The `--output-file` JSON lists the unapplied fixes under `notApplied`.
11
+ - Updated the Coana CLI to v `15.12.9`.
12
+
13
+ ## [1.8.3](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.3) - 2026-10-15
14
+
15
+ ### Changed
16
+ - Updated the Coana CLI to v `15.12.8`.
17
+
7
18
  ## [1.8.2](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.2) - 2026-10-13
8
19
 
9
20
  ### Fixed
10
21
  - Reachability scans in pnpm and yarn projects no longer print a 403 from the Socket API when run with a repository-scoped token. The safety check that runs before Coana launches now uses Socket's public token and only looks up the Coana package itself.
22
+ - `--dynamic-sbom-inference` no longer skips an independent Maven, Gradle or sbt build that shares a directory with a module of another build: only build files another build actually uses count as covered.
11
23
 
12
24
  ## [1.8.1](https://github.com/SocketDev/socket-cli/releases/tag/v1.8.1) - 2026-10-12
13
25
 
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Socket CLI
2
2
 
3
3
  [![Socket Badge](https://socket.dev/api/badge/npm/package/socket)](https://socket.dev/npm/package/socket)
4
- [![Follow @SocketSecurity](https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.2/assets/fleet/badge-follow-x.svg)](https://twitter.com/SocketSecurity)
5
- [![Follow @socket.dev on Bluesky](https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.2/assets/fleet/badge-follow-bluesky.svg)](https://bsky.app/profile/socket.dev)
4
+ [![Follow @SocketSecurity](https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.4/assets/fleet/badge-follow-x.svg)](https://twitter.com/SocketSecurity)
5
+ [![Follow @socket.dev on Bluesky](https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.4/assets/fleet/badge-follow-bluesky.svg)](https://bsky.app/profile/socket.dev)
6
6
 
7
7
  CLI for [Socket.dev](https://socket.dev) — scan dependencies, audit packages, apply security patches, and gate installs from your terminal or CI. This is the 1.x line of the published `socket` package on npm.
8
8
 
@@ -171,8 +171,8 @@ MIT
171
171
  <br/>
172
172
  <div align="center">
173
173
  <picture>
174
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.2/assets/fleet/socket-combomark-dark.svg">
175
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.2/assets/fleet/socket-combomark-light.svg">
176
- <img width="324" height="104" alt="Socket" src="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.2/assets/fleet/socket-combomark-light.svg">
174
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.4/assets/fleet/socket-combomark-dark.svg">
175
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.4/assets/fleet/socket-combomark-light.svg">
176
+ <img width="324" height="104" alt="Socket" src="https://raw.githubusercontent.com/SocketDev/socket-cli/v1.8.4/assets/fleet/socket-combomark-light.svg">
177
177
  </picture>
178
178
  </div>
package/dist/cli.js CHANGED
@@ -2126,6 +2126,28 @@ function withoutDisabledFlags(sockJson) {
2126
2126
  }
2127
2127
  };
2128
2128
  }
2129
+
2130
+ // Gradle reports a project's build file even when absent, which covers
2131
+ // nothing. A sibling outside the build root is independently locatable.
2132
+ async function addCoveredBuildFiles(covered, buildRoot, projects) {
2133
+ const realBuildRoot = await utils.realpathOrResolved(buildRoot);
2134
+ const files = await Promise.all(projects.flatMap(project => project.manifestFiles ?? []).map(async ({
2135
+ file
2136
+ }) => {
2137
+ const resolved = path.resolve(buildRoot, file);
2138
+ return path.join(await utils.realpathOrResolved(path.dirname(resolved)), path.basename(resolved));
2139
+ }));
2140
+ for (const file of files) {
2141
+ if (file.startsWith(`${realBuildRoot}${path.sep}`) && fs$1.existsSync(file)) {
2142
+ covered.add(file);
2143
+ }
2144
+ }
2145
+ }
2146
+
2147
+ // `dir` must be realpath-resolved, as findBuildToolCandidates returns it.
2148
+ function isBuildRootCovered(covered, tool, dir) {
2149
+ return MARKERS_BY_TOOL[tool].some(marker => covered.has(path.join(dir, marker)));
2150
+ }
2129
2151
  function sortByDepthThenPath(dirs, cwd) {
2130
2152
  return [...dirs].sort((a, b) => {
2131
2153
  const relA = path.relative(cwd, a);
@@ -2139,9 +2161,8 @@ function sortByDepthThenPath(dirs, cwd) {
2139
2161
  });
2140
2162
  }
2141
2163
 
2142
- // Depth-sorted (root-most first) so the caller, using each build root's
2143
- // `subprojectDir` facts, visits a reactor root before its own members and can
2144
- // skip subprojects a parent root already covers.
2164
+ // Depth-sorted (root-most first) so the caller visits a reactor root before
2165
+ // its own members and can skip those whose build files it already covers.
2145
2166
  async function findBuildToolCandidates({
2146
2167
  cwd,
2147
2168
  excludePaths,
@@ -3505,6 +3526,7 @@ async function runManifestScript(tool, opts) {
3505
3526
  async function enumerateWorkspaces$1(tool, opts) {
3506
3527
  const result = await (tool === 'gradle' ? enumerateGradleWorkspaces(opts) : tool === 'sbt' ? enumerateSbtWorkspaces(opts) : enumerateMavenWorkspaces(opts));
3507
3528
  return {
3529
+ buildRoot: result.buildRoot,
3508
3530
  code: result.code,
3509
3531
  projects: result.facts.projects ?? [],
3510
3532
  stderr: result.stderr,
@@ -3835,12 +3857,12 @@ async function runEcosystemCandidates({
3835
3857
  withFiles
3836
3858
  }) {
3837
3859
  const outcomes = [];
3860
+ const covered = new Set();
3838
3861
  for (const [ecosystem, dirs] of candidatesByTool) {
3839
- const covered = new Set();
3840
3862
  const disabledRoots = [];
3841
3863
  for (let dirIndex = 0; dirIndex < dirs.length; dirIndex += 1) {
3842
3864
  const dir = dirs[dirIndex];
3843
- if (covered.has(dir)) {
3865
+ if (isBuildRootCovered(covered, ecosystem, dir)) {
3844
3866
  outcomes.push({
3845
3867
  dir,
3846
3868
  ecosystem,
@@ -3924,28 +3946,10 @@ async function runEcosystemCandidates({
3924
3946
  });
3925
3947
  continue;
3926
3948
  }
3927
- covered.add(dir);
3949
+
3928
3950
  // `-f`/`-p` can root the reactor away from `dir`.
3929
3951
  // eslint-disable-next-line no-await-in-loop
3930
- const buildRoot = await utils.realpathOrResolved(path.dirname(result.factsPath));
3931
- // eslint-disable-next-line no-await-in-loop
3932
- const resolvedSubprojectDirs = await Promise.all(result.projects.map(project => utils.realpathOrResolved(path.resolve(buildRoot, project.subprojectDir))));
3933
- for (const subprojectDir of resolvedSubprojectDirs) {
3934
- // Only a genuinely nested member (a descendant of this reactor's own
3935
- // directory) has no independent existence worth its own standalone
3936
- // analysis. A subprojectDir that escapes this reactor's own tree (a
3937
- // sibling, e.g. Maven's `<module>../shared-lib</module>` or Gradle's
3938
- // relocated projectDir) is independently locatable and potentially
3939
- // independently consumed or published - its own un-mediated
3940
- // resolution (e.g. a dependency version this reactor's own
3941
- // dependency management happens to override) is a distinct,
3942
- // meaningful data point, not a redundant one. Never suppress its own
3943
- // build-root invocation, regardless of which reactor(s) also
3944
- // incorporate it or the order candidates happen to be discovered in.
3945
- if (subprojectDir === buildRoot || subprojectDir.startsWith(`${buildRoot}${path.sep}`)) {
3946
- covered.add(subprojectDir);
3947
- }
3948
- }
3952
+ await addCoveredBuildFiles(covered, path.dirname(result.factsPath), result.projects);
3949
3953
  outcomes.push({
3950
3954
  dir,
3951
3955
  ecosystem,
@@ -3957,17 +3961,8 @@ async function runEcosystemCandidates({
3957
3961
  return outcomes;
3958
3962
  }
3959
3963
 
3960
- // Generates one Socket facts file per independent gradle/sbt/maven build
3961
- // root under `cwd`. Coverage is tracked per ecosystem via the facts SBOM's
3962
- // own projects[].subprojectDir, not by pruning the whole discovered subtree,
3963
- // so an unrelated nested project a reactor doesn't declare still gets its
3964
- // own invocation - and only a properly nested subprojectDir counts as
3965
- // coverage at all; one that escapes its declaring reactor's own directory
3966
- // still gets its own independent invocation too (see the covered.add call
3967
- // below). Fail-closed per ecosystem, not globally: a root whose
3968
- // workspace layout can't be determined aborts only that ecosystem's own
3969
- // remaining walk (marking its untried candidates 'aborted'), since coverage
3970
- // is tracked per ecosystem and an unrelated one has nothing to lose from it.
3964
+ // A failed root aborts only its own ecosystem's remaining walk: the build
3965
+ // files it would have covered are all its own tool's.
3971
3966
  async function generateRecursiveManifests({
3972
3967
  cwd,
3973
3968
  excludePaths,
@@ -9103,6 +9098,7 @@ function readWrittenFiles(outputFile) {
9103
9098
  return Array.isArray(files) && files.every(f => typeof f === 'string') ? new Set(files) : undefined;
9104
9099
  }
9105
9100
  // Coana exits with this code after writing an --output-file that lists computed fixes it left unapplied.
9101
+ // Local mode exits with it too, so automation can tell unapplied fixes from a failed run.
9106
9102
  const COANA_FIXES_NOT_APPLIED_EXIT_CODE = 5;
9107
9103
  function isFixesNotAppliedExit(result) {
9108
9104
  return !result.ok && result.data?.code === COANA_FIXES_NOT_APPLIED_EXIT_CODE;
@@ -9336,6 +9332,7 @@ async function coanaFixWithFacts(fixConfig, factsSlot) {
9336
9332
  if (!fixCResult.ok || notApplied.length) {
9337
9333
  return {
9338
9334
  ok: false,
9335
+ code: COANA_FIXES_NOT_APPLIED_EXIT_CODE,
9339
9336
  message: fixesResultJson?.type === 'no-fixes-applied' ? 'No computed fixes were applied' : 'Some computed fixes were not applied',
9340
9337
  cause: formatNotAppliedFixes(notApplied),
9341
9338
  data: {
@@ -12987,8 +12984,9 @@ const config$d = {
12987
12984
  (pom.xml.socket.facts.json, gradle.socket.facts.json, or
12988
12985
  sbt.socket.facts.json, so builds sharing a directory never overwrite each
12989
12986
  other),
12990
- skipping subproject/reactor-module directories a parent build root already
12991
- covers. Unlike \`socket manifest auto\`, this looks beyond CWD itself.
12987
+ skipping build roots whose build file a parent build already reports for
12988
+ one of its subprojects. Unlike \`socket manifest auto\`, this looks beyond
12989
+ CWD itself.
12992
12990
 
12993
12991
  Options
12994
12992
  ${utils.getFlagListOutput(config.flags)}
@@ -14742,7 +14740,13 @@ async function enumerateWorkspaces({
14742
14740
  logger.logger.fail(`The ${ecosystem} build produced no workspace records (exit code ${result.code}); every build reports at least its own root project, so the enumeration task did not run.`);
14743
14741
  return;
14744
14742
  }
14743
+ if (!result.buildRoot) {
14744
+ process.exitCode = 1;
14745
+ logger.logger.fail(`The ${ecosystem} build did not report its build root, so its projects' paths cannot be located.`);
14746
+ return;
14747
+ }
14745
14748
  return {
14749
+ buildRoot: result.buildRoot,
14746
14750
  projects: result.projects
14747
14751
  };
14748
14752
  }
@@ -14885,20 +14889,11 @@ async function discoverBuildRoots({
14885
14889
  };
14886
14890
  }
14887
14891
 
14888
- // Enumerates one build root's declared workspace members (see
14889
- // enumerate-workspaces.mts) and folds them into `coveredByEcosystem`, so a
14890
- // later candidate matching one is recognized as a reactor member rather than
14891
- // independent - only a properly nested subprojectDir counts as coverage at
14892
- // all; one that escapes this candidate's own directory still gets its own
14893
- // entry (see the set.add call below). Called per-candidate right after its
14894
- // own prompt, not as a bulk pass, so the build invocation never blocks
14895
- // candidates that don't need it. A disabled candidate is skipped (no point
14896
- // invoking an off build tool); otherwise this fails closed, same reasoning
14897
- // as generateRecursiveManifests - if enumeration fails there's no way to
14898
- // tell covered from independent, so the caller aborts rather than guess.
14892
+ // Fails closed: without the members' build files, covered and independent
14893
+ // candidates can't be told apart.
14899
14894
  async function markWorkspaceCoverage({
14900
14895
  candidate,
14901
- coveredByEcosystem,
14896
+ covered,
14902
14897
  cwd,
14903
14898
  excludePaths,
14904
14899
  rootSockJson
@@ -14936,21 +14931,7 @@ async function markWorkspaceCoverage({
14936
14931
  message: `Could not determine ${candidate.ecosystem} workspace layout for ${relDir}; aborting rather than risk misclassifying its members.`
14937
14932
  };
14938
14933
  }
14939
- const set = coveredByEcosystem.get(candidate.ecosystem) ?? new Set();
14940
- set.add(candidate.dir);
14941
- const resolvedSubprojectDirs = await Promise.all(enumResult.projects.map(project => utils.realpathOrResolved(path.resolve(candidate.dir, project.subprojectDir))));
14942
- for (const subprojectDir of resolvedSubprojectDirs) {
14943
- // Only a genuinely nested member (a descendant of this candidate's own
14944
- // directory) should be skipped as covered by it. A subprojectDir that
14945
- // escapes this candidate's own tree (a sibling, e.g. Maven's
14946
- // `<module>../shared-lib</module>` or Gradle's relocated projectDir) is
14947
- // independently locatable and worth its own socket.json entry - never
14948
- // mark it covered, regardless of which candidate(s) also incorporate it.
14949
- if (subprojectDir.startsWith(`${candidate.dir}${path.sep}`)) {
14950
- set.add(subprojectDir);
14951
- }
14952
- }
14953
- coveredByEcosystem.set(candidate.ecosystem, set);
14934
+ await addCoveredBuildFiles(covered, enumResult.buildRoot, enumResult.projects);
14954
14935
  return {
14955
14936
  ok: true,
14956
14937
  data: undefined
@@ -15460,7 +15441,7 @@ async function setupRecursiveManifestConfig(cwd, defaultOnReadError, excludePath
15460
15441
  logger.logger.log('For each one, choose to configure it or leave it as-is. To disable one,');
15461
15442
  logger.logger.log('re-run with --exclude-paths instead.');
15462
15443
  logger.logger.log('');
15463
- const coveredByEcosystem = new Map();
15444
+ const covered = new Set();
15464
15445
  // cwd never appears in `included`, but a reactor root often sits exactly
15465
15446
  // at cwd - seed coverage from it first so its declared members still get
15466
15447
  // recognized.
@@ -15471,7 +15452,7 @@ async function setupRecursiveManifestConfig(cwd, defaultOnReadError, excludePath
15471
15452
  dir: realCwd,
15472
15453
  ecosystem
15473
15454
  },
15474
- coveredByEcosystem,
15455
+ covered,
15475
15456
  cwd: realCwd,
15476
15457
  excludePaths,
15477
15458
  rootSockJson
@@ -15489,8 +15470,7 @@ async function setupRecursiveManifestConfig(cwd, defaultOnReadError, excludePath
15489
15470
  };
15490
15471
  const orderedIncluded = sortCandidatesForDisplay(included, realCwd);
15491
15472
  for (const candidate of orderedIncluded) {
15492
- const covered = coveredByEcosystem.get(candidate.ecosystem);
15493
- if (covered?.has(candidate.dir)) {
15473
+ if (isBuildRootCovered(covered, candidate.ecosystem, candidate.dir)) {
15494
15474
  counts.covered += 1;
15495
15475
  continue;
15496
15476
  }
@@ -15527,7 +15507,7 @@ async function setupRecursiveManifestConfig(cwd, defaultOnReadError, excludePath
15527
15507
  // eslint-disable-next-line no-await-in-loop
15528
15508
  const coverageResult = await markWorkspaceCoverage({
15529
15509
  candidate,
15530
- coveredByEcosystem,
15510
+ covered,
15531
15511
  cwd: realCwd,
15532
15512
  excludePaths,
15533
15513
  rootSockJson
@@ -24560,5 +24540,5 @@ process.on('unhandledRejection', async (reason, promise) => {
24560
24540
  // eslint-disable-next-line n/no-process-exit
24561
24541
  process.exit(1);
24562
24542
  });
24563
- //# debugId=e5b43908-d002-4c63-b2f7-4c7336aacdb4
24543
+ //# debugId=f7aeb17e-13e2-4a73-b5ed-da37ea72d476
24564
24544
  //# sourceMappingURL=cli.js.map