@socketsecurity/cli-with-sentry 1.1.17 → 1.1.19

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 (134) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/bin/npm-cli.js +2 -2
  3. package/bin/npx-cli.js +2 -2
  4. package/bin/pnpm-cli.js +2 -2
  5. package/bin/yarn-cli.js +2 -2
  6. package/dist/cli.js +238 -94
  7. package/dist/cli.js.map +1 -1
  8. package/dist/constants.js +5 -3
  9. package/dist/constants.js.map +1 -1
  10. package/dist/flags.js +3 -2
  11. package/dist/flags.js.map +1 -1
  12. package/dist/npm-cli.js +3 -4
  13. package/dist/npm-cli.js.map +1 -1
  14. package/dist/npx-cli.js +3 -3
  15. package/dist/npx-cli.js.map +1 -1
  16. package/dist/pnpm-cli.js +3 -3
  17. package/dist/pnpm-cli.js.map +1 -1
  18. package/dist/shadow-npm-bin.js +3 -106
  19. package/dist/shadow-npm-bin.js.map +1 -1
  20. package/dist/shadow-npm-bin2.js +125 -0
  21. package/dist/shadow-npm-bin2.js.map +1 -0
  22. package/dist/shadow-npx-bin.js +12 -0
  23. package/dist/shadow-npx-bin.js.map +1 -0
  24. package/dist/shadow-pnpm-bin.js +3 -228
  25. package/dist/shadow-pnpm-bin.js.map +1 -1
  26. package/dist/shadow-pnpm-bin2.js +319 -0
  27. package/dist/shadow-pnpm-bin2.js.map +1 -0
  28. package/dist/shadow-yarn-bin.js +58 -150
  29. package/dist/shadow-yarn-bin.js.map +1 -1
  30. package/dist/tsconfig.dts.tsbuildinfo +1 -1
  31. package/dist/types/commands/analytics/cmd-analytics.d.mts.map +1 -1
  32. package/dist/types/commands/analytics/output-analytics.d.mts.map +1 -1
  33. package/dist/types/commands/audit-log/cmd-audit-log.d.mts.map +1 -1
  34. package/dist/types/commands/audit-log/output-audit-log.d.mts.map +1 -1
  35. package/dist/types/commands/ci/handle-ci.d.mts.map +1 -1
  36. package/dist/types/commands/config/cmd-config-auto.d.mts.map +1 -1
  37. package/dist/types/commands/config/cmd-config-get.d.mts.map +1 -1
  38. package/dist/types/commands/config/cmd-config-list.d.mts.map +1 -1
  39. package/dist/types/commands/config/cmd-config-set.d.mts.map +1 -1
  40. package/dist/types/commands/config/cmd-config-unset.d.mts.map +1 -1
  41. package/dist/types/commands/config/handle-config-set.d.mts.map +1 -1
  42. package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
  43. package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
  44. package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
  45. package/dist/types/commands/fix/pull-request.d.mts.map +1 -1
  46. package/dist/types/commands/manifest/cmd-manifest-conda.d.mts.map +1 -1
  47. package/dist/types/commands/npm/cmd-npm.d.mts.map +1 -1
  48. package/dist/types/commands/optimize/handle-optimize.d.mts.map +1 -1
  49. package/dist/types/commands/organization/cmd-organization-dependencies.d.mts.map +1 -1
  50. package/dist/types/commands/organization/cmd-organization-list.d.mts.map +1 -1
  51. package/dist/types/commands/organization/handle-dependencies.d.mts.map +1 -1
  52. package/dist/types/commands/organization/handle-organization-list.d.mts.map +1 -1
  53. package/dist/types/commands/package/handle-purl-deep-score.d.mts.map +1 -1
  54. package/dist/types/commands/package/handle-purls-shallow-score.d.mts.map +1 -1
  55. package/dist/types/commands/pnpm/cmd-pnpm.d.mts.map +1 -1
  56. package/dist/types/commands/repository/cmd-repository-list.d.mts.map +1 -1
  57. package/dist/types/commands/repository/cmd-repository-view.d.mts.map +1 -1
  58. package/dist/types/commands/repository/handle-create-repo.d.mts.map +1 -1
  59. package/dist/types/commands/scan/cmd-scan-diff.d.mts.map +1 -1
  60. package/dist/types/commands/scan/create-scan-from-github.d.mts.map +1 -1
  61. package/dist/types/commands/scan/fetch-report-data.d.mts.map +1 -1
  62. package/dist/types/commands/scan/handle-create-new-scan.d.mts.map +1 -1
  63. package/dist/types/commands/wrapper/postinstall-wrapper.d.mts.map +1 -1
  64. package/dist/types/commands/yarn/cmd-yarn.d.mts.map +1 -1
  65. package/dist/types/constants.d.mts +1 -0
  66. package/dist/types/constants.d.mts.map +1 -1
  67. package/dist/types/flags.d.mts.map +1 -1
  68. package/dist/types/shadow/common.d.mts +31 -0
  69. package/dist/types/shadow/common.d.mts.map +1 -0
  70. package/dist/types/shadow/npm/bin.d.mts +4 -10
  71. package/dist/types/shadow/npm/bin.d.mts.map +1 -1
  72. package/dist/types/shadow/npm-base.d.mts +11 -0
  73. package/dist/types/shadow/npm-base.d.mts.map +1 -0
  74. package/dist/types/shadow/npx/bin.d.mts +5 -0
  75. package/dist/types/shadow/npx/bin.d.mts.map +1 -0
  76. package/dist/types/shadow/pnpm/bin.d.mts +1 -1
  77. package/dist/types/shadow/pnpm/bin.d.mts.map +1 -1
  78. package/dist/types/shadow/stdio-ipc.d.mts +7 -0
  79. package/dist/types/shadow/stdio-ipc.d.mts.map +1 -0
  80. package/dist/types/shadow/yarn/bin.d.mts +1 -1
  81. package/dist/types/shadow/yarn/bin.d.mts.map +1 -1
  82. package/dist/types/utils/agent.d.mts.map +1 -1
  83. package/dist/types/utils/alerts-map.d.mts.map +1 -1
  84. package/dist/types/utils/api.d.mts.map +1 -1
  85. package/dist/types/utils/cmd.d.mts.map +1 -1
  86. package/dist/types/utils/coana.d.mts.map +1 -1
  87. package/dist/types/utils/color-or-markdown.d.mts.map +1 -1
  88. package/dist/types/utils/config.d.mts.map +1 -1
  89. package/dist/types/utils/cve-to-ghsa.d.mts.map +1 -1
  90. package/dist/types/utils/debug.d.mts +45 -0
  91. package/dist/types/utils/debug.d.mts.map +1 -0
  92. package/dist/types/utils/dlx.d.mts +1 -1
  93. package/dist/types/utils/dlx.d.mts.map +1 -1
  94. package/dist/types/utils/ecosystem.d.mts.map +1 -1
  95. package/dist/types/utils/errors.d.mts +48 -0
  96. package/dist/types/utils/errors.d.mts.map +1 -1
  97. package/dist/types/utils/filter-config.d.mts.map +1 -1
  98. package/dist/types/utils/fs.d.mts.map +1 -1
  99. package/dist/types/utils/get-output-kind.d.mts.map +1 -1
  100. package/dist/types/utils/git.d.mts.map +1 -1
  101. package/dist/types/utils/github.d.mts.map +1 -1
  102. package/dist/types/utils/markdown.d.mts +17 -0
  103. package/dist/types/utils/markdown.d.mts.map +1 -1
  104. package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
  105. package/dist/types/utils/npm-package-arg.d.mts +5 -1
  106. package/dist/types/utils/npm-package-arg.d.mts.map +1 -1
  107. package/dist/types/utils/npm-paths.d.mts.map +1 -1
  108. package/dist/types/utils/npm-spec.d.mts +57 -0
  109. package/dist/types/utils/npm-spec.d.mts.map +1 -0
  110. package/dist/types/utils/output-formatting.d.mts.map +1 -1
  111. package/dist/types/utils/package-environment.d.mts.map +1 -1
  112. package/dist/types/utils/pnpm-paths.d.mts.map +1 -1
  113. package/dist/types/utils/purl-to-ghsa.d.mts.map +1 -1
  114. package/dist/types/utils/purl.d.mts +24 -0
  115. package/dist/types/utils/purl.d.mts.map +1 -1
  116. package/dist/types/utils/requirements.d.mts.map +1 -1
  117. package/dist/types/utils/sdk.d.mts.map +1 -1
  118. package/dist/types/utils/serialize-result-json.d.mts.map +1 -1
  119. package/dist/types/utils/socket-json.d.mts.map +1 -1
  120. package/dist/types/utils/socket-package-alert.d.mts.map +1 -1
  121. package/dist/types/utils/socket-url.d.mts.map +1 -1
  122. package/dist/types/utils/strings.d.mts +12 -0
  123. package/dist/types/utils/strings.d.mts.map +1 -1
  124. package/dist/types/utils/tildify.d.mts +0 -2
  125. package/dist/types/utils/tildify.d.mts.map +1 -1
  126. package/dist/types/utils/yarn-paths.d.mts.map +1 -1
  127. package/dist/utils.js +1303 -457
  128. package/dist/utils.js.map +1 -1
  129. package/dist/vendor.js +317 -316
  130. package/package.json +4 -4
  131. package/shadow-bin/npm +2 -2
  132. package/shadow-bin/npx +2 -2
  133. package/shadow-bin/pnpm +2 -2
  134. package/shadow-bin/yarn +2 -2
package/dist/utils.js CHANGED
@@ -18,17 +18,263 @@ var prompts = require('../external/@socketsecurity/registry/lib/prompts');
18
18
  var spawn = require('../external/@socketsecurity/registry/lib/spawn');
19
19
  var fs = require('../external/@socketsecurity/registry/lib/fs');
20
20
  var require$$5 = require('node:module');
21
- var shadowNpmBin = require('./shadow-npm-bin.js');
22
21
  var fs$1 = require('node:fs');
23
22
  var require$$13 = require('../external/@socketsecurity/registry/lib/url');
24
- var promises = require('node:timers/promises');
25
23
  var agent = require('../external/@socketsecurity/registry/lib/agent');
26
24
  var bin = require('../external/@socketsecurity/registry/lib/bin');
27
25
  var packages = require('../external/@socketsecurity/registry/lib/packages');
26
+ var promises = require('node:timers/promises');
28
27
  var globs = require('../external/@socketsecurity/registry/lib/globs');
29
28
  var streams = require('../external/@socketsecurity/registry/lib/streams');
30
29
 
31
30
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
31
+ /**
32
+ * Debug utilities for Socket CLI.
33
+ * Provides structured debugging with categorized levels and helpers.
34
+ *
35
+ * Debug Categories:
36
+ * DEFAULT (shown with SOCKET_CLI_DEBUG=1):
37
+ * - 'error': Critical errors that prevent operation
38
+ * - 'warn': Important warnings that may affect behavior
39
+ * - 'notice': Notable events and state changes
40
+ * - 'silly': Very verbose debugging info
41
+ *
42
+ * OPT-IN ONLY (require explicit DEBUG='category' even with SOCKET_CLI_DEBUG=1):
43
+ * - 'inspect': Detailed object inspection (DEBUG='inspect' or DEBUG='*')
44
+ * - 'stdio': Command execution logs (DEBUG='stdio' or DEBUG='*')
45
+ *
46
+ * These opt-in categories are intentionally excluded from default debug output
47
+ * to reduce noise. Enable them explicitly when needed for deep debugging.
48
+ */
49
+
50
+
51
+ /**
52
+ * Debug an API response.
53
+ * Logs essential info without exposing sensitive data.
54
+ */
55
+ function debugApiResponse(endpoint, status, error) {
56
+ if (error) {
57
+ require$$9.debugDir('error', {
58
+ endpoint,
59
+ error: error instanceof Error ? error.message : 'Unknown error'
60
+ });
61
+ } else if (status && status >= 400) {
62
+ require$$9.debugFn('warn', `API ${endpoint}: HTTP ${status}`);
63
+ } else if (require$$9.isDebug('notice')) {
64
+ require$$9.debugFn('notice', `API ${endpoint}: ${status || 'pending'}`);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Debug file operation.
70
+ * Logs file operations with appropriate level.
71
+ */
72
+ function debugFileOp(operation, filepath, error) {
73
+ if (error) {
74
+ require$$9.debugDir('warn', {
75
+ operation,
76
+ filepath,
77
+ error: error instanceof Error ? error.message : 'Unknown error'
78
+ });
79
+ } else if (require$$9.isDebug('silly')) {
80
+ require$$9.debugFn('silly', `File ${operation}: ${filepath}`);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Debug package scanning.
86
+ * Provides insight into security scanning.
87
+ */
88
+ function debugScan(phase, packageCount, details) {
89
+ switch (phase) {
90
+ case 'start':
91
+ if (packageCount) {
92
+ require$$9.debugFn('notice', `Scanning ${packageCount} packages`);
93
+ }
94
+ break;
95
+ case 'progress':
96
+ if (require$$9.isDebug('silly') && packageCount) {
97
+ require$$9.debugFn('silly', `Scan progress: ${packageCount} packages processed`);
98
+ }
99
+ break;
100
+ case 'complete':
101
+ require$$9.debugFn('notice', `Scan complete${packageCount ? `: ${packageCount} packages` : ''}`);
102
+ break;
103
+ case 'error':
104
+ require$$9.debugDir('error', {
105
+ phase: 'scan_error',
106
+ details
107
+ });
108
+ break;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Debug configuration loading.
114
+ */
115
+ function debugConfig(source, found, error) {
116
+ if (error) {
117
+ require$$9.debugDir('warn', {
118
+ source,
119
+ error: error instanceof Error ? error.message : 'Unknown error'
120
+ });
121
+ } else if (found) {
122
+ require$$9.debugFn('notice', `Config loaded: ${source}`);
123
+ } else if (require$$9.isDebug('silly')) {
124
+ require$$9.debugFn('silly', `Config not found: ${source}`);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Debug git operations.
130
+ * Only logs important git operations, not every command.
131
+ */
132
+ function debugGit(operation, success, details) {
133
+ if (!success) {
134
+ require$$9.debugDir('warn', {
135
+ git_op: operation,
136
+ ...details
137
+ });
138
+ } else if (require$$9.isDebug('notice') && operation.includes('push') || operation.includes('commit')) {
139
+ // Only log important operations like push and commit.
140
+ require$$9.debugFn('notice', `Git ${operation} succeeded`);
141
+ } else if (require$$9.isDebug('silly')) {
142
+ require$$9.debugFn('silly', `Git ${operation}`);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Error utilities for Socket CLI.
148
+ * Provides consistent error handling, formatting, and message extraction.
149
+ *
150
+ * Key Classes:
151
+ * - AuthError: Authentication failures (401/403 responses)
152
+ * - InputError: User input validation failures
153
+ *
154
+ * Key Functions:
155
+ * - captureException: Send errors to Sentry for monitoring
156
+ * - formatErrorWithDetail: Format errors with detailed context
157
+ * - getErrorCause: Get error cause with fallback to UNKNOWN_ERROR
158
+ * - getErrorMessage: Extract error message from any thrown value
159
+ *
160
+ * Error Handling Strategy:
161
+ * - Always prefer specific error types over generic errors
162
+ * - Use formatErrorWithDetail for user-facing error messages
163
+ * - Log errors to Sentry in production for monitoring
164
+ */
165
+
166
+ const {
167
+ kInternalsSymbol,
168
+ [kInternalsSymbol]: {
169
+ getSentry
170
+ }
171
+ } = constants.default;
172
+ class AuthError extends Error {}
173
+ class InputError extends Error {
174
+ constructor(message, body) {
175
+ super(message);
176
+ this.body = body;
177
+ }
178
+ }
179
+ async function captureException(exception, hint) {
180
+ const result = captureExceptionSync(exception, hint);
181
+ // "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
182
+ await promises.setTimeout(1000);
183
+ return result;
184
+ }
185
+ function captureExceptionSync(exception, hint) {
186
+ const Sentry = getSentry();
187
+ if (!Sentry) {
188
+ return '';
189
+ }
190
+ require$$9.debugFn('notice', 'send: exception to Sentry');
191
+ return Sentry.captureException(exception, hint);
192
+ }
193
+
194
+ /**
195
+ * Extracts an error message from an unknown value.
196
+ * Returns the message if it's an Error object, otherwise returns undefined.
197
+ *
198
+ * @param error - The error object to extract message from
199
+ * @returns The error message or undefined
200
+ */
201
+ function getErrorMessage(error) {
202
+ return error?.message;
203
+ }
204
+
205
+ /**
206
+ * Extracts an error message from an unknown value with a fallback.
207
+ * Returns the message if it's an Error object, otherwise returns the fallback.
208
+ *
209
+ * @param error - The error object to extract message from
210
+ * @param fallback - The fallback message if no error message is found
211
+ * @returns The error message or fallback
212
+ *
213
+ * @example
214
+ * getErrorMessageOr(error, 'Unknown error occurred')
215
+ * // Returns: "ENOENT: no such file or directory" or "Unknown error occurred"
216
+ */
217
+ function getErrorMessageOr(error, fallback) {
218
+ return getErrorMessage(error) || fallback;
219
+ }
220
+
221
+ /**
222
+ * Extracts an error cause from an unknown value.
223
+ * Returns the error message if available, otherwise UNKNOWN_ERROR.
224
+ * Commonly used for creating CResult error causes.
225
+ *
226
+ * @param error - The error object to extract message from
227
+ * @returns The error message or UNKNOWN_ERROR constant
228
+ *
229
+ * @example
230
+ * return { ok: false, message: 'Operation failed', cause: getErrorCause(e) }
231
+ */
232
+ function getErrorCause(error) {
233
+ return getErrorMessageOr(error, constants.UNKNOWN_ERROR);
234
+ }
235
+
236
+ /**
237
+ * Formats an error message with an optional error detail appended.
238
+ * Extracts the message from an unknown error value and appends it
239
+ * to the base message if available.
240
+ *
241
+ * @param baseMessage - The base message to display
242
+ * @param error - The error object to extract message from
243
+ * @returns Formatted message with error detail if available
244
+ *
245
+ * @example
246
+ * formatErrorWithDetail('Failed to delete file', error)
247
+ * // Returns: "Failed to delete file: ENOENT: no such file or directory"
248
+ * // Or just: "Failed to delete file" if no error message
249
+ */
250
+ function formatErrorWithDetail(baseMessage, error) {
251
+ const errorMessage = getErrorMessage(error);
252
+ return `${baseMessage}${errorMessage ? `: ${errorMessage}` : ''}`;
253
+ }
254
+
255
+ /**
256
+ * Configuration utilities for Socket CLI.
257
+ * Manages CLI configuration including API tokens, org settings, and preferences.
258
+ *
259
+ * Configuration Hierarchy (highest priority first):
260
+ * 1. Environment variables (SOCKET_CLI_*)
261
+ * 2. Command-line --config flag
262
+ * 3. Persisted config file (base64 encoded JSON)
263
+ *
264
+ * Supported Config Keys:
265
+ * - apiBaseUrl: Socket API endpoint URL
266
+ * - apiProxy: Proxy for API requests
267
+ * - apiToken: Authentication token for Socket API
268
+ * - defaultOrg/org: Default organization slug
269
+ * - enforcedOrgs: Organizations with enforced security policies
270
+ *
271
+ * Key Functions:
272
+ * - findSocketYmlSync: Locate socket.yml configuration file
273
+ * - getConfigValue: Retrieve configuration value by key
274
+ * - overrideCachedConfig: Apply temporary config overrides
275
+ * - updateConfigValue: Persist configuration changes
276
+ */
277
+
32
278
  const sensitiveConfigKeyLookup = new Set([constants.CONFIG_KEY_API_TOKEN]);
33
279
  const supportedConfig = new Map([[constants.CONFIG_KEY_API_BASE_URL, 'Base URL of the Socket API endpoint'], [constants.CONFIG_KEY_API_PROXY, 'A proxy through which to access the Socket API'], [constants.CONFIG_KEY_API_TOKEN, 'The Socket API token required to access most Socket API endpoints'], [constants.CONFIG_KEY_DEFAULT_ORG, 'The default org slug to use; usually the org your Socket API token has access to. When set, all orgSlug arguments are implied to be this value.'], [constants.CONFIG_KEY_ENFORCED_ORGS, 'Orgs in this list have their security policies enforced on this machine'], ['skipAskToPersistDefaultOrg', 'This flag prevents the Socket CLI from asking you to persist the org slug when you selected one interactively'], [constants.CONFIG_KEY_ORG, 'Alias for defaultOrg']]);
34
280
  const supportedConfigEntries = [...supportedConfig.entries()].sort((a, b) => sorts.naturalCompare(a[0], b[0]));
@@ -45,8 +291,10 @@ function getConfigValues() {
45
291
  if (raw) {
46
292
  try {
47
293
  Object.assign(_cachedConfig, JSON.parse(Buffer.from(raw, 'base64').toString()));
48
- } catch {
294
+ debugConfig(socketAppDataPath, true);
295
+ } catch (e) {
49
296
  logger.logger.warn(`Failed to parse config at ${socketAppDataPath}`);
297
+ debugConfig(socketAppDataPath, false, e);
50
298
  }
51
299
  // Normalize apiKey to apiToken and persist it.
52
300
  // This is a one time migration per user.
@@ -100,13 +348,12 @@ function findSocketYmlSync(dir = process.cwd()) {
100
348
  }
101
349
  };
102
350
  } catch (e) {
103
- require$$9.debugDir('inspect', {
104
- error: e
105
- });
351
+ require$$9.debugFn('error', `Failed to parse config file: ${ymlPath}`);
352
+ require$$9.debugDir('error', e);
106
353
  return {
107
354
  ok: false,
108
355
  message: `Found file but was unable to parse ${ymlPath}`,
109
- cause: e instanceof Error ? e.message : String(e)
356
+ cause: getErrorCause(e)
110
357
  };
111
358
  }
112
359
  }
@@ -267,6 +514,20 @@ function updateConfigValue(configKey, value) {
267
514
  };
268
515
  }
269
516
 
517
+ /**
518
+ * Requirements configuration utilities for Socket CLI.
519
+ * Manages API permissions and quota requirements for commands.
520
+ *
521
+ * Key Functions:
522
+ * - getRequirements: Load requirements configuration
523
+ * - getRequirementsKey: Convert command path to requirements key
524
+ *
525
+ * Configuration:
526
+ * - Loads from requirements.json
527
+ * - Maps command paths to permission requirements
528
+ * - Used for permission validation and help text
529
+ */
530
+
270
531
  const require$3 = require$$5.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
271
532
  let _requirements;
272
533
  function getRequirements() {
@@ -283,6 +544,32 @@ function getRequirementsKey(cmdPath) {
283
544
  return cmdPath.replace(/^socket[: ]/, '').replace(/ +/g, ':');
284
545
  }
285
546
 
547
+ /**
548
+ * Socket SDK utilities for Socket CLI.
549
+ * Manages SDK initialization and configuration for API communication.
550
+ *
551
+ * Authentication:
552
+ * - Interactive password prompt for missing tokens
553
+ * - Supports environment variable (SOCKET_CLI_API_TOKEN)
554
+ * - Validates token format and presence
555
+ *
556
+ * Proxy Support:
557
+ * - Automatic proxy agent selection
558
+ * - HTTP/HTTPS proxy configuration
559
+ * - Respects SOCKET_CLI_API_PROXY environment variable
560
+ *
561
+ * SDK Setup:
562
+ * - createSocketSdk: Create configured SDK instance
563
+ * - getDefaultApiToken: Retrieve API token from config/env
564
+ * - getDefaultProxyUrl: Retrieve proxy URL from config/env
565
+ * - getPublicApiToken: Get public API token constant
566
+ * - setupSdk: Initialize Socket SDK with authentication
567
+ *
568
+ * User Agent:
569
+ * - Automatic user agent generation from package.json
570
+ * - Includes CLI version and platform information
571
+ */
572
+
286
573
  const TOKEN_PREFIX = 'sktsec_';
287
574
  const TOKEN_PREFIX_LENGTH = TOKEN_PREFIX.length;
288
575
  const TOKEN_VISIBLE_LENGTH = 5;
@@ -375,6 +662,27 @@ async function setupSdk(options) {
375
662
  };
376
663
  }
377
664
 
665
+ /**
666
+ * API utilities for Socket CLI.
667
+ * Provides consistent API communication with error handling and permissions management.
668
+ *
669
+ * Key Functions:
670
+ * - getDefaultApiBaseUrl: Get configured API endpoint
671
+ * - getErrorMessageForHttpStatusCode: User-friendly HTTP error messages
672
+ * - handleApiCall: Execute Socket SDK API calls with error handling
673
+ * - handleApiCallNoSpinner: Execute API calls without UI spinner
674
+ * - queryApi: Execute raw API queries with text response
675
+ *
676
+ * Error Handling:
677
+ * - Automatic permission requirement logging for 403 errors
678
+ * - Detailed error messages for common HTTP status codes
679
+ * - Integration with debug helpers for API response logging
680
+ *
681
+ * Configuration:
682
+ * - Respects SOCKET_CLI_API_BASE_URL environment variable
683
+ * - Falls back to configured apiBaseUrl or default API_V0_URL
684
+ */
685
+
378
686
  const NO_ERROR_MESSAGE = 'No error message returned';
379
687
  /**
380
688
  * Get command requirements from requirements.json based on command path.
@@ -469,13 +777,10 @@ async function handleApiCall(value, options) {
469
777
  };
470
778
  if (description) {
471
779
  logger.logger.fail(`An error was thrown while requesting ${description}`);
472
- require$$9.debugFn('error', `caught: ${description} error`);
780
+ debugApiResponse(description, undefined, e);
473
781
  } else {
474
- require$$9.debugFn('error', `caught: Socket API request error`);
782
+ debugApiResponse('Socket API', undefined, e);
475
783
  }
476
- require$$9.debugDir('inspect', {
477
- error: e
478
- });
479
784
  require$$9.debugDir('inspect', {
480
785
  socketSdkErrorResult
481
786
  });
@@ -484,7 +789,8 @@ async function handleApiCall(value, options) {
484
789
 
485
790
  // Note: TS can't narrow down the type of result due to generics.
486
791
  if (sdkResult.success === false) {
487
- require$$9.debugFn('error', `fail:${description ? ` ${description}` : ''} bad response`);
792
+ const endpoint = description || 'Socket API';
793
+ debugApiResponse(endpoint, sdkResult.status);
488
794
  require$$9.debugDir('inspect', {
489
795
  sdkResult
490
796
  });
@@ -519,10 +825,8 @@ async function handleApiCallNoSpinner(value, description) {
519
825
  try {
520
826
  sdkResult = await value;
521
827
  } catch (e) {
522
- require$$9.debugFn('error', `caught: ${description} error`);
523
- require$$9.debugDir('inspect', {
524
- error: e
525
- });
828
+ require$$9.debugFn('error', `API request failed: ${description}`);
829
+ require$$9.debugDir('error', e);
526
830
  const errStr = e ? String(e).trim() : '';
527
831
  const message = 'Socket API error';
528
832
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -604,10 +908,8 @@ async function queryApiSafeText(path, description, commandPath) {
604
908
  if (description) {
605
909
  spinner.failAndStop(`An error was thrown while requesting ${description}.`);
606
910
  }
607
- require$$9.debugFn('error', 'caught: await queryApi() error');
608
- require$$9.debugDir('inspect', {
609
- error: e
610
- });
911
+ require$$9.debugFn('error', 'Query API request failed');
912
+ require$$9.debugDir('error', e);
611
913
  const errStr = e ? String(e).trim() : '';
612
914
  const message = 'API request failed';
613
915
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -640,10 +942,8 @@ async function queryApiSafeText(path, description, commandPath) {
640
942
  data
641
943
  };
642
944
  } catch (e) {
643
- require$$9.debugFn('error', 'caught: await result.text() error');
644
- require$$9.debugDir('inspect', {
645
- error: e
646
- });
945
+ require$$9.debugFn('error', 'Failed to read API response text');
946
+ require$$9.debugDir('error', e);
647
947
  return {
648
948
  ok: false,
649
949
  message: 'API request failed',
@@ -728,10 +1028,8 @@ async function sendApiRequest(path, options) {
728
1028
  if (description) {
729
1029
  spinner.failAndStop(`An error was thrown while requesting ${description}.`);
730
1030
  }
731
- require$$9.debugFn('error', `caught: await fetch() ${method} error`);
732
- require$$9.debugDir('inspect', {
733
- error: e
734
- });
1031
+ require$$9.debugFn('error', `API ${method} request failed`);
1032
+ require$$9.debugDir('error', e);
735
1033
  const errStr = e ? String(e).trim() : '';
736
1034
  const message = 'API request failed';
737
1035
  const rawCause = errStr || NO_ERROR_MESSAGE;
@@ -768,10 +1066,8 @@ async function sendApiRequest(path, options) {
768
1066
  data: data
769
1067
  };
770
1068
  } catch (e) {
771
- require$$9.debugFn('error', 'caught: await result.json() error');
772
- require$$9.debugDir('inspect', {
773
- error: e
774
- });
1069
+ require$$9.debugFn('error', 'Failed to parse API response JSON');
1070
+ require$$9.debugDir('error', e);
775
1071
  return {
776
1072
  ok: false,
777
1073
  message: 'API request failed',
@@ -786,6 +1082,24 @@ function failMsgWithBadge(badge, message) {
786
1082
  return `${prefix}${postfix}`;
787
1083
  }
788
1084
 
1085
+ /**
1086
+ * Markdown utilities for Socket CLI.
1087
+ * Generates formatted markdown output for reports and documentation.
1088
+ *
1089
+ * Key Functions:
1090
+ * - mdTableStringNumber: Create markdown table with string keys and number values
1091
+ *
1092
+ * Table Features:
1093
+ * - Auto-sizing columns based on content
1094
+ * - Proper alignment for headers and data
1095
+ * - Clean markdown-compliant formatting
1096
+ *
1097
+ * Usage:
1098
+ * - Analytics reports
1099
+ * - Scan result tables
1100
+ * - Statistical summaries
1101
+ */
1102
+
789
1103
  function mdTableStringNumber(title1, title2, obj) {
790
1104
  // | Date | Counts |
791
1105
  // | ----------- | ------ |
@@ -904,9 +1218,8 @@ function serializeResultJson(data) {
904
1218
  process.exitCode = 1;
905
1219
  const message = 'There was a problem converting the data set to JSON. Please try again without --json';
906
1220
  logger.logger.fail(message);
907
- require$$9.debugDir('inspect', {
908
- error: e
909
- });
1221
+ require$$9.debugFn('error', 'JSON serialization failed');
1222
+ require$$9.debugDir('error', e);
910
1223
 
911
1224
  // This could be caused by circular references, which is an "us" problem.
912
1225
  return `${JSON.stringify({
@@ -965,6 +1278,24 @@ function checkCommandInput(outputKind, ...checks) {
965
1278
  return false;
966
1279
  }
967
1280
 
1281
+ /**
1282
+ * Output format detection utilities for Socket CLI.
1283
+ * Determines output format based on command flags.
1284
+ *
1285
+ * Key Functions:
1286
+ * - getOutputKind: Determine output format from flags
1287
+ *
1288
+ * Supported Formats:
1289
+ * - JSON: Machine-readable JSON output
1290
+ * - Markdown: Formatted markdown for reports
1291
+ * - Text: Plain text for terminal display
1292
+ *
1293
+ * Usage:
1294
+ * - Processes --json and --markdown flags
1295
+ * - Returns appropriate output format constant
1296
+ * - Defaults to text format for terminal display
1297
+ */
1298
+
968
1299
  function getOutputKind(json, markdown) {
969
1300
  if (json) {
970
1301
  return constants.OUTPUT_JSON;
@@ -975,10 +1306,44 @@ function getOutputKind(json, markdown) {
975
1306
  return constants.OUTPUT_TEXT;
976
1307
  }
977
1308
 
1309
+ /**
1310
+ * String manipulation utilities for Socket CLI.
1311
+ * Provides common string transformations and formatting.
1312
+ *
1313
+ * Key Functions:
1314
+ * - camelToKebab: Convert camelCase to kebab-case
1315
+ *
1316
+ * Usage:
1317
+ * - Command name transformations
1318
+ * - Flag name conversions
1319
+ * - Consistent string formatting
1320
+ */
1321
+
978
1322
  function camelToKebab(str) {
979
1323
  return str === '' ? '' : str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
980
1324
  }
981
1325
 
1326
+ /**
1327
+ * Output formatting utilities for Socket CLI.
1328
+ * Provides consistent formatting for help text and command output.
1329
+ *
1330
+ * Key Functions:
1331
+ * - getFlagApiRequirementsOutput: Format API requirements for flags
1332
+ * - getHelpListOutput: Format help text lists with descriptions
1333
+ * - getFlagsHelpOutput: Generate formatted help for command flags
1334
+ *
1335
+ * Formatting Features:
1336
+ * - Automatic indentation and alignment
1337
+ * - Flag description formatting
1338
+ * - Requirements and permissions display
1339
+ * - Hidden flag filtering
1340
+ *
1341
+ * Usage:
1342
+ * - Used by command help systems
1343
+ * - Provides consistent terminal output formatting
1344
+ * - Handles kebab-case conversion for flags
1345
+ */
1346
+
982
1347
  function getFlagApiRequirementsOutput(cmdPath, options) {
983
1348
  const {
984
1349
  indent = 6
@@ -1049,8 +1414,19 @@ function getHelpListOutput(list, options) {
1049
1414
  return result.trim() || '(none)';
1050
1415
  }
1051
1416
 
1052
- // Replace the start of a path with ~/ when it starts with your home dir.
1053
- // A common way to abbreviate the user home dir (though not strictly posix).
1417
+ /**
1418
+ * Path tildification utilities for Socket CLI.
1419
+ * Abbreviates home directory paths with tilde notation.
1420
+ *
1421
+ * Key Functions:
1422
+ * - tildify: Replace home directory with ~ in paths
1423
+ *
1424
+ * Usage:
1425
+ * - Shortens absolute paths for display
1426
+ * - Converts /Users/name/... to ~/...
1427
+ * - Common Unix convention for home directory
1428
+ */
1429
+
1054
1430
  function tildify(cwd) {
1055
1431
  return cwd.replace(new RegExp(`^${regexps.escapeRegExp(constants.default.homePath)}(?:${path.sep}|$)`, 'i'), '~/');
1056
1432
  }
@@ -1269,10 +1645,15 @@ async function meowWithSubcommands(subcommands, options) {
1269
1645
  // We want to detect whether a bool flag is given at all.
1270
1646
  booleanDefault: undefined
1271
1647
  });
1272
- const noSpinner = cli1.flags['spinner'] === false;
1273
- const orgFlag = String(cli1.flags['org'] || '') || undefined;
1648
+ const {
1649
+ config: configFlag,
1650
+ org: orgFlag,
1651
+ spinner: spinnerFlag
1652
+ } = cli1.flags;
1653
+ const noSpinner = spinnerFlag === false || require$$9.isDebug();
1274
1654
 
1275
- // Use CI spinner style when --no-spinner is passed.
1655
+ // Use CI spinner style when --no-spinner is passed or debug mode is enabled.
1656
+ // This prevents the spinner from interfering with debug output.
1276
1657
  if (noSpinner) {
1277
1658
  constants.default.spinner.spinner = spinner.getCliSpinners('ci');
1278
1659
  }
@@ -1282,8 +1663,8 @@ async function meowWithSubcommands(subcommands, options) {
1282
1663
  let configOverrideResult;
1283
1664
  if (constants.default.ENV.SOCKET_CLI_CONFIG) {
1284
1665
  configOverrideResult = overrideCachedConfig(constants.default.ENV.SOCKET_CLI_CONFIG);
1285
- } else if (cli1.flags['config']) {
1286
- configOverrideResult = overrideCachedConfig(cli1.flags['config']);
1666
+ } else if (configFlag) {
1667
+ configOverrideResult = overrideCachedConfig(configFlag);
1287
1668
  }
1288
1669
  if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
1289
1670
  // This overrides the config override and even the explicit token env var.
@@ -1479,9 +1860,10 @@ function meowOrExit({
1479
1860
  spinner: spinnerFlag,
1480
1861
  version: versionFlag
1481
1862
  } = cli.flags;
1482
- const noSpinner = spinnerFlag === false;
1863
+ const noSpinner = spinnerFlag === false || require$$9.isDebug();
1483
1864
 
1484
1865
  // Use CI spinner style when --no-spinner is passed.
1866
+ // This prevents the spinner from interfering with debug output.
1485
1867
  if (noSpinner) {
1486
1868
  constants.default.spinner.spinner = spinner.getCliSpinners('ci');
1487
1869
  }
@@ -1520,6 +1902,8 @@ function meowOrExit({
1520
1902
  console.error('Unknown flag\n--version');
1521
1903
  // eslint-disable-next-line n/no-process-exit
1522
1904
  process.exit(2);
1905
+ // This line is never reached in production, but helps tests.
1906
+ throw new Error('process.exit called');
1523
1907
  }
1524
1908
 
1525
1909
  // Now test for help state. Run Meow again. If it exits now, it must be due
@@ -1753,6 +2137,33 @@ async function getDefaultOrgSlug() {
1753
2137
  };
1754
2138
  }
1755
2139
 
2140
+ /**
2141
+ * Git utilities for Socket CLI.
2142
+ * Provides git operations for repository management, branch handling, and commits.
2143
+ *
2144
+ * Branch Operations:
2145
+ * - gitCheckoutBranch: Switch to branch
2146
+ * - gitCreateBranch: Create new local branch
2147
+ * - gitDeleteBranch: Delete local branch
2148
+ * - gitDeleteRemoteBranch: Delete remote branch
2149
+ * - gitPushBranch: Push branch to remote with --force
2150
+ *
2151
+ * Commit Operations:
2152
+ * - gitCleanFdx: Remove untracked files
2153
+ * - gitCommit: Stage files and create commit
2154
+ * - gitEnsureIdentity: Configure git user.name/email
2155
+ * - gitResetHard: Reset to branch/commit
2156
+ *
2157
+ * Remote URL Parsing:
2158
+ * - parseGitRemoteUrl: Extract owner/repo from SSH or HTTPS URLs
2159
+ *
2160
+ * Repository Information:
2161
+ * - detectDefaultBranch: Find default branch (main/master/develop/etc)
2162
+ * - getBaseBranch: Determine base branch (respects GitHub Actions env)
2163
+ * - getRepoInfo: Extract owner/repo from git remote URL
2164
+ * - gitBranch: Get current branch or commit hash
2165
+ */
2166
+
1756
2167
  // Listed in order of check preference.
1757
2168
  const COMMON_DEFAULT_BRANCH_NAMES = [
1758
2169
  // Modern default (GitHub, GitLab, Bitbucket have switched to this).
@@ -1796,22 +2207,21 @@ async function getBaseBranch(cwd = process.cwd()) {
1796
2207
  }
1797
2208
  async function getRepoInfo(cwd = process.cwd()) {
1798
2209
  let info;
1799
- const quotedCmd = '`git remote get-url origin`';
1800
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1801
2210
  try {
1802
2211
  const remoteUrl = (await spawn.spawn('git', ['remote', 'get-url', 'origin'], {
1803
2212
  cwd
1804
2213
  })).stdout;
1805
2214
  info = parseGitRemoteUrl(remoteUrl);
1806
2215
  if (!info) {
1807
- require$$9.debugFn('error', 'git: unmatched git remote URL format');
1808
- require$$9.debugDir('inspect', {
2216
+ require$$9.debugFn('warn', `Unmatched git remote URL format: ${remoteUrl}`);
2217
+ require$$9.debugDir('warn', {
1809
2218
  remoteUrl
1810
2219
  });
1811
2220
  }
1812
2221
  } catch (e) {
1813
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2222
+ // Expected failure when not in a git repo.
1814
2223
  require$$9.debugDir('inspect', {
2224
+ message: 'git remote get-url failed',
1815
2225
  error: e
1816
2226
  });
1817
2227
  }
@@ -1825,41 +2235,29 @@ async function gitBranch(cwd = process.cwd()) {
1825
2235
  const stdioPipeOptions = {
1826
2236
  cwd
1827
2237
  };
1828
- let quotedCmd = '`git symbolic-ref --short HEAD`';
1829
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1830
2238
  // Try symbolic-ref first which returns the branch name or fails in a
1831
2239
  // detached HEAD state.
1832
2240
  try {
1833
2241
  const gitSymbolicRefResult = await spawn.spawn('git', ['symbolic-ref', '--short', 'HEAD'], stdioPipeOptions);
1834
- require$$9.debugDir('stdio', {
1835
- gitSymbolicRefResult
1836
- });
1837
2242
  return gitSymbolicRefResult.stdout;
1838
2243
  } catch (e) {
1839
- if (require$$9.isDebug('stdio')) {
1840
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1841
- require$$9.debugDir('inspect', {
1842
- error: e
1843
- });
1844
- }
2244
+ // Expected in detached HEAD state, fallback to rev-parse.
2245
+ require$$9.debugDir('inspect', {
2246
+ message: 'In detached HEAD state',
2247
+ error: e
2248
+ });
1845
2249
  }
1846
2250
  // Fallback to using rev-parse to get the short commit hash in a
1847
2251
  // detached HEAD state.
1848
- quotedCmd = '`git rev-parse --short HEAD`';
1849
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1850
2252
  try {
1851
2253
  const gitRevParseResult = await spawn.spawn('git', ['rev-parse', '--short', 'HEAD'], stdioPipeOptions);
1852
- require$$9.debugDir('stdio', {
1853
- gitRevParseResult
1854
- });
1855
2254
  return gitRevParseResult.stdout;
1856
2255
  } catch (e) {
1857
- if (require$$9.isDebug('stdio')) {
1858
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1859
- require$$9.debugDir('inspect', {
1860
- error: e
1861
- });
1862
- }
2256
+ // Both methods failed, likely not in a git repo.
2257
+ require$$9.debugDir('inspect', {
2258
+ message: 'Unable to determine git branch',
2259
+ error: e
2260
+ });
1863
2261
  }
1864
2262
  return undefined;
1865
2263
  }
@@ -1890,14 +2288,12 @@ async function gitCleanFdx(cwd = process.cwd()) {
1890
2288
  cwd,
1891
2289
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
1892
2290
  };
1893
- const quotedCmd = '`git clean -fdx`';
1894
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1895
2291
  try {
1896
2292
  await spawn.spawn('git', ['clean', '-fdx'], stdioIgnoreOptions);
2293
+ debugGit('clean -fdx', true);
1897
2294
  return true;
1898
2295
  } catch (e) {
1899
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1900
- require$$9.debugDir('inspect', {
2296
+ debugGit('clean -fdx', false, {
1901
2297
  error: e
1902
2298
  });
1903
2299
  }
@@ -1908,14 +2304,12 @@ async function gitCheckoutBranch(branch, cwd = process.cwd()) {
1908
2304
  cwd,
1909
2305
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
1910
2306
  };
1911
- const quotedCmd = `\`git checkout ${branch}\``;
1912
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1913
2307
  try {
1914
2308
  await spawn.spawn('git', ['checkout', branch], stdioIgnoreOptions);
2309
+ debugGit(`checkout ${branch}`, true);
1915
2310
  return true;
1916
2311
  } catch (e) {
1917
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1918
- require$$9.debugDir('inspect', {
2312
+ debugGit(`checkout ${branch}`, false, {
1919
2313
  error: e
1920
2314
  });
1921
2315
  }
@@ -1929,14 +2323,12 @@ async function gitCreateBranch(branch, cwd = process.cwd()) {
1929
2323
  cwd,
1930
2324
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
1931
2325
  };
1932
- const quotedCmd = `\`git branch ${branch}\``;
1933
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1934
2326
  try {
1935
2327
  await spawn.spawn('git', ['branch', branch], stdioIgnoreOptions);
2328
+ debugGit(`branch ${branch}`, true);
1936
2329
  return true;
1937
2330
  } catch (e) {
1938
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1939
- require$$9.debugDir('inspect', {
2331
+ debugGit(`branch ${branch}`, false, {
1940
2332
  error: e
1941
2333
  });
1942
2334
  }
@@ -1947,19 +2339,22 @@ async function gitPushBranch(branch, cwd = process.cwd()) {
1947
2339
  cwd,
1948
2340
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
1949
2341
  };
1950
- const quotedCmd = `\`git push --force --set-upstream origin ${branch}\``;
1951
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
1952
2342
  try {
1953
2343
  await spawn.spawn('git', ['push', '--force', '--set-upstream', 'origin', branch], stdioIgnoreOptions);
2344
+ debugGit(`push ${branch}`, true);
1954
2345
  return true;
1955
2346
  } catch (e) {
1956
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
1957
2347
  if (spawn.isSpawnError(e) && e.code === 128) {
1958
- require$$9.debugFn('error', "denied: token requires write permissions for 'contents' and 'pull-requests'");
2348
+ require$$9.debugFn('error', "Push denied: token requires write permissions for 'contents' and 'pull-requests'");
2349
+ require$$9.debugDir('error', e);
2350
+ require$$9.debugDir('inspect', {
2351
+ branch
2352
+ });
2353
+ } else {
2354
+ debugGit(`push ${branch}`, false, {
2355
+ error: e
2356
+ });
1959
2357
  }
1960
- require$$9.debugDir('inspect', {
1961
- error: e
1962
- });
1963
2358
  }
1964
2359
  return false;
1965
2360
  }
@@ -1981,26 +2376,31 @@ async function gitCommit(commitMsg, filepaths, options) {
1981
2376
  cwd,
1982
2377
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
1983
2378
  };
1984
- const quotedAddCmd = `\`git add ${filepaths.join(' ')}\``;
1985
- require$$9.debugFn('stdio', `spawn: ${quotedAddCmd}`);
1986
2379
  try {
1987
2380
  await spawn.spawn('git', ['add', ...filepaths], stdioIgnoreOptions);
2381
+ debugGit('add', true, {
2382
+ count: filepaths.length
2383
+ });
1988
2384
  } catch (e) {
1989
- require$$9.debugFn('error', `caught: ${quotedAddCmd} failed`);
1990
- require$$9.debugDir('inspect', {
2385
+ debugGit('add', false, {
1991
2386
  error: e
1992
2387
  });
2388
+ require$$9.debugDir('inspect', {
2389
+ filepaths
2390
+ });
2391
+ return false;
1993
2392
  }
1994
- const quotedCommitCmd = `\`git commit -m ${commitMsg}\``;
1995
- require$$9.debugFn('stdio', `spawn: ${quotedCommitCmd}`);
1996
2393
  try {
1997
2394
  await spawn.spawn('git', ['commit', '-m', commitMsg], stdioIgnoreOptions);
2395
+ debugGit('commit', true);
1998
2396
  return true;
1999
2397
  } catch (e) {
2000
- require$$9.debugFn('error', `caught: ${quotedCommitCmd} failed`);
2001
- require$$9.debugDir('inspect', {
2398
+ debugGit('commit', false, {
2002
2399
  error: e
2003
2400
  });
2401
+ require$$9.debugDir('inspect', {
2402
+ commitMsg
2403
+ });
2004
2404
  }
2005
2405
  return false;
2006
2406
  }
@@ -2009,19 +2409,16 @@ async function gitDeleteBranch(branch, cwd = process.cwd()) {
2009
2409
  cwd,
2010
2410
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
2011
2411
  };
2012
- const quotedCmd = `\`git branch -D ${branch}\``;
2013
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2014
2412
  try {
2015
2413
  // Will throw with exit code 1 if branch does not exist.
2016
2414
  await spawn.spawn('git', ['branch', '-D', branch], stdioIgnoreOptions);
2017
2415
  return true;
2018
2416
  } catch (e) {
2019
- if (require$$9.isDebug('stdio')) {
2020
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2021
- require$$9.debugDir('inspect', {
2022
- error: e
2023
- });
2024
- }
2417
+ // Expected failure when branch doesn't exist.
2418
+ require$$9.debugDir('inspect', {
2419
+ message: `Branch deletion failed (may not exist): ${branch}`,
2420
+ error: e
2421
+ });
2025
2422
  }
2026
2423
  return false;
2027
2424
  }
@@ -2035,41 +2432,30 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
2035
2432
  1: value
2036
2433
  }) => {
2037
2434
  let configValue;
2038
- {
2039
- const quotedCmd = `\`git config --get ${prop}\``;
2040
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2041
- try {
2042
- // Will throw with exit code 1 if the config property is not set.
2043
- const gitConfigResult = await spawn.spawn('git', ['config', '--get', prop], stdioPipeOptions);
2044
- require$$9.debugDir('stdio', {
2045
- gitConfigResult
2046
- });
2047
- configValue = gitConfigResult.stdout;
2048
- } catch (e) {
2049
- if (require$$9.isDebug('stdio')) {
2050
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2051
- require$$9.debugDir('inspect', {
2052
- error: e
2053
- });
2054
- }
2055
- }
2435
+ try {
2436
+ // Will throw with exit code 1 if the config property is not set.
2437
+ const gitConfigResult = await spawn.spawn('git', ['config', '--get', prop], stdioPipeOptions);
2438
+ configValue = gitConfigResult.stdout;
2439
+ } catch (e) {
2440
+ // Expected when config property is not set.
2441
+ require$$9.debugDir('inspect', {
2442
+ message: `Git config property not set: ${prop}`,
2443
+ error: e
2444
+ });
2056
2445
  }
2057
2446
  if (configValue !== value) {
2058
2447
  const stdioIgnoreOptions = {
2059
2448
  cwd,
2060
2449
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
2061
2450
  };
2062
- const quotedCmd = `\`git config ${prop} ${value}\``;
2063
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2064
2451
  try {
2065
2452
  await spawn.spawn('git', ['config', prop, value], stdioIgnoreOptions);
2066
2453
  } catch (e) {
2067
- if (require$$9.isDebug('stdio')) {
2068
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2069
- require$$9.debugDir('inspect', {
2070
- error: e
2071
- });
2072
- }
2454
+ require$$9.debugFn('warn', `Failed to set git config: ${prop}`);
2455
+ require$$9.debugDir('warn', e);
2456
+ require$$9.debugDir('inspect', {
2457
+ value
2458
+ });
2073
2459
  }
2074
2460
  }
2075
2461
  }));
@@ -2079,19 +2465,12 @@ async function gitLocalBranchExists(branch, cwd = process.cwd()) {
2079
2465
  cwd,
2080
2466
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
2081
2467
  };
2082
- const quotedCmd = `\`git show-ref --quiet refs/heads/${branch}\``;
2083
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2084
2468
  try {
2085
2469
  // Will throw with exit code 1 if the branch does not exist.
2086
2470
  await spawn.spawn('git', ['show-ref', constants.FLAG_QUIET, `refs/heads/${branch}`], stdioIgnoreOptions);
2087
2471
  return true;
2088
- } catch (e) {
2089
- if (require$$9.isDebug('stdio')) {
2090
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2091
- require$$9.debugDir('inspect', {
2092
- error: e
2093
- });
2094
- }
2472
+ } catch {
2473
+ // Expected when branch doesn't exist - no logging needed.
2095
2474
  }
2096
2475
  return false;
2097
2476
  }
@@ -2099,21 +2478,15 @@ async function gitRemoteBranchExists(branch, cwd = process.cwd()) {
2099
2478
  const stdioPipeOptions = {
2100
2479
  cwd
2101
2480
  };
2102
- const quotedCmd = `\`git ls-remote --heads origin ${branch}\``;
2103
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2104
2481
  try {
2105
2482
  const lsRemoteResult = await spawn.spawn('git', ['ls-remote', '--heads', 'origin', branch], stdioPipeOptions);
2106
- require$$9.debugDir('stdio', {
2107
- lsRemoteResult
2108
- });
2109
2483
  return lsRemoteResult.stdout.length > 0;
2110
2484
  } catch (e) {
2111
- if (require$$9.isDebug('stdio')) {
2112
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2113
- require$$9.debugDir('inspect', {
2114
- error: e
2115
- });
2116
- }
2485
+ // Expected when remote is not accessible or branch doesn't exist.
2486
+ require$$9.debugDir('inspect', {
2487
+ message: `Remote branch check failed: ${branch}`,
2488
+ error: e
2489
+ });
2117
2490
  }
2118
2491
  return false;
2119
2492
  }
@@ -2128,14 +2501,12 @@ async function gitResetHard(branch = 'HEAD', cwd = process.cwd()) {
2128
2501
  cwd,
2129
2502
  stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
2130
2503
  };
2131
- const quotedCmd = `\`git reset --hard ${branch}\``;
2132
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2133
2504
  try {
2134
2505
  await spawn.spawn('git', ['reset', '--hard', branch], stdioIgnoreOptions);
2506
+ debugGit(`reset --hard ${branch}`, true);
2135
2507
  return true;
2136
2508
  } catch (e) {
2137
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2138
- require$$9.debugDir('inspect', {
2509
+ debugGit(`reset --hard ${branch}`, false, {
2139
2510
  error: e
2140
2511
  });
2141
2512
  }
@@ -2145,13 +2516,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
2145
2516
  const stdioPipeOptions = {
2146
2517
  cwd
2147
2518
  };
2148
- const quotedCmd = `\`git diff --name-only\``;
2149
- require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
2150
2519
  try {
2151
2520
  const gitDiffResult = await spawn.spawn('git', ['diff', '--name-only'], stdioPipeOptions);
2152
- require$$9.debugDir('stdio', {
2153
- gitDiffResult
2154
- });
2155
2521
  const changedFilesDetails = gitDiffResult.stdout;
2156
2522
  const relPaths = changedFilesDetails.split('\n');
2157
2523
  return {
@@ -2159,10 +2525,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
2159
2525
  data: relPaths.map(p => path$1.normalizePath(p))
2160
2526
  };
2161
2527
  } catch (e) {
2162
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
2163
- require$$9.debugDir('inspect', {
2164
- error: e
2165
- });
2528
+ require$$9.debugFn('error', 'Failed to get unstaged modified files');
2529
+ require$$9.debugDir('error', e);
2166
2530
  return {
2167
2531
  ok: false,
2168
2532
  message: 'Git Error',
@@ -2210,16 +2574,82 @@ function parseGitRemoteUrl(remoteUrl) {
2210
2574
  } : result;
2211
2575
  }
2212
2576
 
2213
- function getPurlObject(purl, options) {
2577
+ /**
2578
+ * Package URL (PURL) utilities for Socket CLI.
2579
+ * Implements the PURL specification for universal package identification.
2580
+ *
2581
+ * PURL Format:
2582
+ * pkg:type/namespace/name@version?qualifiers#subpath
2583
+ *
2584
+ * Key Functions:
2585
+ * - createPurlObject: Create PURL from components
2586
+ * - isPurl: Check if string is valid PURL
2587
+ * - normalizePurl: Normalize PURL format
2588
+ * - parsePurl: Parse PURL string to object
2589
+ * - purlToString: Convert PURL object to string
2590
+ *
2591
+ * Supported Types:
2592
+ * - cargo: Rust packages
2593
+ * - gem: Ruby packages
2594
+ * - go: Go modules
2595
+ * - maven: Java packages
2596
+ * - npm: Node.js packages
2597
+ * - pypi: Python packages
2598
+ *
2599
+ * See: https://github.com/package-url/purl-spec
2600
+ */
2601
+
2602
+ function createPurlObject(type, name, options) {
2603
+ let opts;
2604
+ if (require$$11.isObjectObject(type)) {
2605
+ opts = {
2606
+ __proto__: null,
2607
+ ...type
2608
+ };
2609
+ type = opts.type;
2610
+ name = opts.name;
2611
+ } else if (require$$11.isObjectObject(name)) {
2612
+ opts = {
2613
+ __proto__: null,
2614
+ ...name
2615
+ };
2616
+ name = opts.name;
2617
+ } else {
2618
+ opts = {
2619
+ __proto__: null,
2620
+ ...options
2621
+ };
2622
+ if (typeof name !== 'string') {
2623
+ name = opts.name;
2624
+ }
2625
+ }
2214
2626
  const {
2215
- throws
2216
- } = {
2217
- __proto__: null,
2218
- ...options
2219
- };
2627
+ namespace,
2628
+ qualifiers,
2629
+ subpath,
2630
+ throws,
2631
+ version
2632
+ } = opts;
2220
2633
  const shouldThrow = throws === undefined || !!throws;
2221
2634
  try {
2222
- return typeof purl === 'string' ? vendor.packageurlJsExports.PackageURL.fromString(normalizePurl(purl)) : purl;
2635
+ return new vendor.packageurlJsExports.PackageURL(type, namespace, name, version, qualifiers, subpath);
2636
+ } catch (e) {
2637
+ if (shouldThrow) {
2638
+ throw e;
2639
+ }
2640
+ }
2641
+ return undefined;
2642
+ }
2643
+ function getPurlObject(purl, options) {
2644
+ const {
2645
+ throws
2646
+ } = {
2647
+ __proto__: null,
2648
+ ...options
2649
+ };
2650
+ const shouldThrow = throws === undefined || !!throws;
2651
+ try {
2652
+ return typeof purl === 'string' ? vendor.packageurlJsExports.PackageURL.fromString(normalizePurl(purl)) : purl;
2223
2653
  } catch (e) {
2224
2654
  if (shouldThrow) {
2225
2655
  throw e;
@@ -2231,6 +2661,26 @@ function normalizePurl(rawPurl) {
2231
2661
  return rawPurl.startsWith('pkg:') ? rawPurl : `pkg:${rawPurl}`;
2232
2662
  }
2233
2663
 
2664
+ /**
2665
+ * Socket.dev URL utilities for Socket CLI.
2666
+ * Generates URLs for Socket.dev website features and resources.
2667
+ *
2668
+ * Key Functions:
2669
+ * - getPkgFullNameFromPurl: Extract full package name from PURL
2670
+ * - getSocketDevAlertUrl: Generate alert type documentation URL
2671
+ * - getSocketDevPackageOverviewUrl: Generate package overview URL
2672
+ * - getSocketDevPackageOverviewUrlFromPurl: Generate overview URL from PURL
2673
+ * - getSocketDevPackageUrl: Generate package detail URL
2674
+ * - getSocketDevPackageUrlFromPurl: Generate package URL from PURL
2675
+ * - getSocketDevReportUrl: Generate scan report URL
2676
+ *
2677
+ * URL Generation:
2678
+ * - Package overview and detail pages
2679
+ * - Security alert documentation
2680
+ * - Scan report links
2681
+ * - Ecosystem-specific URL formatting
2682
+ */
2683
+
2234
2684
  function getPkgFullNameFromPurl(purl) {
2235
2685
  const purlObj = getPurlObject(purl);
2236
2686
  const {
@@ -2273,6 +2723,19 @@ function* walkNestedMap(map, keys = []) {
2273
2723
  }
2274
2724
  }
2275
2725
 
2726
+ /**
2727
+ * Coana integration utilities for Socket CLI.
2728
+ * Manages reachability analysis via Coana tech CLI.
2729
+ *
2730
+ * Key Functions:
2731
+ * - extractTier1ReachabilityScanId: Extract scan ID from socket facts file
2732
+ *
2733
+ * Integration:
2734
+ * - Works with @coana-tech/cli for reachability analysis
2735
+ * - Processes socket facts JSON files
2736
+ * - Extracts tier 1 reachability scan identifiers
2737
+ */
2738
+
2276
2739
  function extractTier1ReachabilityScanId(socketFactsFile) {
2277
2740
  const json = fs.readJsonSync(socketFactsFile, {
2278
2741
  throws: false
@@ -2281,6 +2744,25 @@ function extractTier1ReachabilityScanId(socketFactsFile) {
2281
2744
  return tier1ReachabilityScanId.length > 0 ? tier1ReachabilityScanId : undefined;
2282
2745
  }
2283
2746
 
2747
+ /**
2748
+ * File system utilities for Socket CLI.
2749
+ * Provides file and directory search functionality.
2750
+ *
2751
+ * Key Functions:
2752
+ * - findUp: Search for files/directories up the directory tree
2753
+ *
2754
+ * Features:
2755
+ * - Upward directory traversal
2756
+ * - Supports file and directory searching
2757
+ * - Abort signal support for cancellation
2758
+ * - Multiple name search support
2759
+ *
2760
+ * Usage:
2761
+ * - Finding configuration files (package.json, lockfiles)
2762
+ * - Locating project root directories
2763
+ * - Searching for specific files in parent directories
2764
+ */
2765
+
2284
2766
  async function findUp(name, options) {
2285
2767
  const opts = {
2286
2768
  __proto__: null,
@@ -2622,13 +3104,15 @@ function exitWithBinPathError$2(binName) {
2622
3104
  // could not be found.
2623
3105
  // eslint-disable-next-line n/no-process-exit
2624
3106
  process.exit(127);
3107
+ // This line is never reached in production, but helps tests.
3108
+ throw new Error('process.exit called');
2625
3109
  }
2626
3110
  let _yarnBinPath;
2627
3111
  function getYarnBinPath() {
2628
3112
  if (_yarnBinPath === undefined) {
2629
3113
  _yarnBinPath = getYarnBinPathDetails().path;
2630
3114
  if (!_yarnBinPath) {
2631
- exitWithBinPathError$2(constants.default.YARN);
3115
+ exitWithBinPathError$2(constants.YARN);
2632
3116
  }
2633
3117
  }
2634
3118
  return _yarnBinPath;
@@ -2636,7 +3120,7 @@ function getYarnBinPath() {
2636
3120
  let _yarnBinPathDetails;
2637
3121
  function getYarnBinPathDetails() {
2638
3122
  if (_yarnBinPathDetails === undefined) {
2639
- _yarnBinPathDetails = findBinPathDetailsSync(constants.default.YARN);
3123
+ _yarnBinPathDetails = findBinPathDetailsSync(constants.YARN);
2640
3124
  }
2641
3125
  return _yarnBinPathDetails;
2642
3126
  }
@@ -2668,202 +3152,25 @@ function isYarnBerry() {
2668
3152
  return _isYarnBerry;
2669
3153
  }
2670
3154
 
2671
- function exitWithBinPathError$1(binName) {
2672
- logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
2673
- // The exit code 127 indicates that the command or binary being executed
2674
- // could not be found.
2675
- // eslint-disable-next-line n/no-process-exit
2676
- process.exit(127);
2677
- }
2678
- let _npmBinPath;
2679
- function getNpmBinPath() {
2680
- if (_npmBinPath === undefined) {
2681
- _npmBinPath = getNpmBinPathDetails().path;
2682
- if (!_npmBinPath) {
2683
- exitWithBinPathError$1(constants.NPM);
2684
- }
2685
- }
2686
- return _npmBinPath;
2687
- }
2688
- let _npmBinPathDetails;
2689
- function getNpmBinPathDetails() {
2690
- if (_npmBinPathDetails === undefined) {
2691
- _npmBinPathDetails = findBinPathDetailsSync(constants.NPM);
2692
- }
2693
- return _npmBinPathDetails;
2694
- }
2695
- let _npmDirPath;
2696
- function getNpmDirPath() {
2697
- if (_npmDirPath === undefined) {
2698
- const npmBinPath = getNpmBinPath();
2699
- _npmDirPath = npmBinPath ? findNpmDirPathSync(npmBinPath) : undefined;
2700
- if (!_npmDirPath) {
2701
- _npmDirPath = constants.default.ENV.SOCKET_CLI_NPM_PATH || undefined;
2702
- }
2703
- if (!_npmDirPath) {
2704
- let message = 'Unable to find npm CLI install directory.';
2705
- if (npmBinPath) {
2706
- message += `\nSearched parent directories of ${path.dirname(npmBinPath)}.`;
2707
- }
2708
- message += '\n\nThis is may be a bug with socket-npm related to changes to the npm CLI.';
2709
- message += `\nPlease report to ${constants.default.SOCKET_CLI_ISSUES_URL}.`;
2710
- logger.logger.fail(message);
2711
- // The exit code 127 indicates that the command or binary being executed
2712
- // could not be found.
2713
- // eslint-disable-next-line n/no-process-exit
2714
- process.exit(127);
2715
- }
2716
- }
2717
- return _npmDirPath;
2718
- }
2719
- let _npmRequire;
2720
- function getNpmRequire() {
2721
- if (_npmRequire === undefined) {
2722
- const npmDirPath = getNpmDirPath();
2723
- const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
2724
- _npmRequire = require$$5.createRequire(path.join(fs$1.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
2725
- }
2726
- return _npmRequire;
2727
- }
2728
- let _npxBinPath;
2729
- function getNpxBinPath() {
2730
- if (_npxBinPath === undefined) {
2731
- _npxBinPath = getNpxBinPathDetails().path;
2732
- if (!_npxBinPath) {
2733
- exitWithBinPathError$1('npx');
2734
- }
2735
- }
2736
- return _npxBinPath;
2737
- }
2738
- let _npxBinPathDetails;
2739
- function getNpxBinPathDetails() {
2740
- if (_npxBinPathDetails === undefined) {
2741
- _npxBinPathDetails = findBinPathDetailsSync('npx');
2742
- }
2743
- return _npxBinPathDetails;
2744
- }
2745
- function isNpmBinPathShadowed() {
2746
- return getNpmBinPathDetails().shadowed;
2747
- }
2748
- function isNpxBinPathShadowed() {
2749
- return getNpxBinPathDetails().shadowed;
2750
- }
2751
-
2752
- const helpFlags = new Set([constants.FLAG_HELP, '-h']);
2753
-
2754
3155
  /**
2755
- * Convert command arguments to a properly formatted string representation.
3156
+ * DLX execution utilities for Socket CLI.
3157
+ * Manages package execution via npx/pnpm dlx/yarn dlx commands.
3158
+ *
3159
+ * Key Functions:
3160
+ * - spawnCdxgenDlx: Execute CycloneDX generator via dlx
3161
+ * - spawnCoanaDlx: Execute Coana CLI tool via dlx
3162
+ * - spawnDlx: Execute packages using dlx-style commands
3163
+ * - spawnSynpDlx: Execute Synp converter via dlx
3164
+ *
3165
+ * Package Manager Detection:
3166
+ * - Auto-detects npm, pnpm, or yarn based on lockfiles
3167
+ * - Supports force-refresh and silent execution modes
3168
+ *
3169
+ * Integration:
3170
+ * - Works with shadow binaries for security scanning
3171
+ * - Handles version pinning and cache management
3172
+ * - Configures environment for third-party tools
2756
3173
  */
2757
- function cmdFlagsToString(args) {
2758
- const result = [];
2759
- for (let i = 0, {
2760
- length
2761
- } = args; i < length; i += 1) {
2762
- const arg = args[i].trim();
2763
- if (arg.startsWith('--')) {
2764
- const nextArg = i + 1 < length ? args[i + 1].trim() : undefined;
2765
- // Check if the next item exists and is NOT another flag.
2766
- if (nextArg && !nextArg.startsWith('--')) {
2767
- result.push(`${arg}=${nextArg}`);
2768
- i += 1;
2769
- } else {
2770
- result.push(arg);
2771
- }
2772
- }
2773
- }
2774
- return result.join(' ');
2775
- }
2776
-
2777
- /**
2778
- * Convert flag values to array format for processing.
2779
- */
2780
- function cmdFlagValueToArray(value) {
2781
- if (typeof value === 'string') {
2782
- return value.trim().split(/, */).filter(Boolean);
2783
- }
2784
- if (Array.isArray(value)) {
2785
- return value.flatMap(cmdFlagValueToArray);
2786
- }
2787
- return [];
2788
- }
2789
-
2790
- /**
2791
- * Add command name prefix to message text.
2792
- */
2793
- function cmdPrefixMessage(cmdName, text) {
2794
- const cmdPrefix = cmdName ? `${cmdName}: ` : '';
2795
- return `${cmdPrefix}${text}`;
2796
- }
2797
-
2798
- /**
2799
- * Filter out Socket flags from argv before passing to subcommands.
2800
- */
2801
- function filterFlags(argv, flagsToFilter, exceptions) {
2802
- const filtered = [];
2803
-
2804
- // Build set of flags to filter from the provided flag objects.
2805
- const flagsToFilterSet = new Set();
2806
- const flagsWithValueSet = new Set();
2807
- for (const [flagName, flag] of Object.entries(flagsToFilter)) {
2808
- const longFlag = `--${camelToKebab(flagName)}`;
2809
- // Special case for negated booleans.
2810
- if (flagName === 'spinner' || flagName === 'banner') {
2811
- flagsToFilterSet.add(`--no-${flagName}`);
2812
- } else {
2813
- flagsToFilterSet.add(longFlag);
2814
- }
2815
- if (flag?.shortFlag) {
2816
- flagsToFilterSet.add(`-${flag.shortFlag}`);
2817
- }
2818
- // Track flags that take values.
2819
- if (flag.type !== 'boolean') {
2820
- flagsWithValueSet.add(longFlag);
2821
- if (flag?.shortFlag) {
2822
- flagsWithValueSet.add(`-${flag.shortFlag}`);
2823
- }
2824
- }
2825
- }
2826
- for (let i = 0, {
2827
- length
2828
- } = argv; i < length; i += 1) {
2829
- const arg = argv[i];
2830
- // Check if this flag should be kept as an exception.
2831
- if (exceptions?.includes(arg)) {
2832
- filtered.push(arg);
2833
- // Handle flags that take values.
2834
- if (flagsWithValueSet.has(arg)) {
2835
- // Include the next argument (the flag value).
2836
- i += 1;
2837
- if (i < length) {
2838
- filtered.push(argv[i]);
2839
- }
2840
- }
2841
- } else if (flagsToFilterSet.has(arg)) {
2842
- // Skip flags that take values.
2843
- if (flagsWithValueSet.has(arg)) {
2844
- // Skip the next argument (the flag value).
2845
- i += 1;
2846
- }
2847
- // Skip boolean flags (no additional argument to skip).
2848
- } else if (arg && Array.from(flagsWithValueSet).some(flag => arg.startsWith(`${flag}=`))) {
2849
- // Skip --flag=value format for Socket flags unless it's an exception.
2850
- if (exceptions?.some(exc => arg.startsWith(`${exc}=`))) {
2851
- filtered.push(arg);
2852
- }
2853
- // Otherwise skip it.
2854
- } else {
2855
- filtered.push(arg);
2856
- }
2857
- }
2858
- return filtered;
2859
- }
2860
-
2861
- /**
2862
- * Check if argument is a help flag.
2863
- */
2864
- function isHelpFlag(cmdArg) {
2865
- return helpFlags.has(cmdArg);
2866
- }
2867
3174
 
2868
3175
  const require$2 = require$$5.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
2869
3176
  const {
@@ -2919,10 +3226,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
2919
3226
  const packageString = `${packageSpec.name}@${packageSpec.version}`;
2920
3227
 
2921
3228
  // Build command args based on package manager.
2922
- let binName;
2923
3229
  let spawnArgs;
2924
3230
  if (pm === constants.PNPM) {
2925
- binName = constants.PNPM;
2926
3231
  spawnArgs = ['dlx'];
2927
3232
  if (force) {
2928
3233
  // For pnpm, set dlx-cache-max-age to 0 via env to force fresh download.
@@ -2949,7 +3254,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
2949
3254
  const shadowPnpmBin = /*@__PURE__*/require$2(constants.default.shadowPnpmBinPath);
2950
3255
  return await shadowPnpmBin(spawnArgs, finalShadowOptions, spawnExtra);
2951
3256
  } else if (pm === constants.YARN && isYarnBerry()) {
2952
- binName = constants.YARN;
2953
3257
  spawnArgs = ['dlx'];
2954
3258
  // Yarn dlx runs in a temporary environment by design and should always fetch fresh.
2955
3259
  if (silent) {
@@ -2961,7 +3265,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
2961
3265
  } else {
2962
3266
  // Use npm exec/npx.
2963
3267
  // For consistency, we'll use npx which is more commonly used for one-off execution.
2964
- binName = 'npx';
2965
3268
  spawnArgs = ['--yes'];
2966
3269
  if (force) {
2967
3270
  // Use --force to bypass cache and get latest within range.
@@ -2971,7 +3274,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
2971
3274
  spawnArgs.push(constants.FLAG_SILENT);
2972
3275
  }
2973
3276
  spawnArgs.push(packageString, ...args);
2974
- return await shadowNpmBin(binName, spawnArgs, finalShadowOptions, spawnExtra);
3277
+ const shadowNpxBin = /*@__PURE__*/require$2(constants.default.shadowNpxBinPath);
3278
+ return await shadowNpxBin(spawnArgs, finalShadowOptions, spawnExtra);
2975
3279
  }
2976
3280
  }
2977
3281
 
@@ -3036,8 +3340,8 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
3036
3340
  };
3037
3341
  } catch (e) {
3038
3342
  const stderr = e?.stderr;
3039
- const cause = e?.message || constants.UNKNOWN_ERROR;
3040
- const message = stderr ? stderr : cause;
3343
+ const cause = getErrorCause(e);
3344
+ const message = stderr || cause;
3041
3345
  return {
3042
3346
  ok: false,
3043
3347
  data: e,
@@ -3084,6 +3388,26 @@ function hasEnterpriseOrgPlan(orgs) {
3084
3388
  return orgs.some(o => o.plan === 'enterprise');
3085
3389
  }
3086
3390
 
3391
+ /**
3392
+ * Socket JSON utilities for Socket CLI.
3393
+ * Manages .socket/socket.json configuration and scan metadata.
3394
+ *
3395
+ * Key Functions:
3396
+ * - loadDotSocketDirectory: Load .socket directory configuration
3397
+ * - saveSocketJson: Persist scan configuration to .socket/socket.json
3398
+ * - validateSocketJson: Validate socket.json structure
3399
+ *
3400
+ * File Structure:
3401
+ * - Contains scan metadata and configuration
3402
+ * - Stores scan IDs and repository information
3403
+ * - Tracks CLI version and scan timestamps
3404
+ *
3405
+ * Directory Management:
3406
+ * - Creates .socket directory as needed
3407
+ * - Handles nested directory structures
3408
+ * - Supports both read and write operations
3409
+ */
3410
+
3087
3411
  function readOrDefaultSocketJson(cwd) {
3088
3412
  const jsonCResult = readSocketJsonSync(cwd, true);
3089
3413
  return jsonCResult.ok ? jsonCResult.data :
@@ -3129,35 +3453,31 @@ function readSocketJsonSync(cwd, defaultOnError = false) {
3129
3453
  } catch (e) {
3130
3454
  if (defaultOnError) {
3131
3455
  logger.logger.warn(`Failed to read ${constants.SOCKET_JSON}, using default`);
3132
- require$$9.debugDir('inspect', {
3133
- error: e
3134
- });
3456
+ require$$9.debugFn('warn', `Failed to read ${constants.SOCKET_JSON} sync`);
3457
+ require$$9.debugDir('warn', e);
3135
3458
  return {
3136
3459
  ok: true,
3137
3460
  data: getDefaultSocketJson()
3138
3461
  };
3139
3462
  }
3140
- const cause = e?.message;
3141
- require$$9.debugDir('inspect', {
3142
- error: e
3143
- });
3463
+ const cause = formatErrorWithDetail(`An error occurred while trying to read ${constants.SOCKET_JSON}`, e);
3464
+ require$$9.debugFn('error', `Failed to read ${constants.SOCKET_JSON} sync`);
3465
+ require$$9.debugDir('error', e);
3144
3466
  return {
3145
3467
  ok: false,
3146
3468
  message: `Failed to read ${constants.SOCKET_JSON}`,
3147
- cause: `An error occurred while trying to read ${constants.SOCKET_JSON}${cause ? `: ${cause}` : ''}`
3469
+ cause
3148
3470
  };
3149
3471
  }
3150
3472
  let jsonObj;
3151
3473
  try {
3152
3474
  jsonObj = JSON.parse(jsonContent);
3153
3475
  } catch (e) {
3154
- require$$9.debugFn('error', 'caught: JSON.parse error');
3476
+ require$$9.debugFn('error', `Failed to parse ${constants.SOCKET_JSON} as JSON (sync)`);
3155
3477
  require$$9.debugDir('inspect', {
3156
3478
  jsonContent
3157
3479
  });
3158
- require$$9.debugDir('inspect', {
3159
- error: e
3160
- });
3480
+ require$$9.debugDir('error', e);
3161
3481
  if (defaultOnError) {
3162
3482
  logger.logger.warn(`Failed to parse ${constants.SOCKET_JSON}, using default`);
3163
3483
  return {
@@ -3191,11 +3511,11 @@ async function writeSocketJson(cwd, sockJson) {
3191
3511
  try {
3192
3512
  jsonContent = JSON.stringify(sockJson, null, 2);
3193
3513
  } catch (e) {
3194
- require$$9.debugFn('error', 'caught: JSON.stringify error');
3514
+ require$$9.debugFn('error', `Failed to serialize ${constants.SOCKET_JSON} to JSON`);
3195
3515
  require$$9.debugDir('inspect', {
3196
- error: e,
3197
3516
  sockJson
3198
3517
  });
3518
+ require$$9.debugDir('error', e);
3199
3519
  return {
3200
3520
  ok: false,
3201
3521
  message: 'Failed to serialize to JSON',
@@ -3210,6 +3530,32 @@ async function writeSocketJson(cwd, sockJson) {
3210
3530
  };
3211
3531
  }
3212
3532
 
3533
+ /**
3534
+ * GitHub utilities for Socket CLI.
3535
+ * Provides GitHub API integration for repository operations and GHSA vulnerability data.
3536
+ *
3537
+ * Authentication:
3538
+ * - getGitHubToken: Retrieve GitHub token from env/git config
3539
+ * - getOctokit: Get authenticated Octokit instance
3540
+ * - getOctokitGraphql: Get authenticated GraphQL client
3541
+ *
3542
+ * Caching:
3543
+ * - 5-minute TTL for API responses
3544
+ * - Automatic cache invalidation
3545
+ * - Persistent cache in node_modules/.cache
3546
+ *
3547
+ * GHSA Operations:
3548
+ * - cacheFetch: Cache API responses with TTL
3549
+ * - fetchGhsaDetails: Fetch GitHub Security Advisory details
3550
+ * - getGhsaUrl: Generate GHSA advisory URL
3551
+ * - readCache/writeCache: Persistent cache operations
3552
+ *
3553
+ * Repository Operations:
3554
+ * - GraphQL queries for complex operations
3555
+ * - Integration with Octokit REST API
3556
+ * - Support for GitHub Actions environment variables
3557
+ */
3558
+
3213
3559
  async function readCache(key,
3214
3560
  // 5 minute in milliseconds time to live (TTL).
3215
3561
  ttlMs = 5 * 60 * 1000) {
@@ -3289,11 +3635,8 @@ async function fetchGhsaDetails(ids) {
3289
3635
  }
3290
3636
  }
3291
3637
  } catch (e) {
3292
- const cause = e?.message;
3293
- require$$9.debugFn('error', `Failed to fetch GHSA details${cause ? `: ${cause}` : ''}`);
3294
- require$$9.debugDir('inspect', {
3295
- error: e
3296
- });
3638
+ require$$9.debugFn('error', formatErrorWithDetail('Failed to fetch GHSA details', e));
3639
+ require$$9.debugDir('error', e);
3297
3640
  }
3298
3641
  return results;
3299
3642
  }
@@ -3397,12 +3740,153 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
3397
3740
  await spawn.spawn('git', ['remote', 'set-url', 'origin', url], stdioIgnoreOptions);
3398
3741
  return true;
3399
3742
  } catch (e) {
3400
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
3743
+ require$$9.debugFn('error', `Git command failed: ${quotedCmd}`);
3401
3744
  require$$9.debugDir('inspect', {
3402
- error: e
3745
+ cmd: quotedCmd
3403
3746
  });
3747
+ require$$9.debugDir('error', e);
3748
+ }
3749
+ return false;
3750
+ }
3751
+
3752
+ /**
3753
+ * Command-line utilities for Socket CLI.
3754
+ * Handles argument parsing, flag processing, and command formatting.
3755
+ *
3756
+ * Argument Handling:
3757
+ * - Handles both long (--flag) and short (-f) formats
3758
+ * - Preserves special characters and escaping
3759
+ * - Properly quotes arguments containing spaces
3760
+ *
3761
+ * Command Names:
3762
+ * - commandNameFromCamel: Convert camelCase to kebab-case command names
3763
+ * - commandNameFromKebab: Convert kebab-case to camelCase
3764
+ *
3765
+ * Flag Processing:
3766
+ * - cmdFlagsToString: Format arguments for display with proper escaping
3767
+ * - cmdPrefixMessage: Generate command prefix message
3768
+ * - stripConfigFlags: Remove --config flags from argument list
3769
+ * - stripDebugFlags: Remove debug-related flags
3770
+ * - stripHelpFlags: Remove help flags (-h, --help)
3771
+ */
3772
+
3773
+ const helpFlags = new Set([constants.FLAG_HELP, '-h']);
3774
+
3775
+ /**
3776
+ * Convert command arguments to a properly formatted string representation.
3777
+ */
3778
+ function cmdFlagsToString(args) {
3779
+ const result = [];
3780
+ for (let i = 0, {
3781
+ length
3782
+ } = args; i < length; i += 1) {
3783
+ const arg = args[i].trim();
3784
+ if (arg.startsWith('--')) {
3785
+ const nextArg = i + 1 < length ? args[i + 1].trim() : undefined;
3786
+ // Check if the next item exists and is NOT another flag.
3787
+ if (nextArg && !nextArg.startsWith('--') && !nextArg.startsWith('-')) {
3788
+ result.push(`${arg}=${nextArg}`);
3789
+ i += 1;
3790
+ } else {
3791
+ result.push(arg);
3792
+ }
3793
+ } else {
3794
+ // Include non-flag arguments (commands, package names, etc.).
3795
+ result.push(arg);
3796
+ }
3797
+ }
3798
+ return result.join(' ');
3799
+ }
3800
+
3801
+ /**
3802
+ * Convert flag values to array format for processing.
3803
+ */
3804
+ function cmdFlagValueToArray(value) {
3805
+ if (typeof value === 'string') {
3806
+ return value.trim().split(/, */).filter(Boolean);
3807
+ }
3808
+ if (Array.isArray(value)) {
3809
+ return value.flatMap(cmdFlagValueToArray);
3810
+ }
3811
+ return [];
3812
+ }
3813
+
3814
+ /**
3815
+ * Add command name prefix to message text.
3816
+ */
3817
+ function cmdPrefixMessage(cmdName, text) {
3818
+ const cmdPrefix = cmdName ? `${cmdName}: ` : '';
3819
+ return `${cmdPrefix}${text}`;
3820
+ }
3821
+
3822
+ /**
3823
+ * Filter out Socket flags from argv before passing to subcommands.
3824
+ */
3825
+ function filterFlags(argv, flagsToFilter, exceptions) {
3826
+ const filtered = [];
3827
+
3828
+ // Build set of flags to filter from the provided flag objects.
3829
+ const flagsToFilterSet = new Set();
3830
+ const flagsWithValueSet = new Set();
3831
+ for (const [flagName, flag] of Object.entries(flagsToFilter)) {
3832
+ const longFlag = `--${camelToKebab(flagName)}`;
3833
+ // Special case for negated booleans.
3834
+ if (flagName === 'spinner' || flagName === 'banner') {
3835
+ flagsToFilterSet.add(`--no-${flagName}`);
3836
+ } else {
3837
+ flagsToFilterSet.add(longFlag);
3838
+ }
3839
+ if (flag?.shortFlag) {
3840
+ flagsToFilterSet.add(`-${flag.shortFlag}`);
3841
+ }
3842
+ // Track flags that take values.
3843
+ if (flag.type !== 'boolean') {
3844
+ flagsWithValueSet.add(longFlag);
3845
+ if (flag?.shortFlag) {
3846
+ flagsWithValueSet.add(`-${flag.shortFlag}`);
3847
+ }
3848
+ }
3849
+ }
3850
+ for (let i = 0, {
3851
+ length
3852
+ } = argv; i < length; i += 1) {
3853
+ const arg = argv[i];
3854
+ // Check if this flag should be kept as an exception.
3855
+ if (exceptions?.includes(arg)) {
3856
+ filtered.push(arg);
3857
+ // Handle flags that take values.
3858
+ if (flagsWithValueSet.has(arg)) {
3859
+ // Include the next argument (the flag value).
3860
+ i += 1;
3861
+ if (i < length) {
3862
+ filtered.push(argv[i]);
3863
+ }
3864
+ }
3865
+ } else if (flagsToFilterSet.has(arg)) {
3866
+ // Skip flags that take values.
3867
+ if (flagsWithValueSet.has(arg)) {
3868
+ // Skip the next argument (the flag value).
3869
+ i += 1;
3870
+ }
3871
+ // Skip boolean flags (no additional argument to skip).
3872
+ } else if (arg && Array.from(flagsWithValueSet).some(flag => arg.startsWith(`${flag}=`))) {
3873
+ // Skip --flag=value format for Socket flags unless it's an exception.
3874
+ if (exceptions?.some(exc => arg.startsWith(`${exc}=`))) {
3875
+ filtered.push(arg);
3876
+ }
3877
+ // Otherwise skip it.
3878
+ } else {
3879
+ filtered.push(arg);
3880
+ }
3404
3881
  }
3405
- return false;
3882
+ return filtered;
3883
+ }
3884
+
3885
+ /**
3886
+ * Check if argument is a help flag.
3887
+ */
3888
+ function isHelpFlag(cmdArg) {
3889
+ return helpFlags.has(cmdArg);
3406
3890
  }
3407
3891
 
3408
3892
  /**
@@ -3429,7 +3913,7 @@ async function convertCveToGhsa(cveId) {
3429
3913
  } catch (e) {
3430
3914
  return {
3431
3915
  ok: false,
3432
- message: `Failed to convert CVE to GHSA: ${e instanceof Error ? e.message : 'Unknown error'}`
3916
+ message: `Failed to convert CVE to GHSA: ${getErrorCause(e)}`
3433
3917
  };
3434
3918
  }
3435
3919
  }
@@ -3493,7 +3977,7 @@ async function convertPurlToGhsas(purl) {
3493
3977
  } catch (e) {
3494
3978
  return {
3495
3979
  ok: false,
3496
- message: `Failed to convert PURL to GHSA: ${e instanceof Error ? e.message : constants.UNKNOWN_ERROR}`
3980
+ message: `Failed to convert PURL to GHSA: ${getErrorCause(e)}`
3497
3981
  };
3498
3982
  }
3499
3983
  }
@@ -3564,39 +4048,100 @@ fi
3564
4048
  };
3565
4049
  }
3566
4050
 
3567
- const {
3568
- kInternalsSymbol,
3569
- [kInternalsSymbol]: {
3570
- getSentry
4051
+ /**
4052
+ * Safe wrapper for npm-package-arg that doesn't throw.
4053
+ * Returns undefined if parsing fails.
4054
+ */
4055
+ function safeNpa$1(...args) {
4056
+ try {
4057
+ return Reflect.apply(vendor.npaExports, undefined, args);
4058
+ } catch {}
4059
+ return undefined;
4060
+ }
4061
+
4062
+ function exitWithBinPathError$1(binName) {
4063
+ logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
4064
+ // The exit code 127 indicates that the command or binary being executed
4065
+ // could not be found.
4066
+ // eslint-disable-next-line n/no-process-exit
4067
+ process.exit(127);
4068
+ // This line is never reached in production, but helps tests.
4069
+ throw new Error('process.exit called');
4070
+ }
4071
+ let _npmBinPath;
4072
+ function getNpmBinPath() {
4073
+ if (_npmBinPath === undefined) {
4074
+ _npmBinPath = getNpmBinPathDetails().path;
4075
+ if (!_npmBinPath) {
4076
+ exitWithBinPathError$1(constants.NPM);
4077
+ }
3571
4078
  }
3572
- } = constants.default;
3573
- class AuthError extends Error {}
3574
- class InputError extends Error {
3575
- constructor(message, body) {
3576
- super(message);
3577
- this.body = body;
4079
+ return _npmBinPath;
4080
+ }
4081
+ let _npmBinPathDetails;
4082
+ function getNpmBinPathDetails() {
4083
+ if (_npmBinPathDetails === undefined) {
4084
+ _npmBinPathDetails = findBinPathDetailsSync(constants.NPM);
3578
4085
  }
4086
+ return _npmBinPathDetails;
3579
4087
  }
3580
- async function captureException(exception, hint) {
3581
- const result = captureExceptionSync(exception, hint);
3582
- // "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
3583
- await promises.setTimeout(1000);
3584
- return result;
4088
+ let _npmDirPath;
4089
+ function getNpmDirPath() {
4090
+ if (_npmDirPath === undefined) {
4091
+ const npmBinPath = getNpmBinPath();
4092
+ _npmDirPath = npmBinPath ? findNpmDirPathSync(npmBinPath) : undefined;
4093
+ if (!_npmDirPath) {
4094
+ _npmDirPath = constants.default.ENV.SOCKET_CLI_NPM_PATH || undefined;
4095
+ }
4096
+ if (!_npmDirPath) {
4097
+ let message = 'Unable to find npm CLI install directory.';
4098
+ if (npmBinPath) {
4099
+ message += `\nSearched parent directories of ${path.dirname(npmBinPath)}.`;
4100
+ }
4101
+ message += '\n\nThis is may be a bug with socket-npm related to changes to the npm CLI.';
4102
+ message += `\nPlease report to ${constants.default.SOCKET_CLI_ISSUES_URL}.`;
4103
+ logger.logger.fail(message);
4104
+ // The exit code 127 indicates that the command or binary being executed
4105
+ // could not be found.
4106
+ // eslint-disable-next-line n/no-process-exit
4107
+ process.exit(127);
4108
+ // This line is never reached in production, but helps tests.
4109
+ throw new Error('process.exit called');
4110
+ }
4111
+ }
4112
+ return _npmDirPath;
3585
4113
  }
3586
- function captureExceptionSync(exception, hint) {
3587
- const Sentry = getSentry();
3588
- if (!Sentry) {
3589
- return '';
4114
+ let _npmRequire;
4115
+ function getNpmRequire() {
4116
+ if (_npmRequire === undefined) {
4117
+ const npmDirPath = getNpmDirPath();
4118
+ const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
4119
+ _npmRequire = require$$5.createRequire(path.join(fs$1.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
3590
4120
  }
3591
- require$$9.debugFn('notice', 'send: exception to Sentry');
3592
- return Sentry.captureException(exception, hint);
4121
+ return _npmRequire;
3593
4122
  }
3594
-
3595
- function npa(...args) {
3596
- try {
3597
- return Reflect.apply(vendor.npaExports, undefined, args);
3598
- } catch {}
3599
- return undefined;
4123
+ let _npxBinPath;
4124
+ function getNpxBinPath() {
4125
+ if (_npxBinPath === undefined) {
4126
+ _npxBinPath = getNpxBinPathDetails().path;
4127
+ if (!_npxBinPath) {
4128
+ exitWithBinPathError$1('npx');
4129
+ }
4130
+ }
4131
+ return _npxBinPath;
4132
+ }
4133
+ let _npxBinPathDetails;
4134
+ function getNpxBinPathDetails() {
4135
+ if (_npxBinPathDetails === undefined) {
4136
+ _npxBinPathDetails = findBinPathDetailsSync('npx');
4137
+ }
4138
+ return _npxBinPathDetails;
4139
+ }
4140
+ function isNpmBinPathShadowed() {
4141
+ return getNpmBinPathDetails().shadowed;
4142
+ }
4143
+ function isNpxBinPathShadowed() {
4144
+ return getNpxBinPathDetails().shadowed;
3600
4145
  }
3601
4146
 
3602
4147
  function shadowNpmInstall(options) {
@@ -3662,6 +4207,24 @@ function shadowNpmInstall(options) {
3662
4207
  return spawnPromise;
3663
4208
  }
3664
4209
 
4210
+ /**
4211
+ * Package manager agent utilities for Socket CLI.
4212
+ * Manages package installation via different package managers.
4213
+ *
4214
+ * Key Functions:
4215
+ * - runAgentInstall: Execute package installation with detected agent
4216
+ *
4217
+ * Supported Agents:
4218
+ * - npm: Node Package Manager
4219
+ * - pnpm: Fast, disk space efficient package manager
4220
+ * - yarn: Alternative package manager
4221
+ *
4222
+ * Features:
4223
+ * - Automatic agent detection
4224
+ * - Shadow installation for security scanning
4225
+ * - Spinner support for progress indication
4226
+ */
4227
+
3665
4228
  function runAgentInstall(pkgEnvDetails, options) {
3666
4229
  const {
3667
4230
  agent,
@@ -3706,6 +4269,32 @@ function runAgentInstall(pkgEnvDetails, options) {
3706
4269
  });
3707
4270
  }
3708
4271
 
4272
+ /**
4273
+ * Package environment detection utilities for Socket CLI.
4274
+ * Analyzes project environment and package manager configuration.
4275
+ *
4276
+ * Key Functions:
4277
+ * - getPackageEnvironment: Detect package manager and project details
4278
+ * - makeConcurrentExecLimit: Calculate concurrent execution limits
4279
+ *
4280
+ * Environment Detection:
4281
+ * - Detects npm, pnpm, yarn, bun package managers
4282
+ * - Analyzes lockfiles for version information
4283
+ * - Determines Node.js and engine requirements
4284
+ * - Identifies workspace configurations
4285
+ *
4286
+ * Features:
4287
+ * - Browser target detection via browserslist
4288
+ * - Engine compatibility checking
4289
+ * - Package manager version detection
4290
+ * - Workspace and monorepo support
4291
+ *
4292
+ * Usage:
4293
+ * - Auto-detecting appropriate package manager
4294
+ * - Validating environment compatibility
4295
+ * - Configuring concurrent execution limits
4296
+ */
4297
+
3709
4298
  const {
3710
4299
  BUN,
3711
4300
  BUN_LOCK,
@@ -3833,10 +4422,11 @@ async function getAgentVersion(agent, agentExecPath, cwd) {
3833
4422
  shell: constants.default.WIN32
3834
4423
  })).stdout) ?? undefined;
3835
4424
  } catch (e) {
3836
- require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
4425
+ require$$9.debugFn('error', `Package manager command failed: ${quotedCmd}`);
3837
4426
  require$$9.debugDir('inspect', {
3838
- error: e
4427
+ cmd: quotedCmd
3839
4428
  });
4429
+ require$$9.debugDir('error', e);
3840
4430
  }
3841
4431
  return result;
3842
4432
  }
@@ -4065,39 +4655,47 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
4065
4655
  };
4066
4656
  }
4067
4657
 
4658
+ /**
4659
+ * Ecosystem type utilities for Socket CLI.
4660
+ * Manages package ecosystem identifiers and mappings.
4661
+ *
4662
+ * Constants:
4663
+ * - ALL_ECOSYSTEMS: Complete list of supported ecosystems
4664
+ * - ECOSYSTEM_MAP: Map ecosystem strings to PURL types
4665
+ *
4666
+ * Type Definitions:
4667
+ * - PURL_Type: Package URL type from Socket SDK
4668
+ *
4669
+ * Supported Ecosystems:
4670
+ * - apk, bitbucket, cargo, chrome, cocoapods, composer
4671
+ * - conan, conda, cran, deb, docker, gem, generic
4672
+ * - github, gitlab, go, hackage, hex, huggingface
4673
+ * - maven, mlflow, npm, nuget, oci, pub, pypi, rpm, swift
4674
+ *
4675
+ * Usage:
4676
+ * - Validates ecosystem types
4677
+ * - Maps between different ecosystem representations
4678
+ * - Ensures type safety for ecosystem operations
4679
+ */
4680
+
4068
4681
  const ALL_ECOSYSTEMS = ['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'];
4069
4682
  new Set(ALL_ECOSYSTEMS);
4070
4683
  function getEcosystemChoicesForMeow() {
4071
4684
  return [...ALL_ECOSYSTEMS];
4072
4685
  }
4073
4686
 
4074
- function exitWithBinPathError(binName) {
4075
- logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
4076
- // The exit code 127 indicates that the command or binary being executed
4077
- // could not be found.
4078
- // eslint-disable-next-line n/no-process-exit
4079
- process.exit(127);
4080
- }
4081
- let _pnpmBinPath;
4082
- function getPnpmBinPath() {
4083
- if (_pnpmBinPath === undefined) {
4084
- _pnpmBinPath = getPnpmBinPathDetails().path;
4085
- if (!_pnpmBinPath) {
4086
- exitWithBinPathError('pnpm');
4087
- }
4088
- }
4089
- return _pnpmBinPath;
4090
- }
4091
- let _pnpmBinPathDetails;
4092
- function getPnpmBinPathDetails() {
4093
- if (_pnpmBinPathDetails === undefined) {
4094
- _pnpmBinPathDetails = findBinPathDetailsSync('pnpm');
4095
- }
4096
- return _pnpmBinPathDetails;
4097
- }
4098
- function isPnpmBinPathShadowed() {
4099
- return getPnpmBinPathDetails().shadowed;
4100
- }
4687
+ /**
4688
+ * Filter configuration utilities for Socket CLI.
4689
+ * Manages filter configuration normalization for security scanning.
4690
+ *
4691
+ * Key Functions:
4692
+ * - toFilterConfig: Normalize filter configuration objects
4693
+ *
4694
+ * Usage:
4695
+ * - Normalizes user-provided filter objects
4696
+ * - Ensures proper structure for filter configuration
4697
+ * - Validates boolean and array values
4698
+ */
4101
4699
 
4102
4700
  function toFilterConfig(obj) {
4103
4701
  const normalized = {
@@ -4197,6 +4795,30 @@ const ALERT_SEVERITY = createEnum({
4197
4795
  low: 'low'
4198
4796
  });
4199
4797
 
4798
+ /**
4799
+ * Color and markdown formatting utilities for Socket CLI.
4800
+ * Provides dual-mode formatting for terminal colors or markdown output.
4801
+ *
4802
+ * Key Class:
4803
+ * - ColorOrMarkdown: Dual-mode formatter for terminal/markdown output
4804
+ *
4805
+ * Formatting Methods:
4806
+ * - bold: Bold text formatting
4807
+ * - codeBlock: Code block formatting
4808
+ * - codeInline: Inline code formatting
4809
+ * - header: Section headers
4810
+ * - hyperlink: Clickable links
4811
+ * - indent: Text indentation
4812
+ * - italic: Italic text formatting
4813
+ * - list: Bullet list formatting
4814
+ * - table: Table formatting
4815
+ *
4816
+ * Usage:
4817
+ * - Switches between terminal colors and markdown based on output format
4818
+ * - Supports both interactive terminal and report generation
4819
+ * - Handles hyperlink fallbacks for terminals without link support
4820
+ */
4821
+
4200
4822
  class ColorOrMarkdown {
4201
4823
  constructor(useMarkdown) {
4202
4824
  this.useMarkdown = !!useMarkdown;
@@ -4242,6 +4864,28 @@ function getTranslations() {
4242
4864
  return _translations;
4243
4865
  }
4244
4866
 
4867
+ /**
4868
+ * Socket package alert utilities for Socket CLI.
4869
+ * Handles security alerts, vulnerabilities, and package risk assessment.
4870
+ *
4871
+ * Key Functions:
4872
+ * - addArtifactToAlertsMap: Add security alert to package map
4873
+ * - logAlertsMap: Display alerts in formatted output
4874
+ * - shouldSkipPackageAlert: Filter alerts based on criteria
4875
+ *
4876
+ * Alert Types:
4877
+ * - CVE: Common Vulnerabilities and Exposures
4878
+ * - GHSA: GitHub Security Advisories
4879
+ * - Package quality issues
4880
+ * - Supply chain risks
4881
+ *
4882
+ * Features:
4883
+ * - Alert severity classification (critical/high/medium/low)
4884
+ * - Fix type detection (major/minor/patch/none)
4885
+ * - Alert filtering and suppression
4886
+ * - Colorized terminal output
4887
+ */
4888
+
4245
4889
  const ALERT_SEVERITY_COLOR = createEnum({
4246
4890
  critical: 'magenta',
4247
4891
  high: 'red',
@@ -4586,6 +5230,26 @@ function logAlertsMap(alertsMap, options) {
4586
5230
  output.write('\n');
4587
5231
  }
4588
5232
 
5233
+ /**
5234
+ * Alerts map utilities for Socket CLI.
5235
+ * Manages security alerts and vulnerability mappings for packages.
5236
+ *
5237
+ * Key Functions:
5238
+ * - getAlertsMapFromPnpmLockfile: Extract alerts from pnpm lockfile
5239
+ * - getAlertsMapFromPurls: Get alerts for specific package URLs
5240
+ * - processAlertsApiResponse: Process API response into alerts map
5241
+ *
5242
+ * Alert Processing:
5243
+ * - Filters alerts based on socket.yml configuration
5244
+ * - Maps package URLs to security vulnerabilities
5245
+ * - Supports batch processing for performance
5246
+ *
5247
+ * Integration:
5248
+ * - Works with pnpm lockfiles for dependency scanning
5249
+ * - Uses Socket API for vulnerability data
5250
+ * - Respects filter configurations from socket.yml
5251
+ */
5252
+
4589
5253
  async function getAlertsMapFromPnpmLockfile(lockfile, options) {
4590
5254
  const purls = await extractPurlsFromPnpmLockfile(lockfile);
4591
5255
  return await getAlertsMapFromPurls(purls, {
@@ -4686,6 +5350,183 @@ async function getAlertsMapFromPurls(purls, options) {
4686
5350
  return alertsByPurl;
4687
5351
  }
4688
5352
 
5353
+ /**
5354
+ * npm package specification utilities for Socket CLI.
5355
+ * Parses and handles various npm package specification formats.
5356
+ *
5357
+ * Supported Formats:
5358
+ * - Regular packages: lodash, lodash@4.17.21
5359
+ * - Scoped packages: @types/node, @types/node@20.0.0
5360
+ * - Version ranges: lodash@^4.0.0, lodash@~4.17.0
5361
+ * - Git URLs: git+https://github.com/user/repo.git
5362
+ * - File paths: file:../local-package
5363
+ * - Aliases: my-alias@npm:real-package@1.0.0
5364
+ *
5365
+ * Key Functions:
5366
+ * - safeNpa: Safe wrapper for npm-package-arg
5367
+ * - safeNpmSpecToPurl: Convert npm spec to PURL
5368
+ * - safeParseNpmSpec: Parse npm spec to name/version
5369
+ *
5370
+ * Error Handling:
5371
+ * - Returns undefined for invalid specs
5372
+ * - Fallback parsing for edge cases
5373
+ * - Safe against malformed input
5374
+ */
5375
+
5376
+
5377
+ // @ts-expect-error - Result is re-exported below.
5378
+
5379
+ /**
5380
+ * Safe wrapper for npm-package-arg that doesn't throw.
5381
+ * Returns undefined if parsing fails.
5382
+ */
5383
+ function safeNpa(...args) {
5384
+ try {
5385
+ return Reflect.apply(vendor.npaExports, undefined, args);
5386
+ } catch {}
5387
+ return undefined;
5388
+ }
5389
+
5390
+ /**
5391
+ * Parse npm package specification into name and version.
5392
+ * Uses npm-package-arg for proper handling of various spec formats:
5393
+ * - Regular packages: lodash, lodash@4.17.21
5394
+ * - Scoped packages: @types/node, @types/node@20.0.0
5395
+ * - Version ranges: lodash@^4.0.0
5396
+ * - Git URLs, file paths, etc.
5397
+ *
5398
+ * Returns undefined if parsing fails.
5399
+ */
5400
+ function safeParseNpmSpec(pkgSpec) {
5401
+ // Use npm-package-arg for proper spec parsing.
5402
+ const parsed = safeNpa(pkgSpec);
5403
+ if (!parsed) {
5404
+ // Fallback to simple parsing if npm-package-arg fails.
5405
+ // Handle scoped packages first to avoid confusion with version delimiter.
5406
+ if (pkgSpec.startsWith('@')) {
5407
+ const scopedMatch = pkgSpec.match(/^(@[^/@]+\/[^/@]+)(?:@(.+))?$/);
5408
+ if (scopedMatch) {
5409
+ return {
5410
+ name: scopedMatch[1],
5411
+ version: scopedMatch[2]
5412
+ };
5413
+ }
5414
+ }
5415
+
5416
+ // Handle regular packages.
5417
+ const atIndex = pkgSpec.indexOf('@');
5418
+ if (atIndex === -1) {
5419
+ return {
5420
+ name: pkgSpec,
5421
+ version: undefined
5422
+ };
5423
+ }
5424
+ return {
5425
+ name: pkgSpec.slice(0, atIndex),
5426
+ version: pkgSpec.slice(atIndex + 1)
5427
+ };
5428
+ }
5429
+
5430
+ // Extract name and version from parsed spec.
5431
+ const name = parsed.name || pkgSpec;
5432
+ let version;
5433
+
5434
+ // Handle different spec types from npm-package-arg.
5435
+ if (parsed.type === 'tag' || parsed.type === 'version' || parsed.type === 'range') {
5436
+ // For npm registry packages:
5437
+ // - type 'tag': latest, beta, etc.
5438
+ // - type 'version': exact version like 1.0.0
5439
+ // - type 'range': version range like ^1.0.0, ~1.0.0, or * for bare names
5440
+ // Don't include '*' as a version - it means "any version".
5441
+ if (parsed.fetchSpec && parsed.fetchSpec !== '*') {
5442
+ version = parsed.fetchSpec;
5443
+ } else if (parsed.rawSpec && parsed.rawSpec !== '*' && parsed.rawSpec !== parsed.name) {
5444
+ version = parsed.rawSpec;
5445
+ }
5446
+ } else if (parsed.type === 'git' || parsed.type === 'remote' || parsed.type === 'file') {
5447
+ // For non-registry specs, use rawSpec if different from name.
5448
+ if (parsed.rawSpec && parsed.rawSpec !== parsed.name) {
5449
+ version = parsed.rawSpec;
5450
+ }
5451
+ }
5452
+ return {
5453
+ name,
5454
+ version
5455
+ };
5456
+ }
5457
+
5458
+ /**
5459
+ * Convert npm package spec to PURL string.
5460
+ * Handles various npm spec formats and converts them to standardized PURLs.
5461
+ * Returns undefined if conversion fails.
5462
+ */
5463
+ function safeNpmSpecToPurl(pkgSpec) {
5464
+ const parsed = safeParseNpmSpec(pkgSpec);
5465
+ if (!parsed) {
5466
+ return undefined;
5467
+ }
5468
+ const {
5469
+ name,
5470
+ version
5471
+ } = parsed;
5472
+
5473
+ // Create PURL object to ensure proper formatting.
5474
+ const purlObj = createPurlObject({
5475
+ type: constants.NPM,
5476
+ name,
5477
+ version,
5478
+ throws: false
5479
+ });
5480
+ return purlObj?.toString() ?? `pkg:${constants.NPM}/${name}${version ? `@${version}` : ''}`;
5481
+ }
5482
+
5483
+ /**
5484
+ * PNPM path resolution utilities for Socket CLI.
5485
+ * Locates and caches PNPM binary paths.
5486
+ *
5487
+ * Key Functions:
5488
+ * - getPnpmBinPath: Get cached PNPM binary path
5489
+ * - getPnpmBinPathDetails: Get detailed PNPM path information
5490
+ *
5491
+ * Error Handling:
5492
+ * - Exits with code 127 if PNPM not found
5493
+ * - Provides clear error messages for missing binaries
5494
+ *
5495
+ * Caching:
5496
+ * - Caches binary path lookups for performance
5497
+ * - Prevents repeated PATH searches
5498
+ */
5499
+
5500
+ function exitWithBinPathError(binName) {
5501
+ logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
5502
+ // The exit code 127 indicates that the command or binary being executed
5503
+ // could not be found.
5504
+ // eslint-disable-next-line n/no-process-exit
5505
+ process.exit(127);
5506
+ // This line is never reached in production, but helps tests.
5507
+ throw new Error('process.exit called');
5508
+ }
5509
+ let _pnpmBinPath;
5510
+ function getPnpmBinPath() {
5511
+ if (_pnpmBinPath === undefined) {
5512
+ _pnpmBinPath = getPnpmBinPathDetails().path;
5513
+ if (!_pnpmBinPath) {
5514
+ exitWithBinPathError('pnpm');
5515
+ }
5516
+ }
5517
+ return _pnpmBinPath;
5518
+ }
5519
+ let _pnpmBinPathDetails;
5520
+ function getPnpmBinPathDetails() {
5521
+ if (_pnpmBinPathDetails === undefined) {
5522
+ _pnpmBinPathDetails = findBinPathDetailsSync('pnpm');
5523
+ }
5524
+ return _pnpmBinPathDetails;
5525
+ }
5526
+ function isPnpmBinPathShadowed() {
5527
+ return getPnpmBinPathDetails().shadowed;
5528
+ }
5529
+
4689
5530
  exports.AuthError = AuthError;
4690
5531
  exports.COMPLETION_CMD_PREFIX = COMPLETION_CMD_PREFIX;
4691
5532
  exports.InputError = InputError;
@@ -4699,6 +5540,8 @@ exports.cmdPrefixMessage = cmdPrefixMessage;
4699
5540
  exports.convertCveToGhsa = convertCveToGhsa;
4700
5541
  exports.convertPurlToGhsas = convertPurlToGhsas;
4701
5542
  exports.createEnum = createEnum;
5543
+ exports.debugFileOp = debugFileOp;
5544
+ exports.debugScan = debugScan;
4702
5545
  exports.detectAndValidatePackageEnvironment = detectAndValidatePackageEnvironment;
4703
5546
  exports.detectDefaultBranch = detectDefaultBranch;
4704
5547
  exports.determineOrgSlug = determineOrgSlug;
@@ -4709,6 +5552,7 @@ exports.fetchGhsaDetails = fetchGhsaDetails;
4709
5552
  exports.fetchOrganization = fetchOrganization;
4710
5553
  exports.filterFlags = filterFlags;
4711
5554
  exports.findUp = findUp;
5555
+ exports.formatErrorWithDetail = formatErrorWithDetail;
4712
5556
  exports.getAlertsMapFromPnpmLockfile = getAlertsMapFromPnpmLockfile;
4713
5557
  exports.getAlertsMapFromPurls = getAlertsMapFromPurls;
4714
5558
  exports.getBaseBranch = getBaseBranch;
@@ -4718,6 +5562,7 @@ exports.getConfigValueOrUndef = getConfigValueOrUndef;
4718
5562
  exports.getDefaultOrgSlug = getDefaultOrgSlug;
4719
5563
  exports.getEcosystemChoicesForMeow = getEcosystemChoicesForMeow;
4720
5564
  exports.getEnterpriseOrgs = getEnterpriseOrgs;
5565
+ exports.getErrorCause = getErrorCause;
4721
5566
  exports.getFlagApiRequirementsOutput = getFlagApiRequirementsOutput;
4722
5567
  exports.getFlagListOutput = getFlagListOutput;
4723
5568
  exports.getMajor = getMajor;
@@ -4773,7 +5618,6 @@ exports.meowOrExit = meowOrExit;
4773
5618
  exports.meowWithSubcommands = meowWithSubcommands;
4774
5619
  exports.msAtHome = msAtHome;
4775
5620
  exports.normalizePurl = normalizePurl;
4776
- exports.npa = npa;
4777
5621
  exports.parsePnpmLockfile = parsePnpmLockfile;
4778
5622
  exports.queryApiSafeJson = queryApiSafeJson;
4779
5623
  exports.queryApiSafeText = queryApiSafeText;
@@ -4782,6 +5626,8 @@ exports.readOrDefaultSocketJsonUp = readOrDefaultSocketJsonUp;
4782
5626
  exports.readPnpmLockfile = readPnpmLockfile;
4783
5627
  exports.readSocketJsonSync = readSocketJsonSync;
4784
5628
  exports.runAgentInstall = runAgentInstall;
5629
+ exports.safeNpa = safeNpa$1;
5630
+ exports.safeNpmSpecToPurl = safeNpmSpecToPurl;
4785
5631
  exports.sendApiRequest = sendApiRequest;
4786
5632
  exports.serializeResultJson = serializeResultJson;
4787
5633
  exports.setGitRemoteGithubRepoUrl = setGitRemoteGithubRepoUrl;
@@ -4795,5 +5641,5 @@ exports.toFilterConfig = toFilterConfig;
4795
5641
  exports.updateConfigValue = updateConfigValue;
4796
5642
  exports.walkNestedMap = walkNestedMap;
4797
5643
  exports.writeSocketJson = writeSocketJson;
4798
- //# debugId=4f982f8d-ea52-46a2-a41c-84d9eac292ab
5644
+ //# debugId=cf6fa269-bd5d-472d-ba3c-ad112752f863
4799
5645
  //# sourceMappingURL=utils.js.map