@socketsecurity/cli 1.1.101 → 1.1.151

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 (201) hide show
  1. package/CHANGELOG.md +277 -1
  2. package/README.md +9 -0
  3. package/bin/cli.js +33 -1
  4. package/dist/cli.js +9914 -5001
  5. package/dist/cli.js.map +1 -1
  6. package/dist/constants.js +8 -6
  7. package/dist/constants.js.map +1 -1
  8. package/dist/init.gradle +73 -0
  9. package/dist/manifest-scripts/maven-extension/coana-maven-extension.jar +0 -0
  10. package/dist/manifest-scripts/socket-facts.init.gradle +581 -0
  11. package/dist/manifest-scripts/socket-facts.plugin.scala +544 -0
  12. package/dist/shadow-npm-bin2.js +6 -6
  13. package/dist/shadow-npm-bin2.js.map +1 -1
  14. package/dist/shadow-npm-inject.js +10 -10
  15. package/dist/shadow-npm-inject.js.map +1 -1
  16. package/dist/shadow-pnpm-bin2.js +13 -13
  17. package/dist/shadow-pnpm-bin2.js.map +1 -1
  18. package/dist/shadow-yarn-bin.js +3 -3
  19. package/dist/shadow-yarn-bin.js.map +1 -1
  20. package/dist/socket-completion.bash +0 -0
  21. package/dist/tsconfig.dts.tsbuildinfo +1 -1
  22. package/dist/types/commands/audit-log/output-audit-log.d.mts.map +1 -1
  23. package/dist/types/commands/ci/fetch-default-org-slug.d.mts.map +1 -1
  24. package/dist/types/commands/ci/handle-ci.d.mts.map +1 -1
  25. package/dist/types/commands/config/handle-config-get.d.mts.map +1 -1
  26. package/dist/types/commands/config/handle-config-set.d.mts.map +1 -1
  27. package/dist/types/commands/config/output-config-set.d.mts.map +1 -1
  28. package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
  29. package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
  30. package/dist/types/commands/fix/handle-fix.d.mts +1 -1
  31. package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
  32. package/dist/types/commands/fix/types.d.mts +1 -0
  33. package/dist/types/commands/fix/types.d.mts.map +1 -1
  34. package/dist/types/commands/manifest/bazel/bazel-cquery.d.mts +70 -0
  35. package/dist/types/commands/manifest/bazel/bazel-cquery.d.mts.map +1 -0
  36. package/dist/types/commands/manifest/bazel/bazel-pypi-discovery.d.mts +44 -0
  37. package/dist/types/commands/manifest/bazel/bazel-pypi-discovery.d.mts.map +1 -0
  38. package/dist/types/commands/manifest/bazel/bazel-pypi-parser.d.mts +46 -0
  39. package/dist/types/commands/manifest/bazel/bazel-pypi-parser.d.mts.map +1 -0
  40. package/dist/types/commands/manifest/bazel/bazel-query-runner.d.mts +66 -8
  41. package/dist/types/commands/manifest/bazel/bazel-query-runner.d.mts.map +1 -1
  42. package/dist/types/commands/manifest/bazel/bazel-repo-discovery.d.mts +69 -29
  43. package/dist/types/commands/manifest/bazel/bazel-repo-discovery.d.mts.map +1 -1
  44. package/dist/types/commands/manifest/bazel/bazel-workspace-walk.d.mts +18 -0
  45. package/dist/types/commands/manifest/bazel/bazel-workspace-walk.d.mts.map +1 -0
  46. package/dist/types/commands/manifest/bazel/cmd-manifest-bazel.d.mts +26 -0
  47. package/dist/types/commands/manifest/bazel/cmd-manifest-bazel.d.mts.map +1 -1
  48. package/dist/types/commands/manifest/bazel/extract_bazel_to_maven.d.mts +110 -7
  49. package/dist/types/commands/manifest/bazel/extract_bazel_to_maven.d.mts.map +1 -1
  50. package/dist/types/commands/manifest/bazel/extract_bazel_to_pypi.d.mts +20 -0
  51. package/dist/types/commands/manifest/bazel/extract_bazel_to_pypi.d.mts.map +1 -0
  52. package/dist/types/commands/manifest/cmd-manifest-auto.d.mts.map +1 -1
  53. package/dist/types/commands/manifest/cmd-manifest-gradle.d.mts.map +1 -1
  54. package/dist/types/commands/manifest/cmd-manifest-kotlin.d.mts.map +1 -1
  55. package/dist/types/commands/manifest/cmd-manifest-maven.d.mts +9 -0
  56. package/dist/types/commands/manifest/cmd-manifest-maven.d.mts.map +1 -0
  57. package/dist/types/commands/manifest/cmd-manifest-scala.d.mts.map +1 -1
  58. package/dist/types/commands/manifest/cmd-manifest.d.mts.map +1 -1
  59. package/dist/types/commands/manifest/convert-gradle-to-facts.d.mts +15 -0
  60. package/dist/types/commands/manifest/convert-gradle-to-facts.d.mts.map +1 -0
  61. package/dist/types/commands/manifest/convert-maven-to-facts.d.mts +15 -0
  62. package/dist/types/commands/manifest/convert-maven-to-facts.d.mts.map +1 -0
  63. package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts +19 -0
  64. package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts.map +1 -0
  65. package/dist/types/commands/manifest/convert_gradle_to_maven.d.mts +2 -1
  66. package/dist/types/commands/manifest/convert_gradle_to_maven.d.mts.map +1 -1
  67. package/dist/types/commands/manifest/detect-manifest-actions.d.mts +1 -0
  68. package/dist/types/commands/manifest/detect-manifest-actions.d.mts.map +1 -1
  69. package/dist/types/commands/manifest/generate_auto_manifest.d.mts +12 -1
  70. package/dist/types/commands/manifest/generate_auto_manifest.d.mts.map +1 -1
  71. package/dist/types/commands/manifest/parse-build-tool-opts.d.mts +9 -0
  72. package/dist/types/commands/manifest/parse-build-tool-opts.d.mts.map +1 -0
  73. package/dist/types/commands/manifest/run-manifest-facts.d.mts +24 -0
  74. package/dist/types/commands/manifest/run-manifest-facts.d.mts.map +1 -0
  75. package/dist/types/commands/manifest/scripts/assemble.d.mts +16 -0
  76. package/dist/types/commands/manifest/scripts/assemble.d.mts.map +1 -0
  77. package/dist/types/commands/manifest/scripts/build-tool.d.mts +3 -0
  78. package/dist/types/commands/manifest/scripts/build-tool.d.mts.map +1 -0
  79. package/dist/types/commands/manifest/scripts/facts.d.mts +46 -0
  80. package/dist/types/commands/manifest/scripts/facts.d.mts.map +1 -0
  81. package/dist/types/commands/manifest/scripts/records.d.mts +66 -0
  82. package/dist/types/commands/manifest/scripts/records.d.mts.map +1 -0
  83. package/dist/types/commands/manifest/scripts/resolution-report-gradle.d.mts +10 -0
  84. package/dist/types/commands/manifest/scripts/resolution-report-gradle.d.mts.map +1 -0
  85. package/dist/types/commands/manifest/scripts/resolution-report-ivy.d.mts +7 -0
  86. package/dist/types/commands/manifest/scripts/resolution-report-ivy.d.mts.map +1 -0
  87. package/dist/types/commands/manifest/scripts/resolution-report-maven.d.mts +8 -0
  88. package/dist/types/commands/manifest/scripts/resolution-report-maven.d.mts.map +1 -0
  89. package/dist/types/commands/manifest/scripts/resolution-report-render.d.mts +43 -0
  90. package/dist/types/commands/manifest/scripts/resolution-report-render.d.mts.map +1 -0
  91. package/dist/types/commands/manifest/scripts/resolution-report.d.mts +18 -0
  92. package/dist/types/commands/manifest/scripts/resolution-report.d.mts.map +1 -0
  93. package/dist/types/commands/manifest/scripts/run.d.mts +43 -0
  94. package/dist/types/commands/manifest/scripts/run.d.mts.map +1 -0
  95. package/dist/types/commands/manifest/scripts/sidecar.d.mts +27 -0
  96. package/dist/types/commands/manifest/scripts/sidecar.d.mts.map +1 -0
  97. package/dist/types/commands/manifest/setup-manifest-config.d.mts.map +1 -1
  98. package/dist/types/commands/organization/fetch-organization-list.d.mts +2 -2
  99. package/dist/types/commands/organization/fetch-organization-list.d.mts.map +1 -1
  100. package/dist/types/commands/package/output-purls-shallow-score.d.mts.map +1 -1
  101. package/dist/types/commands/repository/fetch-create-repo.d.mts +2 -2
  102. package/dist/types/commands/repository/fetch-create-repo.d.mts.map +1 -1
  103. package/dist/types/commands/repository/fetch-delete-repo.d.mts +2 -2
  104. package/dist/types/commands/repository/fetch-delete-repo.d.mts.map +1 -1
  105. package/dist/types/commands/repository/fetch-list-all-repos.d.mts +2 -2
  106. package/dist/types/commands/repository/fetch-list-all-repos.d.mts.map +1 -1
  107. package/dist/types/commands/repository/fetch-list-repos.d.mts +2 -2
  108. package/dist/types/commands/repository/fetch-list-repos.d.mts.map +1 -1
  109. package/dist/types/commands/repository/fetch-update-repo.d.mts +2 -2
  110. package/dist/types/commands/repository/fetch-update-repo.d.mts.map +1 -1
  111. package/dist/types/commands/repository/fetch-view-repo.d.mts +2 -2
  112. package/dist/types/commands/repository/fetch-view-repo.d.mts.map +1 -1
  113. package/dist/types/commands/repository/handle-list-repos.d.mts.map +1 -1
  114. package/dist/types/commands/repository/output-create-repo.d.mts +2 -2
  115. package/dist/types/commands/repository/output-create-repo.d.mts.map +1 -1
  116. package/dist/types/commands/repository/output-delete-repo.d.mts +2 -2
  117. package/dist/types/commands/repository/output-delete-repo.d.mts.map +1 -1
  118. package/dist/types/commands/repository/output-list-repos.d.mts +2 -2
  119. package/dist/types/commands/repository/output-list-repos.d.mts.map +1 -1
  120. package/dist/types/commands/repository/output-update-repo.d.mts +2 -2
  121. package/dist/types/commands/repository/output-update-repo.d.mts.map +1 -1
  122. package/dist/types/commands/repository/output-view-repo.d.mts +2 -2
  123. package/dist/types/commands/repository/output-view-repo.d.mts.map +1 -1
  124. package/dist/types/commands/scan/cmd-scan-create.d.mts.map +1 -1
  125. package/dist/types/commands/scan/cmd-scan-reach.d.mts.map +1 -1
  126. package/dist/types/commands/scan/create-scan-from-github.d.mts.map +1 -1
  127. package/dist/types/commands/scan/exclude-paths.d.mts +2 -2
  128. package/dist/types/commands/scan/exclude-paths.d.mts.map +1 -1
  129. package/dist/types/commands/scan/fetch-create-org-full-scan.d.mts +2 -2
  130. package/dist/types/commands/scan/fetch-create-org-full-scan.d.mts.map +1 -1
  131. package/dist/types/commands/scan/fetch-delete-org-full-scan.d.mts +2 -2
  132. package/dist/types/commands/scan/fetch-delete-org-full-scan.d.mts.map +1 -1
  133. package/dist/types/commands/scan/fetch-list-scans.d.mts +2 -2
  134. package/dist/types/commands/scan/fetch-list-scans.d.mts.map +1 -1
  135. package/dist/types/commands/scan/fetch-scan-metadata.d.mts +2 -2
  136. package/dist/types/commands/scan/fetch-scan-metadata.d.mts.map +1 -1
  137. package/dist/types/commands/scan/fetch-scan.d.mts +4 -0
  138. package/dist/types/commands/scan/fetch-scan.d.mts.map +1 -1
  139. package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts +2 -1
  140. package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts.map +1 -1
  141. package/dist/types/commands/scan/finalize-tier1-scan.d.mts +9 -5
  142. package/dist/types/commands/scan/finalize-tier1-scan.d.mts.map +1 -1
  143. package/dist/types/commands/scan/handle-create-new-scan.d.mts.map +1 -1
  144. package/dist/types/commands/scan/handle-scan-reach.d.mts.map +1 -1
  145. package/dist/types/commands/scan/output-create-new-scan.d.mts +2 -2
  146. package/dist/types/commands/scan/output-create-new-scan.d.mts.map +1 -1
  147. package/dist/types/commands/scan/output-delete-scan.d.mts +2 -2
  148. package/dist/types/commands/scan/output-delete-scan.d.mts.map +1 -1
  149. package/dist/types/commands/scan/output-list-scans.d.mts +2 -2
  150. package/dist/types/commands/scan/output-list-scans.d.mts.map +1 -1
  151. package/dist/types/commands/scan/output-scan-metadata.d.mts +2 -2
  152. package/dist/types/commands/scan/output-scan-metadata.d.mts.map +1 -1
  153. package/dist/types/commands/scan/output-scan-reach.d.mts +2 -1
  154. package/dist/types/commands/scan/output-scan-reach.d.mts.map +1 -1
  155. package/dist/types/commands/scan/perform-reachability-analysis.d.mts +10 -3
  156. package/dist/types/commands/scan/perform-reachability-analysis.d.mts.map +1 -1
  157. package/dist/types/commands/scan/reachability-flags.d.mts.map +1 -1
  158. package/dist/types/commands/scan/reachability-units.d.mts +18 -0
  159. package/dist/types/commands/scan/reachability-units.d.mts.map +1 -0
  160. package/dist/types/commands/scan/stream-scan.d.mts +3 -1
  161. package/dist/types/commands/scan/stream-scan.d.mts.map +1 -1
  162. package/dist/types/constants.d.mts +2 -0
  163. package/dist/types/constants.d.mts.map +1 -1
  164. package/dist/types/utils/api.d.mts +53 -7
  165. package/dist/types/utils/api.d.mts.map +1 -1
  166. package/dist/types/utils/config.d.mts.map +1 -1
  167. package/dist/types/utils/dlx.d.mts +4 -3
  168. package/dist/types/utils/dlx.d.mts.map +1 -1
  169. package/dist/types/utils/ecosystem.d.mts +8 -1
  170. package/dist/types/utils/ecosystem.d.mts.map +1 -1
  171. package/dist/types/utils/fs.d.mts +1 -0
  172. package/dist/types/utils/fs.d.mts.map +1 -1
  173. package/dist/types/utils/glob.d.mts +5 -4
  174. package/dist/types/utils/glob.d.mts.map +1 -1
  175. package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
  176. package/dist/types/utils/path-resolve.d.mts +1 -1
  177. package/dist/types/utils/path-resolve.d.mts.map +1 -1
  178. package/dist/types/utils/sdk.d.mts +6 -0
  179. package/dist/types/utils/sdk.d.mts.map +1 -1
  180. package/dist/types/utils/self-update.d.mts +3 -0
  181. package/dist/types/utils/self-update.d.mts.map +1 -0
  182. package/dist/types/utils/socket-json.d.mts +18 -0
  183. package/dist/types/utils/socket-json.d.mts.map +1 -1
  184. package/dist/types/utils/socket-package-alert.d.mts.map +1 -1
  185. package/dist/utils.js +614 -283
  186. package/dist/utils.js.map +1 -1
  187. package/dist/vendor.js +50578 -27781
  188. package/external/blessed/lib/tput.js +5 -5
  189. package/package.json +60 -132
  190. package/requirements.json +1 -1
  191. package/shadow-bin/npm +0 -0
  192. package/shadow-bin/npx +0 -0
  193. package/shadow-bin/pnpm +0 -0
  194. package/shadow-bin/yarn +0 -0
  195. package/dist/types/commands/manifest/bazel/bazel-build-parser.d.mts +0 -34
  196. package/dist/types/commands/manifest/bazel/bazel-build-parser.d.mts.map +0 -1
  197. package/external/blessed/usr/fonts/AUTHORS +0 -1
  198. package/external/blessed/usr/fonts/LICENSE +0 -94
  199. package/external/blessed/usr/fonts/README +0 -340
  200. package/external/blessed/usr/fonts/ter-u14b.json +0 -17826
  201. package/external/blessed/usr/fonts/ter-u14n.json +0 -17826
package/dist/utils.js CHANGED
@@ -3,8 +3,8 @@
3
3
  var vendor = require('./vendor.js');
4
4
  var logger = require('../external/@socketsecurity/registry/lib/logger');
5
5
  var strings = require('../external/@socketsecurity/registry/lib/strings');
6
- var require$$9 = require('../external/@socketsecurity/registry/lib/debug');
7
- var require$$11 = require('../external/@socketsecurity/registry/lib/objects');
6
+ var debug$2 = require('../external/@socketsecurity/registry/lib/debug');
7
+ var objects = require('../external/@socketsecurity/registry/lib/objects');
8
8
  var constants = require('./constants.js');
9
9
  var arrays = require('../external/@socketsecurity/registry/lib/arrays');
10
10
  var path$1 = require('../external/@socketsecurity/registry/lib/path');
@@ -18,22 +18,23 @@ var prompts = require('../external/@socketsecurity/registry/lib/prompts');
18
18
  var spawn = require('../external/@socketsecurity/registry/lib/spawn');
19
19
  var fs = require('node:fs');
20
20
  var fs$2 = require('node:fs/promises');
21
- var promises$1 = require('node:stream/promises');
22
- var node_zlib = require('node:zlib');
21
+ var require$$9 = require('node:stream/promises');
22
+ var require$$11 = require('node:zlib');
23
23
  var fs$1 = require('../external/@socketsecurity/registry/lib/fs');
24
- var require$$5 = require('node:module');
24
+ var require$$1 = require('node:module');
25
25
  var os = require('node:os');
26
- var require$$3 = require('node:https');
26
+ var require$$13 = require('node:https');
27
27
  var web = require('node:stream/web');
28
- var require$$13 = require('../external/@socketsecurity/registry/lib/url');
28
+ var url = require('../external/@socketsecurity/registry/lib/url');
29
29
  var agent = require('../external/@socketsecurity/registry/lib/agent');
30
30
  var bin = require('../external/@socketsecurity/registry/lib/bin');
31
31
  var packages = require('../external/@socketsecurity/registry/lib/packages');
32
32
  var require$$0$1 = require('node:url');
33
33
  var globs = require('../external/@socketsecurity/registry/lib/globs');
34
34
  var streams = require('../external/@socketsecurity/registry/lib/streams');
35
- var promises = require('node:timers/promises');
36
- var require$$1 = require('node:util');
35
+ var require$$7 = require('node:timers/promises');
36
+ var require$$10 = require('node:util');
37
+ var require$$12 = require('node:http');
37
38
  var node_tls = require('node:tls');
38
39
  var process$1 = require('node:process');
39
40
  var require$$0 = require('node:crypto');
@@ -98,13 +99,13 @@ function debugApiResponse(method, endpoint, status, error, duration, headers) {
98
99
  */
99
100
  function debugFileOp(operation, filepath, error) {
100
101
  if (error) {
101
- require$$9.debugDir('warn', {
102
+ debug$2.debugDir('warn', {
102
103
  operation,
103
104
  filepath,
104
105
  error: error instanceof Error ? error.message : 'Unknown error'
105
106
  });
106
- } else if (require$$9.isDebug('silly')) {
107
- require$$9.debugFn('silly', `File ${operation}: ${filepath}`);
107
+ } else if (debug$2.isDebug('silly')) {
108
+ debug$2.debugFn('silly', `File ${operation}: ${filepath}`);
108
109
  }
109
110
  }
110
111
 
@@ -116,19 +117,19 @@ function debugScan(phase, packageCount, details) {
116
117
  switch (phase) {
117
118
  case 'start':
118
119
  if (packageCount) {
119
- require$$9.debugFn('notice', `Scanning ${packageCount} packages`);
120
+ debug$2.debugFn('notice', `Scanning ${packageCount} packages`);
120
121
  }
121
122
  break;
122
123
  case 'progress':
123
- if (require$$9.isDebug('silly') && packageCount) {
124
- require$$9.debugFn('silly', `Scan progress: ${packageCount} packages processed`);
124
+ if (debug$2.isDebug('silly') && packageCount) {
125
+ debug$2.debugFn('silly', `Scan progress: ${packageCount} packages processed`);
125
126
  }
126
127
  break;
127
128
  case 'complete':
128
- require$$9.debugFn('notice', `Scan complete${packageCount ? `: ${packageCount} packages` : ''}`);
129
+ debug$2.debugFn('notice', `Scan complete${packageCount ? `: ${packageCount} packages` : ''}`);
129
130
  break;
130
131
  case 'error':
131
- require$$9.debugDir('error', {
132
+ debug$2.debugDir('error', {
132
133
  phase: 'scan_error',
133
134
  details
134
135
  });
@@ -141,14 +142,14 @@ function debugScan(phase, packageCount, details) {
141
142
  */
142
143
  function debugConfig(source, found, error) {
143
144
  if (error) {
144
- require$$9.debugDir('warn', {
145
+ debug$2.debugDir('warn', {
145
146
  source,
146
147
  error: error instanceof Error ? error.message : 'Unknown error'
147
148
  });
148
149
  } else if (found) {
149
- require$$9.debugFn('notice', `Config loaded: ${source}`);
150
- } else if (require$$9.isDebug('silly')) {
151
- require$$9.debugFn('silly', `Config not found: ${source}`);
150
+ debug$2.debugFn('notice', `Config loaded: ${source}`);
151
+ } else if (debug$2.isDebug('silly')) {
152
+ debug$2.debugFn('silly', `Config not found: ${source}`);
152
153
  }
153
154
  }
154
155
 
@@ -158,15 +159,15 @@ function debugConfig(source, found, error) {
158
159
  */
159
160
  function debugGit(operation, success, details) {
160
161
  if (!success) {
161
- require$$9.debugDir('warn', {
162
+ debug$2.debugDir('warn', {
162
163
  git_op: operation,
163
164
  ...details
164
165
  });
165
- } else if (require$$9.isDebug('notice') && operation.includes('push') || operation.includes('commit')) {
166
+ } else if (debug$2.isDebug('notice') && operation.includes('push') || operation.includes('commit')) {
166
167
  // Only log important operations like push and commit.
167
- require$$9.debugFn('notice', `Git ${operation} succeeded`);
168
- } else if (require$$9.isDebug('silly')) {
169
- require$$9.debugFn('silly', `Git ${operation}`);
168
+ debug$2.debugFn('notice', `Git ${operation} succeeded`);
169
+ } else if (debug$2.isDebug('silly')) {
170
+ debug$2.debugFn('silly', `Git ${operation}`);
170
171
  }
171
172
  }
172
173
 
@@ -280,7 +281,7 @@ function shouldSave(currentContent, originalContent, originalFileContent, option
280
281
  const sortedContent = sort ? sortKeys(content) : content;
281
282
  const origContent = originalContent ? stripFormattingSymbols(originalContent) : {};
282
283
  if (ignoreWhitespace) {
283
- return !require$$1.isDeepStrictEqual(sortedContent, origContent);
284
+ return !require$$10.isDeepStrictEqual(sortedContent, origContent);
284
285
  }
285
286
  const formatting = getFormattingFromContent(currentContent);
286
287
  const newFileContent = stringifyWithFormatting(sortedContent, formatting);
@@ -297,7 +298,7 @@ async function retryWrite(filepath, content, retries = 3, baseDelay = 10) {
297
298
  await fs.promises.writeFile(filepath, content);
298
299
  if (process.platform === 'win32') {
299
300
  // eslint-disable-next-line no-await-in-loop
300
- await promises.setTimeout(50);
301
+ await require$$7.setTimeout(50);
301
302
  let accessRetries = 0;
302
303
  const maxAccessRetries = 5;
303
304
  while (accessRetries < maxAccessRetries) {
@@ -305,12 +306,12 @@ async function retryWrite(filepath, content, retries = 3, baseDelay = 10) {
305
306
  // eslint-disable-next-line no-await-in-loop
306
307
  await fs.promises.access(filepath);
307
308
  // eslint-disable-next-line no-await-in-loop
308
- await promises.setTimeout(10);
309
+ await require$$7.setTimeout(10);
309
310
  break;
310
311
  } catch {
311
312
  const delay = 20 * (accessRetries + 1);
312
313
  // eslint-disable-next-line no-await-in-loop
313
- await promises.setTimeout(delay);
314
+ await require$$7.setTimeout(delay);
314
315
  accessRetries++;
315
316
  }
316
317
  }
@@ -324,7 +325,7 @@ async function retryWrite(filepath, content, retries = 3, baseDelay = 10) {
324
325
  }
325
326
  const delay = baseDelay * 2 ** attempt;
326
327
  // eslint-disable-next-line no-await-in-loop
327
- await promises.setTimeout(delay);
328
+ await require$$7.setTimeout(delay);
328
329
  }
329
330
  }
330
331
  }
@@ -353,7 +354,7 @@ async function readFile(filepath) {
353
354
  }
354
355
  const delay = process.platform === 'win32' ? 50 * (attempt + 1) : 20;
355
356
  // eslint-disable-next-line no-await-in-loop
356
- await promises.setTimeout(delay);
357
+ await require$$7.setTimeout(delay);
357
358
  }
358
359
  }
359
360
  throw new Error('Unreachable code');
@@ -410,7 +411,7 @@ class EditableJson {
410
411
  const indent = detectIndent(data);
411
412
  const newline = detectNewline(data)
412
413
  // Use type assertion to allow symbol indexing.
413
- ;
414
+ ;
414
415
  parsed[INDENT_SYMBOL] = indent;
415
416
  parsed[NEWLINE_SYMBOL] = newline;
416
417
  this._content = parsed;
@@ -524,7 +525,7 @@ class InputError extends Error {
524
525
  async function captureException(exception, hint) {
525
526
  const result = captureExceptionSync(exception, hint);
526
527
  // "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
527
- await promises.setTimeout(1000);
528
+ await require$$7.setTimeout(1000);
528
529
  return result;
529
530
  }
530
531
  function captureExceptionSync(exception, hint) {
@@ -532,7 +533,7 @@ function captureExceptionSync(exception, hint) {
532
533
  if (!Sentry) {
533
534
  return '';
534
535
  }
535
- require$$9.debugFn('notice', 'send: exception to Sentry');
536
+ debug$2.debugFn('notice', 'send: exception to Sentry');
536
537
  return Sentry.captureException(exception, hint);
537
538
  }
538
539
 
@@ -694,8 +695,8 @@ function findSocketYmlSync(dir = process.cwd()) {
694
695
  }
695
696
  };
696
697
  } catch (e) {
697
- require$$9.debugFn('error', `Failed to parse config file: ${ymlPath}`);
698
- require$$9.debugDir('error', e);
698
+ debug$2.debugFn('error', `Failed to parse config file: ${ymlPath}`);
699
+ debug$2.debugDir('error', e);
699
700
  return {
700
701
  ok: false,
701
702
  message: `Found file but was unable to parse ${ymlPath}`,
@@ -759,7 +760,7 @@ let _cachedConfig;
759
760
  // When using --config or SOCKET_CLI_CONFIG, do not persist the config.
760
761
  let _configFromFlag = false;
761
762
  function overrideCachedConfig(jsonConfig) {
762
- require$$9.debugFn('notice', 'override: full config (not stored)');
763
+ debug$2.debugFn('notice', 'override: full config (not stored)');
763
764
  let config;
764
765
  try {
765
766
  config = JSON.parse(String(jsonConfig));
@@ -801,15 +802,22 @@ function overrideCachedConfig(jsonConfig) {
801
802
  };
802
803
  }
803
804
  function overrideConfigApiToken(apiToken) {
804
- require$$9.debugFn('notice', 'override: Socket API token (not stored)');
805
- // Set token to the local cached config and mark it read-only so it doesn't persist.
806
- _cachedConfig = {
807
- ...vendor.configExports,
808
- ...(apiToken === undefined ? {} : {
809
- apiToken: String(apiToken)
810
- })
811
- };
812
- _configFromFlag = true;
805
+ debug$2.debugFn('notice', 'override: Socket API token (not stored)');
806
+ if (apiToken === undefined) {
807
+ // SOCKET_CLI_NO_API_TOKEN: operate with no token and lock the config to
808
+ // read-only so nothing is persisted for this run.
809
+ _cachedConfig = {
810
+ ...vendor.configExports
811
+ };
812
+ _configFromFlag = true;
813
+ return;
814
+ }
815
+ // A token supplied via env (SOCKET_CLI_API_TOKEN / SOCKET_SECURITY_API_TOKEN)
816
+ // overrides authentication only. getDefaultApiToken() reads it straight from
817
+ // the environment, so we intentionally do NOT inject it into the cached config
818
+ // and do NOT mark the config read-only: unrelated keys (e.g. defaultOrg) can
819
+ // still be saved with `socket config set`, while the env token never reaches
820
+ // disk because it never enters the persisted cache.
813
821
  }
814
822
  let _pendingSave = false;
815
823
  function updateConfigValue(configKey, value) {
@@ -838,7 +846,7 @@ function updateConfigValue(configKey, value) {
838
846
  return {
839
847
  ok: true,
840
848
  message: `Config key '${key}' was ${wasDeleted ? 'deleted' : `updated`}`,
841
- data: 'Change applied but not persisted; current config is overridden through env var or flag'
849
+ data: 'The active config is read-only because it was fully overridden by the ' + '--config flag, SOCKET_CLI_CONFIG, or SOCKET_CLI_NO_API_TOKEN. Remove ' + 'the override to save changes to disk.'
842
850
  };
843
851
  }
844
852
  if (!_pendingSave) {
@@ -931,7 +939,7 @@ function updateConfigValue(configKey, value) {
931
939
  * - Used for permission validation and help text
932
940
  */
933
941
 
934
- const require$3 = require$$5.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
942
+ const require$3 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
935
943
  let _requirements;
936
944
  function getRequirements() {
937
945
  if (_requirements === undefined) {
@@ -995,14 +1003,14 @@ function getRequirementsKey(cmdPath) {
995
1003
  * Wraps debugFn to provide a simpler API.
996
1004
  */
997
1005
  const debug$1 = message => {
998
- require$$9.debugFn('socket:telemetry:service', message);
1006
+ debug$2.debugFn('socket:telemetry:service', message);
999
1007
  };
1000
1008
 
1001
1009
  /**
1002
1010
  * DebugDir wrapper for telemetry service.
1003
1011
  */
1004
1012
  const debugDirWrapper = obj => {
1005
- require$$9.debugDir('socket:telemetry:service', obj);
1013
+ debug$2.debugDir('socket:telemetry:service', obj);
1006
1014
  };
1007
1015
 
1008
1016
  /**
@@ -1367,7 +1375,7 @@ class TelemetryService {
1367
1375
  * Debug wrapper for telemetry integration.
1368
1376
  */
1369
1377
  const debug = message => {
1370
- require$$9.debugFn('socket:telemetry:integration', message);
1378
+ debug$2.debugFn('socket:telemetry:integration', message);
1371
1379
  };
1372
1380
 
1373
1381
  /**
@@ -1816,6 +1824,32 @@ async function trackSubprocessError(command, startTime, error, exitCode, metadat
1816
1824
  * - Includes CLI version and platform information
1817
1825
  */
1818
1826
 
1827
+ // SDK v4 rejects request timeouts outside this range (see the SDK's
1828
+ // MIN_HTTP_TIMEOUT / MAX_HTTP_TIMEOUT). The SDK does not re-export those
1829
+ // constants, so the bounds are mirrored here.
1830
+ const MIN_API_TIMEOUT_MS = 5_000;
1831
+ const MAX_API_TIMEOUT_MS = 300_000;
1832
+
1833
+ // Clamp a SOCKET_CLI_API_TIMEOUT value into the SDK's accepted range. The SDK
1834
+ // throws a TypeError on out-of-range timeouts, so an out-of-range user value
1835
+ // would otherwise make every API call fail; clamping preserves intent (a small
1836
+ // value maps to the floor, a huge value to the ceiling) while staying valid.
1837
+ function clampApiTimeout(timeout) {
1838
+ return Math.min(Math.max(timeout, MIN_API_TIMEOUT_MS), MAX_API_TIMEOUT_MS);
1839
+ }
1840
+
1841
+ // Lazy-evaluated full CLI user agent for direct (non-SDK) API calls.
1842
+ // Includes the CLI product token, Node.js version, and OS platform/arch.
1843
+ // e.g. "socket/1.1.96 node/v22.0.0 linux/arm64"
1844
+ let _cliUserAgent;
1845
+ function getCliUserAgent() {
1846
+ if (!_cliUserAgent) {
1847
+ const name = constants.default.ENV.INLINED_SOCKET_CLI_NAME.replace('@', '').replace('/', '-');
1848
+ const version = constants.default.ENV.INLINED_SOCKET_CLI_VERSION;
1849
+ _cliUserAgent = [`${name}/${version}`, `node/${process.version}`, `${process.platform}/${process.arch}`].join(' ');
1850
+ }
1851
+ return _cliUserAgent;
1852
+ }
1819
1853
  const TOKEN_PREFIX = 'sktsec_';
1820
1854
  const TOKEN_PREFIX_LENGTH = TOKEN_PREFIX.length;
1821
1855
  const TOKEN_VISIBLE_LENGTH = 5;
@@ -1823,13 +1857,13 @@ const TOKEN_VISIBLE_LENGTH = 5;
1823
1857
  // The Socket API server that should be used for operations.
1824
1858
  function getDefaultApiBaseUrl$1() {
1825
1859
  const baseUrl = constants.default.ENV.SOCKET_CLI_API_BASE_URL || getConfigValueOrUndef(constants.CONFIG_KEY_API_BASE_URL);
1826
- return require$$13.isUrl(baseUrl) ? baseUrl : undefined;
1860
+ return url.isUrl(baseUrl) ? baseUrl : undefined;
1827
1861
  }
1828
1862
 
1829
1863
  // The Socket API server that should be used for operations.
1830
1864
  function getDefaultProxyUrl() {
1831
1865
  const apiProxy = constants.default.ENV.SOCKET_CLI_API_PROXY || getConfigValueOrUndef(constants.CONFIG_KEY_API_PROXY);
1832
- return require$$13.isUrl(apiProxy) ? apiProxy : undefined;
1866
+ return url.isUrl(apiProxy) ? apiProxy : undefined;
1833
1867
  }
1834
1868
 
1835
1869
  // Cached extra CA certificates for SSL_CERT_FILE support.
@@ -1862,7 +1896,7 @@ function getExtraCaCerts() {
1862
1896
  _extraCaCerts = [...node_tls.rootCertificates, extraCerts];
1863
1897
  return _extraCaCerts;
1864
1898
  } catch (e) {
1865
- require$$9.debugFn('warn', `Failed to read certificate file: ${certPath}`, e);
1899
+ debug$2.debugFn('warn', `Failed to read certificate file: ${certPath}`, e);
1866
1900
  return undefined;
1867
1901
  }
1868
1902
  }
@@ -1912,7 +1946,7 @@ async function setupSdk(options) {
1912
1946
  let {
1913
1947
  apiProxy
1914
1948
  } = opts;
1915
- if (!require$$13.isUrl(apiProxy)) {
1949
+ if (!url.isUrl(apiProxy)) {
1916
1950
  apiProxy = getDefaultProxyUrl();
1917
1951
  }
1918
1952
  const {
@@ -1921,31 +1955,45 @@ async function setupSdk(options) {
1921
1955
 
1922
1956
  // Usage of HttpProxyAgent vs. HttpsProxyAgent based on the chart at:
1923
1957
  // https://github.com/delvedor/hpagent?tab=readme-ov-file#usage
1924
- const ProxyAgent = apiBaseUrl?.startsWith('http:') ? vendor.HttpProxyAgent : vendor.HttpsProxyAgent;
1958
+ const isHttp = apiBaseUrl?.startsWith('http:');
1959
+ const ProxyAgent = isHttp ? vendor.HttpProxyAgent : vendor.HttpsProxyAgent;
1925
1960
 
1926
1961
  // Load extra CA certificates for SSL_CERT_FILE support when
1927
1962
  // NODE_EXTRA_CA_CERTS was not set at process startup.
1928
1963
  const ca = getExtraCaCerts();
1964
+
1965
+ // Always pass an explicit agent. Node >=19's global agent enables keepAlive
1966
+ // with a 5s socket timeout that Node applies as a per-socket inactivity
1967
+ // timeout. A request made without an explicit agent inherits it and is torn
1968
+ // down after 5s of socket inactivity, even when SOCKET_CLI_API_TIMEOUT is
1969
+ // unset. This breaks slow endpoints like upload-manifest-files, which streams
1970
+ // a chunked multipart body while the server parses auth/multipart before
1971
+ // sending any response byte. A fresh Agent carries no timeout, so a request
1972
+ // is bounded only by a real SOCKET_CLI_API_TIMEOUT (applied below via the
1973
+ // SDK's timeout option) or until interrupted.
1929
1974
  const sdkOptions = {
1930
- ...(apiProxy ? {
1931
- agent: new ProxyAgent({
1932
- proxy: apiProxy,
1933
- ...(ca ? {
1934
- ca,
1935
- proxyConnectOptions: {
1936
- ca
1937
- }
1938
- } : {})
1939
- })
1940
- } : ca ? {
1941
- agent: new require$$3.Agent({
1942
- ca
1943
- })
1944
- } : {}),
1975
+ agent: apiProxy ? new ProxyAgent({
1976
+ proxy: apiProxy,
1977
+ ...(ca ? {
1978
+ ca,
1979
+ proxyConnectOptions: {
1980
+ ca
1981
+ }
1982
+ } : {})
1983
+ }) : isHttp ? new require$$12.Agent() : new require$$13.Agent(ca ? {
1984
+ ca
1985
+ } : undefined),
1945
1986
  ...(apiBaseUrl ? {
1946
1987
  baseUrl: apiBaseUrl
1947
1988
  } : {}),
1948
- timeout: constants.default.ENV.SOCKET_CLI_API_TIMEOUT,
1989
+ // SDK v4 validates the request timeout to be within [5000, 300000] ms and
1990
+ // throws otherwise. Only forward a truthy timeout; when unset (0) omit it
1991
+ // so the SDK applies its own default instead of rejecting the value. A
1992
+ // truthy-but-out-of-range value is clamped into the accepted range rather
1993
+ // than forwarded, which would make every SDK call throw.
1994
+ ...(constants.default.ENV.SOCKET_CLI_API_TIMEOUT ? {
1995
+ timeout: clampApiTimeout(constants.default.ENV.SOCKET_CLI_API_TIMEOUT)
1996
+ } : {}),
1949
1997
  userAgent: vendor.distExports.createUserAgentFromPkgJson({
1950
1998
  name: constants.default.ENV.INLINED_SOCKET_CLI_NAME,
1951
1999
  version: constants.default.ENV.INLINED_SOCKET_CLI_VERSION,
@@ -2034,32 +2082,36 @@ async function setupSdk(options) {
2034
2082
  const MAX_REDIRECTS = 20;
2035
2083
  const NO_ERROR_MESSAGE = 'No error message returned';
2036
2084
 
2037
- // Cached HTTPS agent for extra CA certificate support in direct API calls.
2085
+ // Cached HTTPS agent for direct API calls. Undefined only until the first
2086
+ // getHttpsAgent() call lazily creates it.
2038
2087
  let _httpsAgent;
2039
- let _httpsAgentResolved = false;
2040
2088
 
2041
- // Returns an HTTPS agent configured with extra CA certificates when
2042
- // SSL_CERT_FILE is set but NODE_EXTRA_CA_CERTS is not.
2089
+ // Returns an explicit HTTPS agent for direct API calls, carrying extra CA
2090
+ // certificates when SSL_CERT_FILE is set but NODE_EXTRA_CA_CERTS is not. An
2091
+ // explicit agent is always returned. Node >=19's global agent enables keepAlive
2092
+ // with a 5s socket timeout that Node applies as a per-socket inactivity
2093
+ // timeout. A request made without an explicit agent inherits it and is torn
2094
+ // down after 5s of socket inactivity, prematurely dropping slow or idle-gapped
2095
+ // requests (e.g. streaming full-scan responses, large downloads) even when no
2096
+ // timeout was requested. A fresh Agent carries no timeout.
2043
2097
  function getHttpsAgent() {
2044
- if (_httpsAgentResolved) {
2098
+ if (_httpsAgent) {
2045
2099
  return _httpsAgent;
2046
2100
  }
2047
- _httpsAgentResolved = true;
2048
2101
  const ca = getExtraCaCerts();
2049
- if (!ca) {
2050
- return undefined;
2051
- }
2052
- _httpsAgent = new require$$3.Agent({
2102
+ const agent = ca ? new require$$13.Agent({
2053
2103
  ca
2054
- });
2055
- return _httpsAgent;
2104
+ }) : new require$$13.Agent();
2105
+ _httpsAgent = agent;
2106
+ return agent;
2056
2107
  }
2057
2108
 
2058
2109
  // All outbound API requests use node:https.request rather than global fetch.
2059
2110
  // This ensures no body timeout is applied — large streaming ND-JSON responses
2060
- // (e.g. full scan results) can transfer without a hard deadline. When
2061
- // SSL_CERT_FILE is configured, a custom HttpsAgent carrying the extra CA
2062
- // certificates is passed; otherwise the default agent is used.
2111
+ // (e.g. full scan results) can transfer without a hard deadline. An explicit
2112
+ // HttpsAgent is always passed (carrying extra CA certificates when
2113
+ // SSL_CERT_FILE is configured) so requests do not inherit Node's global-agent
2114
+ // keepAlive socket timeout.
2063
2115
 
2064
2116
  // Internal httpsRequest-based fetch with redirect support.
2065
2117
  function _httpsRequestFetch(url, init, agent, redirectCount) {
@@ -2071,7 +2123,7 @@ function _httpsRequestFetch(url, init, agent, redirectCount) {
2071
2123
  if (init.body) {
2072
2124
  headers['content-length'] = String(Buffer.byteLength(init.body));
2073
2125
  }
2074
- const req = require$$3.request(url, {
2126
+ const req = require$$13.request(url, {
2075
2127
  method: init.method || 'GET',
2076
2128
  headers,
2077
2129
  agent
@@ -2220,6 +2272,26 @@ async function getErrorMessageForHttpStatusCode(code) {
2220
2272
  }
2221
2273
  return `Server responded with status code ${code}`;
2222
2274
  }
2275
+
2276
+ /**
2277
+ * The subset of a Socket SDK result that {@link handleApiCall} reads. Both the
2278
+ * OpenAPI-derived `SocketSdkResult<T>` family and the SDK 4.x strict result
2279
+ * types (`OrganizationsResult`, `RepositoryResult`, `DeleteResult`, ...)
2280
+ * structurally satisfy this shape, so a caller can pass whichever result a
2281
+ * given SDK method returns without forcing a (sometimes stale) operation-key
2282
+ * shape onto the strict return types.
2283
+ */
2284
+
2285
+ /**
2286
+ * The success `data` type carried by a Socket SDK result union `R`. The
2287
+ * conditional distributes over `R`'s members, so only the success member(s)
2288
+ * contribute their `data`; the error member resolves to `never` and drops out.
2289
+ * Inferring the whole result `R` and extracting here (rather than inferring a
2290
+ * bare `Data` from a `Promise<{ data: Data } | ...>`) avoids `Data` absorbing
2291
+ * the error branch's `data?: undefined` — which would otherwise widen every
2292
+ * result to `CResult<Data | undefined>`.
2293
+ */
2294
+
2223
2295
  /**
2224
2296
  * Handle Socket SDK API calls with error handling and permission logging.
2225
2297
  */
@@ -2268,25 +2340,25 @@ async function handleApiCall(value, options) {
2268
2340
  if (description && !silence) {
2269
2341
  logger.logger.fail(`An error was thrown while requesting ${description}`);
2270
2342
  }
2271
- require$$9.debugDir('inspect', {
2343
+ debug$2.debugDir('inspect', {
2272
2344
  socketSdkErrorResult
2273
2345
  });
2274
2346
  return socketSdkErrorResult;
2275
2347
  }
2276
2348
 
2277
- // Note: TS can't narrow down the type of result due to generics.
2349
+ // The `success` discriminant is a concrete boolean literal in both branches,
2350
+ // so this narrows the result to its error branch regardless of `R`.
2278
2351
  if (sdkResult.success === false) {
2279
2352
  const endpoint = description || 'Socket API';
2280
2353
  debugApiResponse('API', endpoint, sdkResult.status);
2281
- require$$9.debugDir('inspect', {
2354
+ debug$2.debugDir('inspect', {
2282
2355
  sdkResult
2283
2356
  });
2284
- const errCResult = sdkResult;
2285
- const errStr = errCResult.error ? String(errCResult.error).trim() : '';
2357
+ const errStr = sdkResult.error ? String(sdkResult.error).trim() : '';
2286
2358
  const message = errStr || NO_ERROR_MESSAGE;
2287
- const reason = errCResult.cause || NO_ERROR_MESSAGE;
2359
+ const reason = sdkResult.cause || NO_ERROR_MESSAGE;
2288
2360
  const baseCause = reason && message !== reason ? `${message} (reason: ${reason})` : message;
2289
- const cause = errCResult.url ? `${baseCause} (url: ${errCResult.url})` : baseCause;
2361
+ const cause = sdkResult.url ? `${baseCause} (url: ${sdkResult.url})` : baseCause;
2290
2362
  const socketSdkErrorResult = {
2291
2363
  ok: false,
2292
2364
  message: 'Socket API error',
@@ -2302,6 +2374,9 @@ async function handleApiCall(value, options) {
2302
2374
  }
2303
2375
  return socketSdkErrorResult;
2304
2376
  }
2377
+ // Narrowing a type parameter by its `success` discriminant resolves `.data`
2378
+ // through the constraint's success branch (`unknown`); re-apply the precise
2379
+ // per-call success type the return contract already guarantees.
2305
2380
  const socketSdkSuccessResult = {
2306
2381
  ok: true,
2307
2382
  data: sdkResult.data
@@ -2313,8 +2388,8 @@ async function handleApiCallNoSpinner(value, description) {
2313
2388
  try {
2314
2389
  sdkResult = await value;
2315
2390
  } catch (e) {
2316
- require$$9.debugFn('error', `API request failed: ${description}`);
2317
- require$$9.debugDir('error', e);
2391
+ debug$2.debugFn('error', `API request failed: ${description}`);
2392
+ debug$2.debugDir('error', e);
2318
2393
  const errStr = e ? String(e).trim() : '';
2319
2394
  const message = 'Socket API error';
2320
2395
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -2328,18 +2403,18 @@ async function handleApiCallNoSpinner(value, description) {
2328
2403
  };
2329
2404
  }
2330
2405
 
2331
- // Note: TS can't narrow down the type of result due to generics
2406
+ // The `success` discriminant is a concrete boolean literal in both branches,
2407
+ // so this narrows the result to its error branch regardless of `R`.
2332
2408
  if (sdkResult.success === false) {
2333
- require$$9.debugFn('error', `fail: ${description} bad response`);
2334
- require$$9.debugDir('inspect', {
2409
+ debug$2.debugFn('error', `fail: ${description} bad response`);
2410
+ debug$2.debugDir('inspect', {
2335
2411
  sdkResult
2336
2412
  });
2337
- const sdkErrorResult = sdkResult;
2338
- const errStr = sdkErrorResult.error ? String(sdkErrorResult.error).trim() : '';
2413
+ const errStr = sdkResult.error ? String(sdkResult.error).trim() : '';
2339
2414
  const message = errStr || NO_ERROR_MESSAGE;
2340
- const reason = sdkErrorResult.cause || NO_ERROR_MESSAGE;
2415
+ const reason = sdkResult.cause || NO_ERROR_MESSAGE;
2341
2416
  const baseCause = reason && message !== reason ? `${message} (reason: ${reason})` : message;
2342
- const cause = sdkErrorResult.url ? `${baseCause} (url: ${sdkErrorResult.url})` : baseCause;
2417
+ const cause = sdkResult.url ? `${baseCause} (url: ${sdkResult.url})` : baseCause;
2343
2418
  return {
2344
2419
  ok: false,
2345
2420
  message: 'Socket API error',
@@ -2349,10 +2424,12 @@ async function handleApiCallNoSpinner(value, description) {
2349
2424
  }
2350
2425
  };
2351
2426
  } else {
2352
- const sdkSuccessResult = sdkResult;
2427
+ // Narrowing a type parameter by its `success` discriminant resolves `.data`
2428
+ // through the constraint's success branch (`unknown`); re-apply the precise
2429
+ // per-call success type the return contract already guarantees.
2353
2430
  return {
2354
2431
  ok: true,
2355
- data: sdkSuccessResult.data
2432
+ data: sdkResult.data
2356
2433
  };
2357
2434
  }
2358
2435
  }
@@ -2365,16 +2442,19 @@ async function queryApi(path, apiToken) {
2365
2442
  const result = await apiFetch(url, {
2366
2443
  method: 'GET',
2367
2444
  headers: {
2368
- Authorization: `Basic ${btoa(`${apiToken}:`)}`
2445
+ Authorization: `Basic ${btoa(`${apiToken}:`)}`,
2446
+ 'User-Agent': getCliUserAgent()
2369
2447
  }
2370
2448
  });
2371
2449
  return result;
2372
2450
  }
2373
-
2374
2451
  /**
2375
- * Query Socket API endpoint and return text response with error handling.
2452
+ * Query a Socket API endpoint and return the HTTP status alongside the text
2453
+ * body, with error handling. Unlike queryApiSafeText this surfaces the status
2454
+ * on success (including 2xx statuses like 202 Accepted), so callers can drive
2455
+ * status-dependent flows such as the cached-scan 202 poll loop.
2376
2456
  */
2377
- async function queryApiSafeText(path, description, commandPath) {
2457
+ async function queryApiSafeTextWithStatus(path, description, commandPath) {
2378
2458
  const apiToken = getDefaultApiToken();
2379
2459
  if (!apiToken) {
2380
2460
  return {
@@ -2405,8 +2485,8 @@ async function queryApiSafeText(path, description, commandPath) {
2405
2485
  spinner.failAndStop(`An error was thrown while requesting ${description}.`);
2406
2486
  debugApiResponse('GET', path, undefined, e, duration);
2407
2487
  }
2408
- require$$9.debugFn('error', 'Query API request failed');
2409
- require$$9.debugDir('error', e);
2488
+ debug$2.debugFn('error', 'Query API request failed');
2489
+ debug$2.debugDir('error', e);
2410
2490
  const errStr = e ? String(e).trim() : '';
2411
2491
  const message = 'API request failed';
2412
2492
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -2432,14 +2512,17 @@ async function queryApiSafeText(path, description, commandPath) {
2432
2512
  };
2433
2513
  }
2434
2514
  try {
2435
- const data = await result.text();
2515
+ const text = await result.text();
2436
2516
  return {
2437
2517
  ok: true,
2438
- data
2518
+ data: {
2519
+ status: result.status,
2520
+ text
2521
+ }
2439
2522
  };
2440
2523
  } catch (e) {
2441
- require$$9.debugFn('error', 'Failed to read API response text');
2442
- require$$9.debugDir('error', e);
2524
+ debug$2.debugFn('error', 'Failed to read API response text');
2525
+ debug$2.debugDir('error', e);
2443
2526
  return {
2444
2527
  ok: false,
2445
2528
  message: 'API request failed',
@@ -2448,6 +2531,17 @@ async function queryApiSafeText(path, description, commandPath) {
2448
2531
  }
2449
2532
  }
2450
2533
 
2534
+ /**
2535
+ * Query Socket API endpoint and return text response with error handling.
2536
+ */
2537
+ async function queryApiSafeText(path, description, commandPath) {
2538
+ const result = await queryApiSafeTextWithStatus(path, description);
2539
+ return result.ok ? {
2540
+ ok: true,
2541
+ data: result.data.text
2542
+ } : result;
2543
+ }
2544
+
2451
2545
  /**
2452
2546
  * Query Socket API endpoint and return parsed JSON response.
2453
2547
  */
@@ -2510,7 +2604,8 @@ async function sendApiRequest(path, options) {
2510
2604
  method,
2511
2605
  headers: {
2512
2606
  Authorization: `Basic ${btoa(`${apiToken}:`)}`,
2513
- 'Content-Type': 'application/json'
2607
+ 'Content-Type': 'application/json',
2608
+ 'User-Agent': getCliUserAgent()
2514
2609
  },
2515
2610
  ...(body ? {
2516
2611
  body: JSON.stringify(body)
@@ -2524,8 +2619,8 @@ async function sendApiRequest(path, options) {
2524
2619
  if (description) {
2525
2620
  spinner.failAndStop(`An error was thrown while requesting ${description}.`);
2526
2621
  }
2527
- require$$9.debugFn('error', `API ${method} request failed`);
2528
- require$$9.debugDir('error', e);
2622
+ debug$2.debugFn('error', `API ${method} request failed`);
2623
+ debug$2.debugDir('error', e);
2529
2624
  const errStr = e ? String(e).trim() : '';
2530
2625
  const message = 'API request failed';
2531
2626
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -2561,8 +2656,8 @@ async function sendApiRequest(path, options) {
2561
2656
  data: data
2562
2657
  };
2563
2658
  } catch (e) {
2564
- require$$9.debugFn('error', 'Failed to parse API response JSON');
2565
- require$$9.debugDir('error', e);
2659
+ debug$2.debugFn('error', 'Failed to parse API response JSON');
2660
+ debug$2.debugDir('error', e);
2566
2661
  return {
2567
2662
  ok: false,
2568
2663
  message: 'API request failed',
@@ -2693,9 +2788,9 @@ cols) {
2693
2788
  // Serialize the final result object before printing it
2694
2789
  // All commands that support the --json flag should call this before printing
2695
2790
  function serializeResultJson(data) {
2696
- if (!require$$11.isObject(data)) {
2791
+ if (!objects.isObject(data)) {
2697
2792
  process.exitCode = 1;
2698
- require$$9.debugFn('inspect', {
2793
+ debug$2.debugFn('inspect', {
2699
2794
  data
2700
2795
  });
2701
2796
 
@@ -2713,8 +2808,8 @@ function serializeResultJson(data) {
2713
2808
  process.exitCode = 1;
2714
2809
  const message = 'There was a problem converting the data set to JSON. Please try again without --json';
2715
2810
  logger.logger.fail(message);
2716
- require$$9.debugFn('error', 'JSON serialization failed');
2717
- require$$9.debugDir('error', e);
2811
+ debug$2.debugFn('error', 'JSON serialization failed');
2812
+ debug$2.debugDir('error', e);
2718
2813
 
2719
2814
  // This could be caused by circular references, which is an "us" problem.
2720
2815
  return `${JSON.stringify({
@@ -2979,7 +3074,7 @@ function getHelpListOutput(list, options) {
2979
3074
  const names = Object.keys(list).sort(sorts.naturalCompare);
2980
3075
  for (const name of names) {
2981
3076
  const entry = list[name];
2982
- const entryIsObj = require$$11.isObject(entry);
3077
+ const entryIsObj = objects.isObject(entry);
2983
3078
  if (entryIsObj && 'hidden' in entry && entry?.hidden) {
2984
3079
  continue;
2985
3080
  }
@@ -3077,9 +3172,9 @@ function getAsciiHeader(command, orgFlag, compactMode = false) {
3077
3172
  // Version display: show hash in debug mode, otherwise show semantic version.
3078
3173
  const fullVersion = constants.default.ENV.INLINED_SOCKET_CLI_VERSION;
3079
3174
  const versionHash = constants.default.ENV.INLINED_SOCKET_CLI_VERSION_HASH;
3080
- const cliVersion = redacting ? REDACTED : require$$9.isDebug() ? versionHash : `v${fullVersion}`;
3175
+ const cliVersion = redacting ? REDACTED : debug$2.isDebug() ? versionHash : `v${fullVersion}`;
3081
3176
  const nodeVersion = redacting ? REDACTED : process.version;
3082
- const showNodeVersion = !redacting && require$$9.isDebug();
3177
+ const showNodeVersion = !redacting && debug$2.isDebug();
3083
3178
  const defaultOrg = getConfigValueOrUndef(constants.CONFIG_KEY_DEFAULT_ORG);
3084
3179
  const configFromFlagDot = isConfigFromFlag() ? '*' : '.';
3085
3180
 
@@ -3197,7 +3292,7 @@ async function meowWithSubcommands(config, options) {
3197
3292
  hidden: true,
3198
3293
  description: 'Print the app version'
3199
3294
  },
3200
- ...require$$11.getOwn(additionalOptions, 'flags')
3295
+ ...objects.getOwn(additionalOptions, 'flags')
3201
3296
  };
3202
3297
  const [commandOrAliasName_, ...rawCommandArgv] = argv;
3203
3298
  let commandOrAliasName = commandOrAliasName_;
@@ -3232,7 +3327,7 @@ async function meowWithSubcommands(config, options) {
3232
3327
  }
3233
3328
  }
3234
3329
  if (isRootCommand) {
3235
- const hiddenDebugFlag = !require$$9.isDebug();
3330
+ const hiddenDebugFlag = !debug$2.isDebug();
3236
3331
  flags$1['compactHeader'] = {
3237
3332
  ...flags$1['compactHeader'],
3238
3333
  hidden: false
@@ -3295,7 +3390,7 @@ async function meowWithSubcommands(config, options) {
3295
3390
  spinner: spinnerFlag
3296
3391
  } = cli1.flags;
3297
3392
  const compactMode = compactHeaderFlag || constants.default.ENV.CI && !constants.default.ENV.VITEST;
3298
- const noSpinner = spinnerFlag === false || require$$9.isDebug();
3393
+ const noSpinner = spinnerFlag === false || debug$2.isDebug();
3299
3394
 
3300
3395
  // Use CI spinner style when --no-spinner is passed or debug mode is enabled.
3301
3396
  // This prevents the spinner from interfering with debug output.
@@ -3318,8 +3413,10 @@ async function meowWithSubcommands(config, options) {
3318
3413
  } else {
3319
3414
  const tokenOverride = constants.default.ENV.SOCKET_CLI_API_TOKEN;
3320
3415
  if (tokenOverride) {
3321
- // This will set the token (even if there was a config override) and
3322
- // set it to readOnly, making sure the temp token won't be persisted.
3416
+ // The env token overrides authentication only. getDefaultApiToken reads it
3417
+ // straight from the environment, so overrideConfigApiToken does not inject
3418
+ // it into the cached config and leaves the config writable — unrelated keys
3419
+ // still persist, while the env token itself is never written to disk.
3323
3420
  overrideConfigApiToken(tokenOverride);
3324
3421
  }
3325
3422
  }
@@ -3393,10 +3490,10 @@ async function meowWithSubcommands(config, options) {
3393
3490
  } else {
3394
3491
  lines.push('Commands');
3395
3492
  lines.push(` ${getHelpListOutput({
3396
- ...require$$11.toSortedObject(Object.fromEntries(Object.entries(subcommands).filter(({
3493
+ ...objects.toSortedObject(Object.fromEntries(Object.entries(subcommands).filter(({
3397
3494
  1: subcommand
3398
3495
  }) => !subcommand.hidden))),
3399
- ...require$$11.toSortedObject(Object.fromEntries(Object.entries(aliases).filter(({
3496
+ ...objects.toSortedObject(Object.fromEntries(Object.entries(aliases).filter(({
3400
3497
  1: alias
3401
3498
  }) => {
3402
3499
  const {
@@ -3541,7 +3638,7 @@ function meowOrExit(config, options) {
3541
3638
  version: versionFlag
3542
3639
  } = cli.flags;
3543
3640
  const compactMode = compactHeaderFlag || constants.default.ENV.CI && !constants.default.ENV.VITEST;
3544
- const noSpinner = spinnerFlag === false || require$$9.isDebug();
3641
+ const noSpinner = spinnerFlag === false || debug$2.isDebug();
3545
3642
 
3546
3643
  // Use CI spinner style when --no-spinner is passed.
3547
3644
  // This prevents the spinner from interfering with debug output.
@@ -3578,7 +3675,7 @@ function meowOrExit(config, options) {
3578
3675
  }
3579
3676
 
3580
3677
  // Meow doesn't detect 'version' as an unknown flag, so we do the leg work here.
3581
- if (versionFlag && !require$$11.hasOwn(cliConfig.flags, 'version')) {
3678
+ if (versionFlag && !objects.hasOwn(cliConfig.flags, 'version')) {
3582
3679
  // Use `console.error` here instead of `logger.error` to match Meow behavior.
3583
3680
  console.error('Unknown flag\n--version');
3584
3681
  // eslint-disable-next-line n/no-process-exit
@@ -3649,7 +3746,7 @@ async function fetchOrganization(options) {
3649
3746
  }
3650
3747
  sockSdk = sockSdkCResult.data;
3651
3748
  }
3652
- const orgsCResult = await handleApiCall(sockSdk.getOrganizations(), {
3749
+ const orgsCResult = await handleApiCall(sockSdk.listOrganizations(), {
3653
3750
  description,
3654
3751
  silence
3655
3752
  });
@@ -3778,7 +3875,7 @@ async function determineOrgSlug(orgFlag, interactive, dryRun) {
3778
3875
  async function getDefaultOrgSlug(silence) {
3779
3876
  const defaultOrgResult = getConfigValueOrUndef('defaultOrg');
3780
3877
  if (defaultOrgResult) {
3781
- require$$9.debugFn('notice', 'use: org from "defaultOrg" value of socket/settings local app data', defaultOrgResult);
3878
+ debug$2.debugFn('notice', 'use: org from "defaultOrg" value of socket/settings local app data', defaultOrgResult);
3782
3879
  return {
3783
3880
  ok: true,
3784
3881
  data: defaultOrgResult
@@ -3786,7 +3883,7 @@ async function getDefaultOrgSlug(silence) {
3786
3883
  }
3787
3884
  const envOrgSlug = constants.default.ENV.SOCKET_CLI_ORG_SLUG;
3788
3885
  if (envOrgSlug) {
3789
- require$$9.debugFn('notice', 'use: org from SOCKET_CLI_ORG_SLUG environment variable', envOrgSlug);
3886
+ debug$2.debugFn('notice', 'use: org from SOCKET_CLI_ORG_SLUG environment variable', envOrgSlug);
3790
3887
  return {
3791
3888
  ok: true,
3792
3889
  data: envOrgSlug
@@ -3809,7 +3906,12 @@ async function getDefaultOrgSlug(silence) {
3809
3906
  data: `No organization associated with the Socket API token. Unable to continue.`
3810
3907
  };
3811
3908
  }
3812
- const slug = organizations[keys[0]]?.name ?? undefined;
3909
+
3910
+ // Use the org's URL-safe `slug`, not its display `name`: this value is
3911
+ // exported as SOCKET_ORG_SLUG for the Coana CLI, which resolves the org by
3912
+ // slug. `name` is the human-readable display name (and may be null), so using
3913
+ // it here produced a wrong/empty org identifier.
3914
+ const slug = organizations[0]?.slug ?? undefined;
3813
3915
  if (!slug) {
3814
3916
  return {
3815
3917
  ok: false,
@@ -3817,7 +3919,7 @@ async function getDefaultOrgSlug(silence) {
3817
3919
  data: `Cannot determine the default organization for the API token. Unable to continue.`
3818
3920
  };
3819
3921
  }
3820
- require$$9.debugFn('notice', 'resolve: org from Socket API', slug);
3922
+ debug$2.debugFn('notice', 'resolve: org from Socket API', slug);
3821
3923
  return {
3822
3924
  ok: true,
3823
3925
  message: 'Retrieved default org from server',
@@ -3954,14 +4056,14 @@ async function getRepoInfo(cwd = process.cwd()) {
3954
4056
  })).stdout;
3955
4057
  info = parseGitRemoteUrl(remoteUrl);
3956
4058
  if (!info) {
3957
- require$$9.debugFn('warn', `Unmatched git remote URL format: ${remoteUrl}`);
3958
- require$$9.debugDir('warn', {
4059
+ debug$2.debugFn('warn', `Unmatched git remote URL format: ${remoteUrl}`);
4060
+ debug$2.debugDir('warn', {
3959
4061
  remoteUrl
3960
4062
  });
3961
4063
  }
3962
4064
  } catch (e) {
3963
4065
  // Expected failure when not in a git repo.
3964
- require$$9.debugDir('inspect', {
4066
+ debug$2.debugDir('inspect', {
3965
4067
  message: 'git remote get-url failed',
3966
4068
  error: e
3967
4069
  });
@@ -3987,7 +4089,7 @@ async function gitBranch(cwd = process.cwd()) {
3987
4089
  return gitSymbolicRefResult.stdout;
3988
4090
  } catch (e) {
3989
4091
  // Expected in detached HEAD state, fallback to rev-parse.
3990
- require$$9.debugDir('inspect', {
4092
+ debug$2.debugDir('inspect', {
3991
4093
  message: 'In detached HEAD state',
3992
4094
  error: e
3993
4095
  });
@@ -3999,7 +4101,7 @@ async function gitBranch(cwd = process.cwd()) {
3999
4101
  return gitRevParseResult.stdout;
4000
4102
  } catch (e) {
4001
4103
  // Both methods failed, likely not in a git repo.
4002
- require$$9.debugDir('inspect', {
4104
+ debug$2.debugDir('inspect', {
4003
4105
  message: 'Unable to determine git branch',
4004
4106
  error: e
4005
4107
  });
@@ -4031,7 +4133,7 @@ async function detectDefaultBranch(cwd = process.cwd()) {
4031
4133
  async function gitCleanFdx(cwd = process.cwd()) {
4032
4134
  const stdioIgnoreOptions = {
4033
4135
  cwd,
4034
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4136
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4035
4137
  };
4036
4138
  try {
4037
4139
  await spawn.spawn('git', ['clean', '-fdx'], stdioIgnoreOptions);
@@ -4047,7 +4149,7 @@ async function gitCleanFdx(cwd = process.cwd()) {
4047
4149
  async function gitCheckoutBranch(branch, cwd = process.cwd()) {
4048
4150
  const stdioIgnoreOptions = {
4049
4151
  cwd,
4050
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4152
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4051
4153
  };
4052
4154
  try {
4053
4155
  await spawn.spawn('git', ['checkout', branch], stdioIgnoreOptions);
@@ -4066,7 +4168,7 @@ async function gitCreateBranch(branch, cwd = process.cwd()) {
4066
4168
  }
4067
4169
  const stdioIgnoreOptions = {
4068
4170
  cwd,
4069
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4171
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4070
4172
  };
4071
4173
  try {
4072
4174
  await spawn.spawn('git', ['branch', branch], stdioIgnoreOptions);
@@ -4082,7 +4184,7 @@ async function gitCreateBranch(branch, cwd = process.cwd()) {
4082
4184
  async function gitPushBranch(branch, cwd = process.cwd()) {
4083
4185
  const stdioIgnoreOptions = {
4084
4186
  cwd,
4085
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4187
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4086
4188
  };
4087
4189
  try {
4088
4190
  await spawn.spawn('git', ['push', '--force', '--set-upstream', 'origin', branch], stdioIgnoreOptions);
@@ -4090,9 +4192,9 @@ async function gitPushBranch(branch, cwd = process.cwd()) {
4090
4192
  return true;
4091
4193
  } catch (e) {
4092
4194
  if (spawn.isSpawnError(e) && e.code === 128) {
4093
- require$$9.debugFn('error', "Push denied: token requires write permissions for 'contents' and 'pull-requests'");
4094
- require$$9.debugDir('error', e);
4095
- require$$9.debugDir('inspect', {
4195
+ debug$2.debugFn('error', "Push denied: token requires write permissions for 'contents' and 'pull-requests'");
4196
+ debug$2.debugDir('error', e);
4197
+ debug$2.debugDir('inspect', {
4096
4198
  branch
4097
4199
  });
4098
4200
  } else {
@@ -4105,7 +4207,7 @@ async function gitPushBranch(branch, cwd = process.cwd()) {
4105
4207
  }
4106
4208
  async function gitCommit(commitMsg, filepaths, options) {
4107
4209
  if (!filepaths.length) {
4108
- require$$9.debugFn('notice', `miss: no filepaths to add`);
4210
+ debug$2.debugFn('notice', `miss: no filepaths to add`);
4109
4211
  return false;
4110
4212
  }
4111
4213
  const {
@@ -4119,7 +4221,7 @@ async function gitCommit(commitMsg, filepaths, options) {
4119
4221
  await gitEnsureIdentity(user, email, cwd);
4120
4222
  const stdioIgnoreOptions = {
4121
4223
  cwd,
4122
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4224
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4123
4225
  };
4124
4226
  try {
4125
4227
  await spawn.spawn('git', ['add', ...filepaths], stdioIgnoreOptions);
@@ -4130,7 +4232,7 @@ async function gitCommit(commitMsg, filepaths, options) {
4130
4232
  debugGit('add', false, {
4131
4233
  error: e
4132
4234
  });
4133
- require$$9.debugDir('inspect', {
4235
+ debug$2.debugDir('inspect', {
4134
4236
  filepaths
4135
4237
  });
4136
4238
  return false;
@@ -4143,7 +4245,7 @@ async function gitCommit(commitMsg, filepaths, options) {
4143
4245
  debugGit('commit', false, {
4144
4246
  error: e
4145
4247
  });
4146
- require$$9.debugDir('inspect', {
4248
+ debug$2.debugDir('inspect', {
4147
4249
  commitMsg
4148
4250
  });
4149
4251
  }
@@ -4152,7 +4254,7 @@ async function gitCommit(commitMsg, filepaths, options) {
4152
4254
  async function gitDeleteBranch(branch, cwd = process.cwd()) {
4153
4255
  const stdioIgnoreOptions = {
4154
4256
  cwd,
4155
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4257
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4156
4258
  };
4157
4259
  try {
4158
4260
  // Will throw with exit code 1 if branch does not exist.
@@ -4160,7 +4262,7 @@ async function gitDeleteBranch(branch, cwd = process.cwd()) {
4160
4262
  return true;
4161
4263
  } catch (e) {
4162
4264
  // Expected failure when branch doesn't exist.
4163
- require$$9.debugDir('inspect', {
4265
+ debug$2.debugDir('inspect', {
4164
4266
  message: `Branch deletion failed (may not exist): ${branch}`,
4165
4267
  error: e
4166
4268
  });
@@ -4170,7 +4272,7 @@ async function gitDeleteBranch(branch, cwd = process.cwd()) {
4170
4272
  async function gitDeleteRemoteBranch(branch, cwd = process.cwd()) {
4171
4273
  const stdioIgnoreOptions = {
4172
4274
  cwd,
4173
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4275
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4174
4276
  };
4175
4277
  try {
4176
4278
  // Will throw with exit code 1 if branch does not exist.
@@ -4178,7 +4280,7 @@ async function gitDeleteRemoteBranch(branch, cwd = process.cwd()) {
4178
4280
  return true;
4179
4281
  } catch (e) {
4180
4282
  // Expected failure when remote branch doesn't exist.
4181
- require$$9.debugDir('inspect', {
4283
+ debug$2.debugDir('inspect', {
4182
4284
  message: `Remote branch deletion failed (may not exist): ${branch}`,
4183
4285
  error: e
4184
4286
  });
@@ -4201,7 +4303,7 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
4201
4303
  configValue = gitConfigResult.stdout;
4202
4304
  } catch (e) {
4203
4305
  // Expected when config property is not set.
4204
- require$$9.debugDir('inspect', {
4306
+ debug$2.debugDir('inspect', {
4205
4307
  message: `Git config property not set: ${prop}`,
4206
4308
  error: e
4207
4309
  });
@@ -4209,14 +4311,14 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
4209
4311
  if (configValue !== value) {
4210
4312
  const stdioIgnoreOptions = {
4211
4313
  cwd,
4212
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4314
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4213
4315
  };
4214
4316
  try {
4215
4317
  await spawn.spawn('git', ['config', prop, value], stdioIgnoreOptions);
4216
4318
  } catch (e) {
4217
- require$$9.debugFn('warn', `Failed to set git config: ${prop}`);
4218
- require$$9.debugDir('warn', e);
4219
- require$$9.debugDir('inspect', {
4319
+ debug$2.debugFn('warn', `Failed to set git config: ${prop}`);
4320
+ debug$2.debugDir('warn', e);
4321
+ debug$2.debugDir('inspect', {
4220
4322
  value
4221
4323
  });
4222
4324
  }
@@ -4226,7 +4328,7 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
4226
4328
  async function gitLocalBranchExists(branch, cwd = process.cwd()) {
4227
4329
  const stdioIgnoreOptions = {
4228
4330
  cwd,
4229
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4331
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4230
4332
  };
4231
4333
  try {
4232
4334
  // Will throw with exit code 1 if the branch does not exist.
@@ -4246,7 +4348,7 @@ async function gitRemoteBranchExists(branch, cwd = process.cwd()) {
4246
4348
  return lsRemoteResult.stdout.length > 0;
4247
4349
  } catch (e) {
4248
4350
  // Expected when remote is not accessible or branch doesn't exist.
4249
- require$$9.debugDir('inspect', {
4351
+ debug$2.debugDir('inspect', {
4250
4352
  message: `Remote branch check failed: ${branch}`,
4251
4353
  error: e
4252
4354
  });
@@ -4262,7 +4364,7 @@ async function gitResetAndClean(branch = 'HEAD', cwd = process.cwd()) {
4262
4364
  async function gitResetHard(branch = 'HEAD', cwd = process.cwd()) {
4263
4365
  const stdioIgnoreOptions = {
4264
4366
  cwd,
4265
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
4367
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
4266
4368
  };
4267
4369
  try {
4268
4370
  await spawn.spawn('git', ['reset', '--hard', branch], stdioIgnoreOptions);
@@ -4288,8 +4390,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
4288
4390
  data: relPaths.map(p => path$1.normalizePath(p))
4289
4391
  };
4290
4392
  } catch (e) {
4291
- require$$9.debugFn('error', 'Failed to get unstaged modified files');
4292
- require$$9.debugDir('error', e);
4393
+ debug$2.debugFn('error', 'Failed to get unstaged modified files');
4394
+ debug$2.debugDir('error', e);
4293
4395
  return {
4294
4396
  ok: false,
4295
4397
  message: 'Git Error',
@@ -4359,8 +4461,16 @@ constants.NODE_MODULES,
4359
4461
  // Where Node modules are installed, see <https://nodejs.org/>
4360
4462
  // Taken from globby:
4361
4463
  // https://github.com/sindresorhus/globby/blob/v14.0.2/ignore.js#L11-L16
4362
- 'flow-typed'];
4464
+ 'flow-typed',
4465
+ // Conventional Python virtual environment dir. Arbitrarily-named venvs are
4466
+ // detected via their pyvenv.cfg marker during the discovery walk below.
4467
+ '.venv'];
4363
4468
  const IGNORED_DIR_PATTERNS = IGNORED_DIRS.map(i => `**/${i}`);
4469
+
4470
+ // Marker file at the root of every Python virtual environment (stdlib `venv`
4471
+ // per PEP 405, and virtualenv >= 20). Lets us detect venvs that don't use a
4472
+ // conventional directory name.
4473
+ const PYVENV_CFG = 'pyvenv.cfg';
4364
4474
  async function getWorkspaceGlobs(agent, cwd = process.cwd()) {
4365
4475
  let workspacePatterns;
4366
4476
  if (agent === constants.PNPM) {
@@ -4481,20 +4591,49 @@ async function globWithGitIgnore(patterns, options) {
4481
4591
  ...options
4482
4592
  };
4483
4593
  const ignores = new Set(IGNORED_DIR_PATTERNS);
4594
+
4595
+ // CLI-supplied `additionalIgnores` are already anchored minimatch — they
4596
+ // must not pass through the `ignore` package (whose gitignore "match
4597
+ // anywhere" semantics would re-interpret a bare `tests` to match
4598
+ // `subdir/tests/foo.json`). Keep them in fast-glob's ignore list across
4599
+ // both paths; only gitignore-translated entries go into the `ig` matcher.
4600
+ const cliMinimatchIgnores = additionalIgnores ?? [];
4484
4601
  const projectIgnorePaths = socketConfig?.projectIgnorePaths;
4485
- if (Array.isArray(projectIgnorePaths)) {
4486
- const ignorePatterns = ignoreFileLinesToGlobPatterns(projectIgnorePaths, path.join(cwd, '.gitignore'), cwd);
4487
- for (const pattern of ignorePatterns) {
4488
- ignores.add(pattern);
4489
- }
4490
- }
4491
- const gitIgnoreStream = vendor.outExports.globStream(['**/.gitignore'], {
4602
+ const projectIgnoreGlobs = Array.isArray(projectIgnorePaths) ? ignoreFileLinesToGlobPatterns(projectIgnorePaths, path.join(cwd, '.gitignore'), cwd) : [];
4603
+ for (const pattern of projectIgnoreGlobs) {
4604
+ ignores.add(pattern);
4605
+ }
4606
+
4607
+ // The discovery walk (`.gitignore` files plus `pyvenv.cfg` venv markers) has
4608
+ // to honor the same directory exclusions as the package walk below. Otherwise
4609
+ // an unreadable subtree (e.g. a postgres `pgdata` dir owned by another uid, or
4610
+ // a Docker volume mount) makes fast-glob throw `EACCES: permission denied,
4611
+ // scandir` *here* — before --exclude-paths (`cliMinimatchIgnores`) or
4612
+ // projectIgnorePaths are ever applied to the main walk, which is why excluding
4613
+ // the path did not help. `suppressErrors` is the backstop: a directory the
4614
+ // user simply cannot read cannot contain manifests they could scan anyway, so
4615
+ // skip it instead of aborting the whole `socket fix` / `socket scan` run.
4616
+ // Negated patterns are dropped — for a discovery walk they could only
4617
+ // re-include a subtree (never prevent a crash), and fast-glob treats `!`
4618
+ // ignore entries inconsistently. Folding pyvenv.cfg discovery into this same
4619
+ // walk avoids a second full-tree traversal.
4620
+ const discoveryStream = vendor.outExports.globStream(['**/.gitignore', `**/${PYVENV_CFG}`], {
4492
4621
  absolute: true,
4493
4622
  cwd,
4494
4623
  dot: true,
4495
- ignore: DEFAULT_IGNORE_FOR_GIT_IGNORE
4624
+ ignore: [...DEFAULT_IGNORE_FOR_GIT_IGNORE, ...projectIgnoreGlobs, ...cliMinimatchIgnores].filter(p => p.charCodeAt(0) !== 33 /*'!'*/).map(stripTrailingSlash),
4625
+ suppressErrors: true
4496
4626
  });
4497
- for await (const ignorePatterns of streams.transform(gitIgnoreStream, async filepath => ignoreFileToGlobPatterns((await fs$1.safeReadFile(filepath)) ?? '', filepath, cwd), {
4627
+ for await (const ignorePatterns of streams.transform(discoveryStream, async filepath => {
4628
+ if (path.basename(filepath) === PYVENV_CFG) {
4629
+ // A pyvenv.cfg sits at the venv root, so exclude the whole directory.
4630
+ const relDir = path.relative(cwd, path.dirname(filepath)).replace(/\\/g, '/');
4631
+ // An empty relDir means the scan target itself is a venv root; don't
4632
+ // emit `/**`, which would exclude everything the user explicitly targeted.
4633
+ return relDir ? [`${relDir}/**`] : [];
4634
+ }
4635
+ return ignoreFileToGlobPatterns((await fs$1.safeReadFile(filepath)) ?? '', filepath, cwd);
4636
+ }, {
4498
4637
  concurrency: 8
4499
4638
  })) {
4500
4639
  for (const p of ignorePatterns) {
@@ -4508,20 +4647,20 @@ async function globWithGitIgnore(patterns, options) {
4508
4647
  break;
4509
4648
  }
4510
4649
  }
4511
-
4512
- // CLI-supplied `additionalIgnores` are already anchored minimatch — they
4513
- // must not pass through the `ignore` package (whose gitignore "match
4514
- // anywhere" semantics would re-interpret a bare `tests` to match
4515
- // `subdir/tests/foo.json`). Keep them in fast-glob's ignore list across
4516
- // both paths; only gitignore-translated entries go into the `ig` matcher.
4517
- const cliMinimatchIgnores = additionalIgnores ?? [];
4518
4650
  const globOptions = {
4519
4651
  __proto__: null,
4520
4652
  absolute: true,
4521
4653
  cwd,
4522
4654
  dot: true,
4523
4655
  ignore: hasNegatedPattern ? [...globs.defaultIgnore, ...cliMinimatchIgnores] : [...ignores, ...cliMinimatchIgnores].map(stripTrailingSlash),
4524
- ...additionalOptions
4656
+ ...additionalOptions,
4657
+ // Skip directories the running user cannot read rather than aborting the
4658
+ // whole walk on the first `EACCES` (see the .gitignore discovery walk
4659
+ // above for the full rationale). Pinned after `...additionalOptions` so a
4660
+ // caller's options bag cannot accidentally flip it back to `false` and
4661
+ // re-introduce the crash — `suppressErrors` is a safety invariant here, not
4662
+ // a tunable.
4663
+ suppressErrors: true
4525
4664
  };
4526
4665
 
4527
4666
  // When no filter is provided and no negated patterns exist, use the fast path.
@@ -4614,14 +4753,14 @@ function pathsToGlobPatterns(paths, cwd) {
4614
4753
 
4615
4754
  function createPurlObject(type, name, options) {
4616
4755
  let opts;
4617
- if (require$$11.isObjectObject(type)) {
4756
+ if (objects.isObjectObject(type)) {
4618
4757
  opts = {
4619
4758
  __proto__: null,
4620
4759
  ...type
4621
4760
  };
4622
4761
  type = opts.type;
4623
4762
  name = opts.name;
4624
- } else if (require$$11.isObjectObject(name)) {
4763
+ } else if (objects.isObjectObject(name)) {
4625
4764
  opts = {
4626
4765
  __proto__: null,
4627
4766
  ...name
@@ -4751,7 +4890,7 @@ function* walkNestedMap(map, keys = []) {
4751
4890
  * Integration:
4752
4891
  * - Works with @coana-tech/cli for reachability analysis
4753
4892
  * - Processes socket facts JSON files
4754
- * - Extracts tier 1 reachability scan identifiers
4893
+ * - Extracts full application reachability scan identifiers
4755
4894
  */
4756
4895
 
4757
4896
  const {
@@ -4818,7 +4957,7 @@ async function compressSocketFactsForUpload(scanPaths) {
4818
4957
  // `rm({ force: true })` no-ops on missing files, so tracking before
4819
4958
  // creation is safe.
4820
4959
  brPaths.push(brPath);
4821
- await promises$1.pipeline(fs.createReadStream(p), node_zlib.createBrotliCompress(), fs.createWriteStream(brPath));
4960
+ await require$$9.pipeline(fs.createReadStream(p), require$$11.createBrotliCompress(), fs.createWriteStream(brPath));
4822
4961
  return brPath;
4823
4962
  }));
4824
4963
  const failure = results.find(r => r.status === 'rejected');
@@ -4936,6 +5075,17 @@ async function findUp(name, options) {
4936
5075
  }
4937
5076
  return undefined;
4938
5077
  }
5078
+ async function withTmpDir(prefix, fn) {
5079
+ const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), prefix));
5080
+ try {
5081
+ return await fn(tmpDir);
5082
+ } finally {
5083
+ await fs.promises.rm(tmpDir, {
5084
+ recursive: true,
5085
+ force: true
5086
+ }).catch(() => {});
5087
+ }
5088
+ }
4939
5089
 
4940
5090
  function findBinPathDetailsSync(binName) {
4941
5091
  const rawBinPaths = bin.whichBinSync(binName, {
@@ -5132,7 +5282,7 @@ function isYarnBerry() {
5132
5282
  * - Configures environment for third-party tools
5133
5283
  */
5134
5284
 
5135
- const require$2 = require$$5.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
5285
+ const require$2 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
5136
5286
  const {
5137
5287
  PACKAGE_LOCK_JSON,
5138
5288
  PNPM_LOCK_YAML,
@@ -5194,20 +5344,27 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
5194
5344
  spawnArgs.push(constants.FLAG_SILENT);
5195
5345
  }
5196
5346
  spawnArgs.push('dlx');
5347
+ // Never let the target project's `.pnpmfile.cjs` hooks run while we launch
5348
+ // a third-party tool via `pnpm dlx`. In a pnpm workspace root, `pnpm dlx`
5349
+ // loads the cwd's `.pnpmfile.cjs`, so a broken hook there (e.g. a `require`
5350
+ // of an unresolved Git LFS pointer) crashes the launcher with a bare exit
5351
+ // code before our tool ever starts. The dlx tool installs into an isolated
5352
+ // store, so the project's install hooks are irrelevant to it. pnpm honors
5353
+ // this only as a config setting, not as a `dlx` CLI flag, so it must be set
5354
+ // via the npm_config_ env var. See: https://pnpm.io/npmrc#settings
5355
+ const pnpmEnv = {
5356
+ ...objects.getOwn(finalShadowOptions, 'env'),
5357
+ npm_config_ignore_pnpmfile: 'true'
5358
+ };
5197
5359
  if (force) {
5198
- // For pnpm, set dlx-cache-max-age to 0 via env to force fresh download.
5199
- // This ensures we always get the latest version within the range.
5200
- finalShadowOptions = {
5201
- ...finalShadowOptions,
5202
- env: {
5203
- ...require$$11.getOwn(finalShadowOptions, 'env'),
5204
- // Set dlx cache max age to 0 minutes to bypass cache.
5205
- // The npm_config_ prefix is how pnpm reads config from environment variables.
5206
- // See: https://pnpm.io/npmrc#settings
5207
- npm_config_dlx_cache_max_age: '0'
5208
- }
5209
- };
5360
+ // Set dlx-cache-max-age to 0 minutes to bypass cache and force a fresh
5361
+ // download. This ensures we always get the latest version within the range.
5362
+ pnpmEnv['npm_config_dlx_cache_max_age'] = '0';
5210
5363
  }
5364
+ finalShadowOptions = {
5365
+ ...finalShadowOptions,
5366
+ env: pnpmEnv
5367
+ };
5211
5368
  spawnArgs.push(packageString, ...args);
5212
5369
  const shadowPnpmBin = /*@__PURE__*/require$2(constants.default.shadowPnpmBinPath);
5213
5370
  return await shadowPnpmBin(spawnArgs, finalShadowOptions, spawnExtra);
@@ -5224,7 +5381,7 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
5224
5381
  finalShadowOptions = {
5225
5382
  ...finalShadowOptions,
5226
5383
  env: {
5227
- ...require$$11.getOwn(finalShadowOptions, 'env'),
5384
+ ...objects.getOwn(finalShadowOptions, 'env'),
5228
5385
  YARN_NODE_LINKER: 'node-modules'
5229
5386
  }
5230
5387
  };
@@ -5254,6 +5411,30 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
5254
5411
  */
5255
5412
  const installedCoanaScriptPathsByVersion = new Map();
5256
5413
 
5414
+ /**
5415
+ * Strip npm-injected `npm_package_*` env vars before spawning a Coana
5416
+ * subprocess. npm (and pnpm/yarn classic) populate one env var per leaf in
5417
+ * the cwd's package.json — `npm_package_dependencies_*`, `npm_package_scripts_*`,
5418
+ * etc. In big monorepos with hundreds of deps this can easily account for
5419
+ * 50KB+ of environment, pushing combined argv + env past Linux ARG_MAX
5420
+ * (~128KB) and causing `spawn` to fail with E2BIG before Coana even starts.
5421
+ *
5422
+ * Coana does not read `npm_package_*` itself, so dropping them is safe. We
5423
+ * intentionally keep `npm_config_*` (registry, cache, proxy settings sourced
5424
+ * from .npmrc), `npm_lifecycle_*`, and everything else untouched — those can
5425
+ * matter for outbound network behavior of nested `npm install` calls.
5426
+ */
5427
+ function sanitizeEnvForCoanaSubprocess(env) {
5428
+ const out = {};
5429
+ for (const key of Object.keys(env)) {
5430
+ if (key.startsWith('npm_package_')) {
5431
+ continue;
5432
+ }
5433
+ out[key] = env[key];
5434
+ }
5435
+ return out;
5436
+ }
5437
+
5257
5438
  /**
5258
5439
  * Spawn an installed Coana entry point via `node` (or directly, if it's a
5259
5440
  * native binary). Shared by the SOCKET_CLI_COANA_LOCAL_PATH branch and the
@@ -5264,8 +5445,8 @@ async function spawnCoanaScriptViaNode(scriptPath, args, finalEnv, options, spaw
5264
5445
  const spawnArgs = isBinary ? args : [scriptPath, ...args];
5265
5446
  const spawnResult = await spawn.spawn(isBinary ? scriptPath : 'node', spawnArgs, {
5266
5447
  cwd: options.cwd,
5267
- env: finalEnv,
5268
- stdio: spawnExtra?.['stdio'] || 'inherit'
5448
+ env: sanitizeEnvForCoanaSubprocess(finalEnv),
5449
+ stdio: options.stdio ?? spawnExtra?.['stdio'] ?? 'inherit'
5269
5450
  });
5270
5451
  return {
5271
5452
  ok: true,
@@ -5309,7 +5490,7 @@ async function installCoanaToTmpdir(version, finalEnv) {
5309
5490
  }
5310
5491
  const installDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'socket-coana-'));
5311
5492
  await spawn.spawn('npm', ['install', '--no-save', '--no-package-lock', '--no-audit', '--no-fund', '--prefix', installDir, `@coana-tech/cli@${version}`], {
5312
- env: finalEnv,
5493
+ env: sanitizeEnvForCoanaSubprocess(finalEnv),
5313
5494
  stdio: 'inherit'
5314
5495
  });
5315
5496
  const scriptPath = await resolveCoanaBinFromInstallDir(installDir);
@@ -5341,6 +5522,38 @@ async function spawnCoanaViaNpmInstall(args, version, finalEnv, options, spawnEx
5341
5522
  return buildDlxErrorResult(e);
5342
5523
  }
5343
5524
  }
5525
+ /**
5526
+ * Resolve how the Coana engine should be launched.
5527
+ *
5528
+ * SOCKET_CLI_COANA_LAUNCHER wins when set:
5529
+ * - 'auto' (default): try dlx first, fall back to `npm install` + `node` on
5530
+ * launcher-level failures.
5531
+ * - 'npm-install': skip dlx entirely; always `npm install` + `node`.
5532
+ * - 'npx': dlx only; never fall back.
5533
+ * Unrecognized values warn and behave as 'auto'.
5534
+ *
5535
+ * The legacy boolean variables SOCKET_CLI_COANA_FORCE_NPM_INSTALL
5536
+ * ('npm-install') and SOCKET_CLI_COANA_DISABLE_NPM_FALLBACK ('npx') are still
5537
+ * honored when the new variable is unset, but are intentionally undocumented.
5538
+ */
5539
+ function getCoanaLauncherMode() {
5540
+ const rawMode = process.env['SOCKET_CLI_COANA_LAUNCHER'];
5541
+ const mode = rawMode?.trim().toLowerCase();
5542
+ if (mode) {
5543
+ if (mode === 'auto' || mode === 'npm-install' || mode === 'npx') {
5544
+ return mode;
5545
+ }
5546
+ logger.logger.warn(`Ignoring unrecognized SOCKET_CLI_COANA_LAUNCHER value "${rawMode}"; expected "auto", "npm-install", or "npx".`);
5547
+ return 'auto';
5548
+ }
5549
+ if (process.env['SOCKET_CLI_COANA_FORCE_NPM_INSTALL']) {
5550
+ return 'npm-install';
5551
+ }
5552
+ if (process.env['SOCKET_CLI_COANA_DISABLE_NPM_FALLBACK']) {
5553
+ return 'npx';
5554
+ }
5555
+ return 'auto';
5556
+ }
5344
5557
 
5345
5558
  /**
5346
5559
  * Helper to spawn coana with dlx.
@@ -5352,9 +5565,10 @@ async function spawnCoanaViaNpmInstall(args, version, finalEnv, options, spawnEx
5352
5565
  *
5353
5566
  * If the dlx path fails (e.g. broken `npx` on the host), falls back to
5354
5567
  * `npm install`-ing @coana-tech/cli into a temp directory and invoking it
5355
- * directly via `node`. The fallback can be disabled with
5356
- * SOCKET_CLI_COANA_DISABLE_NPM_FALLBACK or forced as the primary path with
5357
- * SOCKET_CLI_COANA_FORCE_NPM_INSTALL.
5568
+ * directly via `node`. The launcher strategy can be overridden with
5569
+ * SOCKET_CLI_COANA_LAUNCHER: 'auto' (the default) tries dlx with the
5570
+ * npm-install fallback, 'npm-install' skips dlx entirely, and 'npx' never
5571
+ * falls back.
5358
5572
  */
5359
5573
  async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5360
5574
  const {
@@ -5369,9 +5583,8 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5369
5583
  const mixinsEnv = {
5370
5584
  SOCKET_CLI_VERSION: constants.default.ENV.INLINED_SOCKET_CLI_VERSION,
5371
5585
  // Forwarded to the Coana CLI so it can append our product token to its
5372
- // outbound axios User-Agent header. Format mirrors Coana's base UA:
5373
- // `socket/<version> node/<nodeVersion> <platform>/<arch>`.
5374
- SOCKET_CALLER_USER_AGENT: `socket/${constants.default.ENV.INLINED_SOCKET_CLI_VERSION} node/${process.version} ${process.platform}/${process.arch}`
5586
+ // outbound axios User-Agent header.
5587
+ SOCKET_CALLER_USER_AGENT: getCliUserAgent()
5375
5588
  };
5376
5589
  const defaultApiToken = getDefaultApiToken();
5377
5590
  if (defaultApiToken) {
@@ -5396,23 +5609,38 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5396
5609
  ...spawnEnv
5397
5610
  };
5398
5611
  const resolvedVersion = coanaVersion || constants.default.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION;
5612
+
5613
+ // `shadowNpmBase` (the dlx launcher) configures the child's stdio from its
5614
+ // `options` arg, NOT from the registry-spawn `extra` arg — the latter only
5615
+ // attaches metadata to the result. Callers that requested streaming via
5616
+ // `spawnExtra` (the 4th arg), e.g. `{ stdio: 'inherit' }` from
5617
+ // `socket manifest gradle`, were therefore silently ignored on this path:
5618
+ // Coana ran piped and its output — including the real failure reason — never
5619
+ // reached the user, leaving only an unhelpful "command failed". Resolve the
5620
+ // requested stdio from either argument and honor it on every launch path:
5621
+ // dlx, local-path, and npm-install (e.g. `socket fix --silence` requests
5622
+ // `stdio: 'pipe'` via options).
5623
+ const requestedStdio = spawnExtra?.['stdio'] ?? objects.getOwn(dlxOptions, 'stdio');
5399
5624
  const localCoanaPath = process.env['SOCKET_CLI_COANA_LOCAL_PATH'];
5400
5625
  // Use local Coana CLI if path is provided.
5401
5626
  if (localCoanaPath) {
5402
5627
  try {
5403
5628
  return await spawnCoanaScriptViaNode(localCoanaPath, args, finalEnv, {
5404
- cwd: dlxOptions.cwd
5629
+ cwd: dlxOptions.cwd,
5630
+ stdio: requestedStdio
5405
5631
  }, spawnExtra);
5406
5632
  } catch (e) {
5407
5633
  return buildDlxErrorResult(e);
5408
5634
  }
5409
5635
  }
5636
+ const launcherMode = getCoanaLauncherMode();
5410
5637
 
5411
5638
  // Allow forcing the npm-install path for debugging or for environments
5412
5639
  // where dlx is known-broken.
5413
- if (process.env['SOCKET_CLI_COANA_FORCE_NPM_INSTALL']) {
5640
+ if (launcherMode === 'npm-install') {
5414
5641
  return await spawnCoanaViaNpmInstall(args, resolvedVersion, finalEnv, {
5415
- cwd: dlxOptions.cwd
5642
+ cwd: dlxOptions.cwd,
5643
+ stdio: requestedStdio
5416
5644
  }, spawnExtra);
5417
5645
  }
5418
5646
  try {
@@ -5422,8 +5650,16 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5422
5650
  version: resolvedVersion
5423
5651
  }, args, {
5424
5652
  force: true,
5425
- silent: true,
5653
+ // Do NOT silence the launcher. `--silent` (npm loglevel silent) hides
5654
+ // npm's own download/registry/launch errors, so when npx/pnpm-dlx fails
5655
+ // to fetch @coana-tech/cli the user is left with a bare exit code and no
5656
+ // cause. shadowNpmBase defaults to `--loglevel error`, which keeps real
5657
+ // launcher errors visible while staying quiet on success.
5658
+ silent: false,
5426
5659
  ...dlxOptions,
5660
+ ...(requestedStdio === undefined ? {} : {
5661
+ stdio: requestedStdio
5662
+ }),
5427
5663
  env: finalEnv,
5428
5664
  ipc: {
5429
5665
  [constants.default.SOCKET_CLI_SHADOW_ACCEPT_RISKS]: true,
@@ -5439,7 +5675,7 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5439
5675
  };
5440
5676
  } catch (e) {
5441
5677
  const dlxError = buildDlxErrorResult(e);
5442
- if (process.env['SOCKET_CLI_COANA_DISABLE_NPM_FALLBACK']) {
5678
+ if (launcherMode === 'npx') {
5443
5679
  return dlxError;
5444
5680
  }
5445
5681
 
@@ -5449,9 +5685,10 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5449
5685
  if (!shouldFallbackOnDlxError(e)) {
5450
5686
  return dlxError;
5451
5687
  }
5452
- logger.logger.warn('Coana dlx invocation failed before Coana started; falling back to `npm install` + `node`.');
5688
+ logger.logger.warn('Coana dlx invocation failed; retrying via `npm install` + `node`.');
5453
5689
  const fallbackResult = await spawnCoanaViaNpmInstall(args, resolvedVersion, finalEnv, {
5454
- cwd: dlxOptions.cwd
5690
+ cwd: dlxOptions.cwd,
5691
+ stdio: requestedStdio
5455
5692
  }, spawnExtra);
5456
5693
  if (fallbackResult.ok) {
5457
5694
  return fallbackResult;
@@ -5485,10 +5722,29 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
5485
5722
  * rather than blindly re-running Coana.
5486
5723
  */
5487
5724
  function shouldFallbackOnDlxError(e) {
5488
- const capturedStderr = String(e?.stderr ?? '');
5489
- if (capturedStderr && /Coana CLI version/i.test(capturedStderr)) {
5725
+ // Coana clearly ran (its banner is in the captured stderr) → any later
5726
+ // non-zero exit is a real Coana failure and retrying would hit it again.
5727
+ if (coanaBannerSeen(e)) {
5490
5728
  return false;
5491
5729
  }
5730
+ return dlxLauncherFailedBeforeCoana(e);
5731
+ }
5732
+
5733
+ /**
5734
+ * Heuristic: did the dlx launcher (npx / pnpm dlx / yarn dlx) fail BEFORE the
5735
+ * Coana process itself started? True for spawn-level errors (a string `code`
5736
+ * like ENOENT), signal kills, and exit codes >= 128 (conventionally
5737
+ * signal-derived) — all cases where the launcher, not Coana, is the culprit
5738
+ * (e.g. npx missing from PATH, or @coana-tech/cli failing to download). A small
5739
+ * integer exit code is deliberately NOT treated as a launch failure: Coana's
5740
+ * own exit codes are small integers too, so it is genuinely ambiguous.
5741
+ *
5742
+ * Caveat: a launcher that fails to download the package can also exit with a
5743
+ * small integer (npm/npx often exit 1), which lands in the ambiguous bucket.
5744
+ * We cannot disambiguate those from a real Coana exit without inspecting the
5745
+ * launcher's output, so the npm-install fallback does not fire for them.
5746
+ */
5747
+ function dlxLauncherFailedBeforeCoana(e) {
5492
5748
  const code = e?.code;
5493
5749
  // Spawn-level failure (e.g. ENOENT when npx is missing from PATH).
5494
5750
  if (typeof code === 'string') {
@@ -5500,10 +5756,18 @@ function shouldFallbackOnDlxError(e) {
5500
5756
  }
5501
5757
  // Exit codes >= 128 are conventionally signal-derived, and the observed
5502
5758
  // npx-launcher failures in the wild fall into this range (e.g. 249, 254).
5503
- if (typeof code === 'number' && code >= 128) {
5504
- return true;
5505
- }
5506
- return false;
5759
+ return typeof code === 'number' && code >= 128;
5760
+ }
5761
+
5762
+ /**
5763
+ * Definitive proof Coana actually booted: its startup banner appears in the
5764
+ * captured stderr. Only available when the launcher's output was piped
5765
+ * (captured); with inherited stdio there is nothing to inspect, so this
5766
+ * returns false (the failure is then classified by exit code / signal alone).
5767
+ */
5768
+ function coanaBannerSeen(e) {
5769
+ const capturedStderr = String(e?.stderr ?? '');
5770
+ return !!capturedStderr && /Coana CLI version/i.test(capturedStderr);
5507
5771
  }
5508
5772
 
5509
5773
  /**
@@ -5512,6 +5776,7 @@ function shouldFallbackOnDlxError(e) {
5512
5776
  */
5513
5777
  function buildDlxErrorResult(e) {
5514
5778
  const stderr = e?.stderr;
5779
+ const stdout = e?.stdout;
5515
5780
  const exitCode = e?.code;
5516
5781
  const signal = e?.signal;
5517
5782
  const cause = getErrorCause(e);
@@ -5523,7 +5788,29 @@ function buildDlxErrorResult(e) {
5523
5788
  details.push(`signal ${signal}`);
5524
5789
  }
5525
5790
  const detailSuffix = details.length ? ` (${details.join(', ')})` : '';
5526
- const message = stderr ? `Coana command failed${detailSuffix}: ${stderr}` : `Coana command failed${detailSuffix}: ${cause}`;
5791
+ // Prefer captured stderr, then stdout, then the generic spawn error. Coana
5792
+ // logs some failures (e.g. unresolved Gradle dependencies) to stdout, so
5793
+ // without the stdout fallback a piped failure collapsed to an unhelpful
5794
+ // "command failed" even when the real reason was captured.
5795
+ const detail = stderr || stdout || cause;
5796
+ // Be honest about WHERE the failure happened. On the dlx path the spawned
5797
+ // process is the package-manager launcher (npx / pnpm dlx / yarn dlx), which
5798
+ // downloads @coana-tech/cli and only then runs it — so a failure may be the
5799
+ // launcher dying before Coana ever started, not Coana itself. We can only be
5800
+ // CERTAIN of that for a spawn-level error (a string `code` like ENOENT: the
5801
+ // launcher binary could not start, so Coana provably never ran). A non-zero
5802
+ // exit or signal is genuinely ambiguous — Coana may have started, streamed
5803
+ // output, and then died (e.g. OOM), or the launcher may have failed to fetch
5804
+ // the package — and with inherited stdio there is no captured output to tell
5805
+ // them apart, so we must not assert either way.
5806
+ let message;
5807
+ if (coanaBannerSeen(e)) {
5808
+ message = `Coana command failed${detailSuffix}: ${detail}`;
5809
+ } else if (typeof e?.code === 'string') {
5810
+ message = `Failed to launch Coana via the package manager${detailSuffix} — the npx/pnpm-dlx/yarn-dlx launcher could not start (e.g. it is missing from PATH): ${detail}`;
5811
+ } else {
5812
+ message = `Coana failed to run via the package manager${detailSuffix}: ${detail}`;
5813
+ }
5527
5814
  return {
5528
5815
  ok: false,
5529
5816
  data: e,
@@ -5622,7 +5909,7 @@ function getDefaultSocketJson() {
5622
5909
  function readSocketJsonSync(cwd, defaultOnError = false) {
5623
5910
  const sockJsonPath = path.join(cwd, constants.SOCKET_JSON);
5624
5911
  if (!fs.existsSync(sockJsonPath)) {
5625
- require$$9.debugFn('notice', `miss: ${constants.SOCKET_JSON} not found at ${cwd}`);
5912
+ debug$2.debugFn('notice', `miss: ${constants.SOCKET_JSON} not found at ${cwd}`);
5626
5913
  return {
5627
5914
  ok: true,
5628
5915
  data: getDefaultSocketJson()
@@ -5634,16 +5921,16 @@ function readSocketJsonSync(cwd, defaultOnError = false) {
5634
5921
  } catch (e) {
5635
5922
  if (defaultOnError) {
5636
5923
  logger.logger.warn(`Failed to read ${constants.SOCKET_JSON}, using default`);
5637
- require$$9.debugFn('warn', `Failed to read ${constants.SOCKET_JSON} sync`);
5638
- require$$9.debugDir('warn', e);
5924
+ debug$2.debugFn('warn', `Failed to read ${constants.SOCKET_JSON} sync`);
5925
+ debug$2.debugDir('warn', e);
5639
5926
  return {
5640
5927
  ok: true,
5641
5928
  data: getDefaultSocketJson()
5642
5929
  };
5643
5930
  }
5644
5931
  const cause = formatErrorWithDetail(`An error occurred while trying to read ${constants.SOCKET_JSON}`, e);
5645
- require$$9.debugFn('error', `Failed to read ${constants.SOCKET_JSON} sync`);
5646
- require$$9.debugDir('error', e);
5932
+ debug$2.debugFn('error', `Failed to read ${constants.SOCKET_JSON} sync`);
5933
+ debug$2.debugDir('error', e);
5647
5934
  return {
5648
5935
  ok: false,
5649
5936
  message: `Failed to read ${constants.SOCKET_JSON}`,
@@ -5654,11 +5941,11 @@ function readSocketJsonSync(cwd, defaultOnError = false) {
5654
5941
  try {
5655
5942
  jsonObj = JSON.parse(jsonContent);
5656
5943
  } catch (e) {
5657
- require$$9.debugFn('error', `Failed to parse ${constants.SOCKET_JSON} as JSON (sync)`);
5658
- require$$9.debugDir('inspect', {
5944
+ debug$2.debugFn('error', `Failed to parse ${constants.SOCKET_JSON} as JSON (sync)`);
5945
+ debug$2.debugDir('inspect', {
5659
5946
  jsonContent
5660
5947
  });
5661
- require$$9.debugDir('error', e);
5948
+ debug$2.debugDir('error', e);
5662
5949
  if (defaultOnError) {
5663
5950
  logger.logger.warn(`Failed to parse ${constants.SOCKET_JSON}, using default`);
5664
5951
  return {
@@ -5692,11 +5979,11 @@ async function writeSocketJson(cwd, sockJson) {
5692
5979
  try {
5693
5980
  jsonContent = JSON.stringify(sockJson, null, 2);
5694
5981
  } catch (e) {
5695
- require$$9.debugFn('error', `Failed to serialize ${constants.SOCKET_JSON} to JSON`);
5696
- require$$9.debugDir('inspect', {
5982
+ debug$2.debugFn('error', `Failed to serialize ${constants.SOCKET_JSON} to JSON`);
5983
+ debug$2.debugDir('inspect', {
5697
5984
  sockJson
5698
5985
  });
5699
- require$$9.debugDir('error', e);
5986
+ debug$2.debugDir('error', e);
5700
5987
  return {
5701
5988
  ok: false,
5702
5989
  message: 'Failed to serialize to JSON',
@@ -5812,12 +6099,12 @@ async function fetchGhsaDetails(ids) {
5812
6099
  if (advisory && advisory.ghsaId) {
5813
6100
  results.set(id, advisory);
5814
6101
  } else {
5815
- require$$9.debugFn('notice', `miss: no advisory found for ${id}`);
6102
+ debug$2.debugFn('notice', `miss: no advisory found for ${id}`);
5816
6103
  }
5817
6104
  }
5818
6105
  } catch (e) {
5819
- require$$9.debugFn('error', formatErrorWithDetail('Failed to fetch GHSA details', e));
5820
- require$$9.debugDir('error', e);
6106
+ debug$2.debugFn('error', formatErrorWithDetail('Failed to fetch GHSA details', e));
6107
+ debug$2.debugDir('error', e);
5821
6108
  }
5822
6109
  return results;
5823
6110
  }
@@ -5828,13 +6115,13 @@ function getOctokit() {
5828
6115
  SOCKET_CLI_GITHUB_TOKEN
5829
6116
  } = constants.default.ENV;
5830
6117
  if (!SOCKET_CLI_GITHUB_TOKEN) {
5831
- require$$9.debugFn('notice', 'miss: SOCKET_CLI_GITHUB_TOKEN env var');
6118
+ debug$2.debugFn('notice', 'miss: SOCKET_CLI_GITHUB_TOKEN env var');
5832
6119
  }
5833
6120
  const octokitOptions = {
5834
6121
  auth: SOCKET_CLI_GITHUB_TOKEN,
5835
6122
  baseUrl: constants.default.ENV.GITHUB_API_URL
5836
6123
  };
5837
- require$$9.debugDir('inspect', {
6124
+ debug$2.debugDir('inspect', {
5838
6125
  octokitOptions
5839
6126
  });
5840
6127
  _octokit = new vendor.Octokit(octokitOptions);
@@ -5848,7 +6135,7 @@ function getOctokitGraphql() {
5848
6135
  SOCKET_CLI_GITHUB_TOKEN
5849
6136
  } = constants.default.ENV;
5850
6137
  if (!SOCKET_CLI_GITHUB_TOKEN) {
5851
- require$$9.debugFn('notice', 'miss: SOCKET_CLI_GITHUB_TOKEN env var');
6138
+ debug$2.debugFn('notice', 'miss: SOCKET_CLI_GITHUB_TOKEN env var');
5852
6139
  }
5853
6140
  _octokitGraphql = vendor.graphql2.defaults({
5854
6141
  headers: {
@@ -5901,31 +6188,31 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
5901
6188
  const {
5902
6189
  GITHUB_SERVER_URL
5903
6190
  } = constants.default.ENV;
5904
- const urlObj = require$$13.parseUrl(GITHUB_SERVER_URL);
6191
+ const urlObj = url.parseUrl(GITHUB_SERVER_URL);
5905
6192
  const host = urlObj?.host;
5906
6193
  if (!host) {
5907
- require$$9.debugFn('error', 'invalid: GITHUB_SERVER_URL env var');
5908
- require$$9.debugDir('inspect', {
6194
+ debug$2.debugFn('error', 'invalid: GITHUB_SERVER_URL env var');
6195
+ debug$2.debugDir('inspect', {
5909
6196
  GITHUB_SERVER_URL
5910
6197
  });
5911
6198
  return false;
5912
6199
  }
5913
- const url = `https://x-access-token:${token}@${host}/${owner}/${repo}`;
6200
+ const url$1 = `https://x-access-token:${token}@${host}/${owner}/${repo}`;
5914
6201
  const stdioIgnoreOptions = {
5915
6202
  cwd,
5916
- stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
6203
+ stdio: debug$2.isDebug('stdio') ? 'inherit' : 'ignore'
5917
6204
  };
5918
- const quotedCmd = `\`git remote set-url origin ${url}\``;
5919
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
6205
+ const quotedCmd = `\`git remote set-url origin ${url$1}\``;
6206
+ debug$2.debugFn('stdio', `spawn: ${quotedCmd}`);
5920
6207
  try {
5921
- await spawn.spawn('git', ['remote', 'set-url', 'origin', url], stdioIgnoreOptions);
6208
+ await spawn.spawn('git', ['remote', 'set-url', 'origin', url$1], stdioIgnoreOptions);
5922
6209
  return true;
5923
6210
  } catch (e) {
5924
- require$$9.debugFn('error', `Git command failed: ${quotedCmd}`);
5925
- require$$9.debugDir('inspect', {
6211
+ debug$2.debugFn('error', `Git command failed: ${quotedCmd}`);
6212
+ debug$2.debugDir('inspect', {
5926
6213
  cmd: quotedCmd
5927
6214
  });
5928
- require$$9.debugDir('error', e);
6215
+ debug$2.debugDir('error', e);
5929
6216
  }
5930
6217
  return false;
5931
6218
  }
@@ -6218,11 +6505,31 @@ function isPnpmLockfileScanCommand(command) {
6218
6505
  // export type _Check_EcosystemString_has_all_purl_types =
6219
6506
  // ExpectNever<MissingInEcosystemString>
6220
6507
 
6221
- const ALL_ECOSYSTEMS = ['alpm', 'apk', 'bitbucket', 'cargo', 'chrome', 'cocoapods', 'composer', 'conan', 'conda', 'cran', 'deb', 'docker', 'gem', 'generic', 'github', 'golang', 'hackage', 'hex', 'huggingface', 'maven', 'mlflow', constants.NPM, 'nuget', 'oci', 'pub', 'pypi', 'qpkg', 'rpm', 'swift', 'swid', 'unknown', 'vscode'];
6508
+ const ALL_ECOSYSTEMS = ['alpm', 'apk', 'bitbucket', 'cargo', 'chrome', 'clawhub', 'cocoapods', 'composer', 'conan', 'conda', 'cran', 'deb', 'docker', 'gem', 'generic', 'github', 'golang', 'hackage', 'hex', 'huggingface', 'maven', 'mlflow', constants.NPM, 'nuget', 'oci', 'pub', 'pypi', 'qpkg', 'rpm', 'socket', 'swift', 'swid', 'unknown', 'vscode'];
6222
6509
  new Set(ALL_ECOSYSTEMS);
6510
+
6511
+ // Purl types accepted by Coana's reachability `--purl-types` gate
6512
+ // (@coana-tech/cli `getAdvisoryEcosystemFromPurlType`), narrower than
6513
+ // ALL_ECOSYSTEMS. Values outside this set are rejected by the engine at scan
6514
+ // time, so we validate up front. Keep in sync when bumping @coana-tech/cli.
6515
+ const REACHABILITY_SUPPORTED_ECOSYSTEMS = ['cargo', 'composer', 'gem', 'golang', 'maven', constants.NPM, 'nuget', 'pypi'];
6223
6516
  function getEcosystemChoicesForMeow() {
6224
6517
  return [...ALL_ECOSYSTEMS];
6225
6518
  }
6519
+ function getReachabilityEcosystemChoices() {
6520
+ return [...REACHABILITY_SUPPORTED_ECOSYSTEMS];
6521
+ }
6522
+ function parseReachEcosystems(raw) {
6523
+ const choices = getReachabilityEcosystemChoices();
6524
+ const result = [];
6525
+ for (const ecosystem of raw) {
6526
+ if (!choices.includes(ecosystem)) {
6527
+ throw new InputError(`Invalid ecosystem: "${ecosystem}". Valid values are: ${arrays.joinAnd(choices)}`);
6528
+ }
6529
+ result.push(ecosystem);
6530
+ }
6531
+ return result;
6532
+ }
6226
6533
 
6227
6534
  /**
6228
6535
  * Package manager identifiers accepted by Coana's --package-managers filter.
@@ -6401,7 +6708,7 @@ function getNpmRequire() {
6401
6708
  if (_npmRequire === undefined) {
6402
6709
  const npmDirPath = getNpmDirPath();
6403
6710
  const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
6404
- _npmRequire = require$$5.createRequire(path.join(fs.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
6711
+ _npmRequire = require$$1.createRequire(path.join(fs.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
6405
6712
  }
6406
6713
  return _npmRequire;
6407
6714
  }
@@ -6453,7 +6760,7 @@ function shadowNpmInstall(options) {
6453
6760
  __proto__: null,
6454
6761
  ...options
6455
6762
  };
6456
- const useDebug = require$$9.isDebug('stdio');
6763
+ const useDebug = debug$2.isDebug('stdio');
6457
6764
  const terminatorPos = args.indexOf('--');
6458
6765
  const rawBinArgs = terminatorPos === -1 ? args : args.slice(0, terminatorPos);
6459
6766
  const binArgs = rawBinArgs.filter(a => !agent.isNpmAuditFlag(a) && !agent.isNpmFundFlag(a) && !agent.isNpmProgressFlag(a));
@@ -6461,12 +6768,12 @@ function shadowNpmInstall(options) {
6461
6768
  const progressArg = rawBinArgs.findLast(agent.isNpmProgressFlag) !== '--no-progress';
6462
6769
  const isSilent = !useDebug && !binArgs.some(agent.isNpmLoglevelFlag);
6463
6770
  const logLevelArgs = isSilent ? [constants.FLAG_LOGLEVEL, 'silent'] : [];
6464
- const useIpc = require$$11.isObject(ipc);
6771
+ const useIpc = objects.isObject(ipc);
6465
6772
 
6466
6773
  // Include 'ipc' in the spawnOpts.stdio when an options.ipc object is provided.
6467
6774
  // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
6468
6775
  // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
6469
- let stdio = require$$11.getOwn(spawnOpts, 'stdio');
6776
+ let stdio = objects.getOwn(spawnOpts, 'stdio');
6470
6777
  if (typeof stdio === 'string') {
6471
6778
  stdio = useIpc ? [stdio, stdio, stdio, 'ipc'] : [stdio, stdio, stdio];
6472
6779
  } else if (Array.isArray(stdio)) {
@@ -6488,7 +6795,7 @@ function shadowNpmInstall(options) {
6488
6795
  env: {
6489
6796
  ...process.env,
6490
6797
  ...constants.default.processEnv,
6491
- ...require$$11.getOwn(spawnOpts, 'env')
6798
+ ...objects.getOwn(spawnOpts, 'env')
6492
6799
  },
6493
6800
  spinner,
6494
6801
  stdio
@@ -6569,7 +6876,7 @@ function runAgentInstall(pkgEnvDetails, options) {
6569
6876
  CI: '1'
6570
6877
  } : {}),
6571
6878
  NODE_OPTIONS: cmdFlagsToString([...(skipNodeHardenFlags ? [] : constants.default.nodeHardenFlags), ...constants.default.nodeNoWarningsFlags]),
6572
- ...require$$11.getOwn(spawnOpts, 'env')
6879
+ ...objects.getOwn(spawnOpts, 'env')
6573
6880
  }
6574
6881
  });
6575
6882
  }
@@ -6751,7 +7058,7 @@ async function getAgentExecPath(agent) {
6751
7058
  async function getAgentVersion(agent, agentExecPath, cwd) {
6752
7059
  let result;
6753
7060
  const quotedCmd = `\`${agent} ${constants.FLAG_VERSION}\``;
6754
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
7061
+ debug$2.debugFn('stdio', `spawn: ${quotedCmd}`);
6755
7062
  try {
6756
7063
  let stdout;
6757
7064
 
@@ -6767,8 +7074,8 @@ async function getAgentVersion(agent, agentExecPath, cwd) {
6767
7074
  shouldRunWithNode = resolved;
6768
7075
  }
6769
7076
  } catch (e) {
6770
- require$$9.debugFn('warn', `Failed to resolve bin path for ${agentExecPath}, falling back to direct spawn.`);
6771
- require$$9.debugDir('error', e);
7077
+ debug$2.debugFn('warn', `Failed to resolve bin path for ${agentExecPath}, falling back to direct spawn.`);
7078
+ debug$2.debugDir('error', e);
6772
7079
  }
6773
7080
  }
6774
7081
  if (shouldRunWithNode) {
@@ -6790,11 +7097,11 @@ async function getAgentVersion(agent, agentExecPath, cwd) {
6790
7097
  // and tildes (~).
6791
7098
  vendor.semverExports.coerce(stdout) ?? undefined;
6792
7099
  } catch (e) {
6793
- require$$9.debugFn('error', `Package manager command failed: ${quotedCmd}`);
6794
- require$$9.debugDir('inspect', {
7100
+ debug$2.debugFn('error', `Package manager command failed: ${quotedCmd}`);
7101
+ debug$2.debugDir('inspect', {
6795
7102
  cmd: quotedCmd
6796
7103
  });
6797
- require$$9.debugDir('error', e);
7104
+ debug$2.debugDir('error', e);
6798
7105
  }
6799
7106
  return result;
6800
7107
  }
@@ -7023,6 +7330,20 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
7023
7330
  };
7024
7331
  }
7025
7332
 
7333
+ // Check the public npm registry for a newer socket release.
7334
+ async function runSelfUpdateCheck() {
7335
+ await vendor.updater({
7336
+ name: constants.default.SOCKET_CLI_BIN_NAME,
7337
+ registryUrl: 'https://registry.npmjs.org/',
7338
+ ttl: 86_400_000 /* 24 hours in milliseconds */,
7339
+ version: constants.default.ENV.INLINED_SOCKET_CLI_VERSION,
7340
+ logCallback: (name, version, latest) => {
7341
+ logger.logger.log(`\n\nšŸ“¦ Update available for ${vendor.yoctocolorsCjsExports.cyan(name)}: ${vendor.yoctocolorsCjsExports.gray(version)} → ${vendor.yoctocolorsCjsExports.green(latest)}`);
7342
+ logger.logger.log(`šŸ“ ${socketPackageLink('npm', name, `files/${latest}/CHANGELOG.md`, 'View changelog')}`);
7343
+ }
7344
+ });
7345
+ }
7346
+
7026
7347
  /**
7027
7348
  * Temporary package executor detection utilities for Socket CLI.
7028
7349
  * Identifies and handles temporary execution contexts.
@@ -7309,7 +7630,7 @@ function toFilterConfig(obj) {
7309
7630
  const normalized = {
7310
7631
  __proto__: null
7311
7632
  };
7312
- const keys = require$$11.isObject(obj) ? Object.keys(obj) : [];
7633
+ const keys = objects.isObject(obj) ? Object.keys(obj) : [];
7313
7634
  for (const key of keys) {
7314
7635
  const value = obj[key];
7315
7636
  if (typeof value === 'boolean' || Array.isArray(value)) {
@@ -7362,7 +7683,7 @@ function parsePnpmLockfile(lockfileContent) {
7362
7683
  result = vendor.jsYaml.load(strings.stripBom(lockfileContent));
7363
7684
  } catch {}
7364
7685
  }
7365
- return require$$11.isObjectObject(result) ? result : null;
7686
+ return objects.isObjectObject(result) ? result : null;
7366
7687
  }
7367
7688
  async function readPnpmLockfile(lockfilePath) {
7368
7689
  return fs.existsSync(lockfilePath) ? await fs$1.readFileUtf8(lockfilePath) : undefined;
@@ -7463,7 +7784,7 @@ class ColorOrMarkdown {
7463
7784
  }
7464
7785
  }
7465
7786
 
7466
- const require$1 = require$$5.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
7787
+ const require$1 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
7467
7788
  let _translations;
7468
7789
  function getTranslations() {
7469
7790
  if (_translations === undefined) {
@@ -7573,8 +7894,13 @@ async function addArtifactToAlertsMap(artifact, alertsByPurl, options) {
7573
7894
  blocked: true,
7574
7895
  critical: true,
7575
7896
  cve: true,
7576
- ...require$$11.getOwn(options, 'filter')
7897
+ ...objects.getOwn(options, 'filter')
7577
7898
  });
7899
+
7900
+ // `issueRules` is a user-provided YAML map typed as
7901
+ // `{ [issueName: string]: boolean }`, so key by `string` here. A string
7902
+ // index signature also keeps the `enabledState[alert.type]` lookup below
7903
+ // well-typed regardless of how `alert.type` resolves.
7578
7904
  const enabledState = {
7579
7905
  __proto__: null,
7580
7906
  ...socketYml?.issueRules
@@ -7593,7 +7919,7 @@ async function addArtifactToAlertsMap(artifact, alertsByPurl, options) {
7593
7919
  const fixableCve = fixType === ALERT_FIX_TYPE.cve;
7594
7920
  const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade;
7595
7921
  const fixable = fixableCve || fixableUpgrade;
7596
- const upgradable = fixableUpgrade && !require$$11.hasOwn(overrides, name);
7922
+ const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name);
7597
7923
  if (filterConfig.blocked && blocked || filterConfig.critical && critical || filterConfig.cve && cve || filterConfig.fixable && fixable || filterConfig.upgradable && upgradable) {
7598
7924
  sockPkgAlerts.push({
7599
7925
  name,
@@ -7867,7 +8193,7 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
7867
8193
  }
7868
8194
  async function getAlertsMapFromPurls(purls, options) {
7869
8195
  const uniqPurls = arrays.arrayUnique(purls);
7870
- require$$9.debugDir('silly', {
8196
+ debug$2.debugDir('silly', {
7871
8197
  purls: uniqPurls
7872
8198
  });
7873
8199
  let {
@@ -7882,7 +8208,7 @@ async function getAlertsMapFromPurls(purls, options) {
7882
8208
  consolidate: false,
7883
8209
  nothrow: false,
7884
8210
  ...options,
7885
- filter: toFilterConfig(require$$11.getOwn(options, 'filter'))
8211
+ filter: toFilterConfig(objects.getOwn(options, 'filter'))
7886
8212
  };
7887
8213
  if (opts.onlyFixable) {
7888
8214
  opts.filter.fixable = true;
@@ -7940,7 +8266,7 @@ async function getAlertsMapFromPurls(purls, options) {
7940
8266
  } else {
7941
8267
  spinner?.stop();
7942
8268
  logger.logger.fail(`Received a ${batchResult.status} response from Socket API which we consider a permanent failure:`, batchResult.error, batchResult.cause ? `( ${batchResult.cause} )` : '');
7943
- require$$9.debugDir('inspect', {
8269
+ debug$2.debugDir('inspect', {
7944
8270
  batchResult
7945
8271
  });
7946
8272
  break;
@@ -8091,6 +8417,7 @@ function safeNpmSpecToPurl(pkgSpec) {
8091
8417
  exports.ALL_PACKAGE_MANAGERS = ALL_PACKAGE_MANAGERS;
8092
8418
  exports.AuthError = AuthError;
8093
8419
  exports.COMPLETION_CMD_PREFIX = COMPLETION_CMD_PREFIX;
8420
+ exports.IGNORED_DIRS = IGNORED_DIRS;
8094
8421
  exports.InputError = InputError;
8095
8422
  exports.RangeStyles = RangeStyles;
8096
8423
  exports.apiFetch = apiFetch;
@@ -8145,6 +8472,7 @@ exports.getOrgSlugs = getOrgSlugs;
8145
8472
  exports.getOutputKind = getOutputKind;
8146
8473
  exports.getPackageFilesForScan = getPackageFilesForScan;
8147
8474
  exports.getPublicApiToken = getPublicApiToken;
8475
+ exports.getReachabilityEcosystemChoices = getReachabilityEcosystemChoices;
8148
8476
  exports.getRepoInfo = getRepoInfo;
8149
8477
  exports.getRepoName = getRepoName;
8150
8478
  exports.getRepoOwner = getRepoOwner;
@@ -8191,13 +8519,16 @@ exports.meowOrExit = meowOrExit;
8191
8519
  exports.meowWithSubcommands = meowWithSubcommands;
8192
8520
  exports.msAtHome = msAtHome;
8193
8521
  exports.parsePnpmLockfile = parsePnpmLockfile;
8522
+ exports.parseReachEcosystems = parseReachEcosystems;
8194
8523
  exports.queryApiSafeJson = queryApiSafeJson;
8195
8524
  exports.queryApiSafeText = queryApiSafeText;
8525
+ exports.queryApiSafeTextWithStatus = queryApiSafeTextWithStatus;
8196
8526
  exports.readOrDefaultSocketJson = readOrDefaultSocketJson;
8197
8527
  exports.readOrDefaultSocketJsonUp = readOrDefaultSocketJsonUp;
8198
8528
  exports.readPnpmLockfile = readPnpmLockfile;
8199
8529
  exports.readSocketJsonSync = readSocketJsonSync;
8200
8530
  exports.runAgentInstall = runAgentInstall;
8531
+ exports.runSelfUpdateCheck = runSelfUpdateCheck;
8201
8532
  exports.safeNpa = safeNpa$1;
8202
8533
  exports.safeNpmSpecToPurl = safeNpmSpecToPurl;
8203
8534
  exports.sendApiRequest = sendApiRequest;
@@ -8208,7 +8539,6 @@ exports.setupTelemetryExitHandlers = setupTelemetryExitHandlers;
8208
8539
  exports.socketDashboardLink = socketDashboardLink;
8209
8540
  exports.socketDevLink = socketDevLink;
8210
8541
  exports.socketDocsLink = socketDocsLink;
8211
- exports.socketPackageLink = socketPackageLink;
8212
8542
  exports.spawnCdxgenDlx = spawnCdxgenDlx;
8213
8543
  exports.spawnCoanaDlx = spawnCoanaDlx;
8214
8544
  exports.spawnSynpDlx = spawnSynpDlx;
@@ -8224,6 +8554,7 @@ exports.trackSubprocessStart = trackSubprocessStart;
8224
8554
  exports.updateConfigValue = updateConfigValue;
8225
8555
  exports.walkNestedMap = walkNestedMap;
8226
8556
  exports.webLink = webLink;
8557
+ exports.withTmpDir = withTmpDir;
8227
8558
  exports.writeSocketJson = writeSocketJson;
8228
- //# debugId=3d2a7b08-ceff-43f9-8aea-9e31467b851b
8559
+ //# debugId=42fc0b13-4cfc-491d-a46f-94274b113cbc
8229
8560
  //# sourceMappingURL=utils.js.map