@socketsecurity/cli 1.1.18 → 1.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/bin/npm-cli.js +2 -2
- package/bin/npx-cli.js +2 -2
- package/bin/pnpm-cli.js +2 -2
- package/bin/yarn-cli.js +2 -2
- package/dist/cli.js +285 -117
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +8 -3
- package/dist/constants.js.map +1 -1
- package/dist/flags.js +3 -2
- package/dist/flags.js.map +1 -1
- package/dist/npm-cli.js +3 -4
- package/dist/npm-cli.js.map +1 -1
- package/dist/npx-cli.js +3 -3
- package/dist/npx-cli.js.map +1 -1
- package/dist/pnpm-cli.js +3 -3
- package/dist/pnpm-cli.js.map +1 -1
- package/dist/shadow-npm-bin.js +3 -106
- package/dist/shadow-npm-bin.js.map +1 -1
- package/dist/shadow-npm-bin2.js +125 -0
- package/dist/shadow-npm-bin2.js.map +1 -0
- package/dist/shadow-npx-bin.js +12 -0
- package/dist/shadow-npx-bin.js.map +1 -0
- package/dist/shadow-pnpm-bin.js +3 -228
- package/dist/shadow-pnpm-bin.js.map +1 -1
- package/dist/shadow-pnpm-bin2.js +323 -0
- package/dist/shadow-pnpm-bin2.js.map +1 -0
- package/dist/shadow-yarn-bin.js +62 -150
- package/dist/shadow-yarn-bin.js.map +1 -1
- package/dist/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/types/commands/analytics/cmd-analytics.d.mts.map +1 -1
- package/dist/types/commands/analytics/output-analytics.d.mts.map +1 -1
- package/dist/types/commands/audit-log/cmd-audit-log.d.mts.map +1 -1
- package/dist/types/commands/audit-log/output-audit-log.d.mts.map +1 -1
- package/dist/types/commands/ci/handle-ci.d.mts.map +1 -1
- package/dist/types/commands/config/cmd-config-auto.d.mts.map +1 -1
- package/dist/types/commands/config/cmd-config-get.d.mts.map +1 -1
- package/dist/types/commands/config/cmd-config-list.d.mts.map +1 -1
- package/dist/types/commands/config/cmd-config-set.d.mts.map +1 -1
- package/dist/types/commands/config/cmd-config-unset.d.mts.map +1 -1
- package/dist/types/commands/config/handle-config-set.d.mts.map +1 -1
- package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/pull-request.d.mts.map +1 -1
- package/dist/types/commands/login/attempt-login.d.mts.map +1 -1
- package/dist/types/commands/manifest/cmd-manifest-conda.d.mts.map +1 -1
- package/dist/types/commands/npm/cmd-npm.d.mts.map +1 -1
- package/dist/types/commands/optimize/handle-optimize.d.mts.map +1 -1
- package/dist/types/commands/optimize/ls-by-agent.d.mts.map +1 -1
- package/dist/types/commands/organization/cmd-organization-dependencies.d.mts.map +1 -1
- package/dist/types/commands/organization/cmd-organization-list.d.mts.map +1 -1
- package/dist/types/commands/organization/handle-dependencies.d.mts.map +1 -1
- package/dist/types/commands/organization/handle-organization-list.d.mts.map +1 -1
- package/dist/types/commands/package/handle-purl-deep-score.d.mts.map +1 -1
- package/dist/types/commands/package/handle-purls-shallow-score.d.mts.map +1 -1
- package/dist/types/commands/pnpm/cmd-pnpm.d.mts.map +1 -1
- package/dist/types/commands/raw-npm/run-raw-npm.d.mts.map +1 -1
- package/dist/types/commands/raw-npx/run-raw-npx.d.mts.map +1 -1
- package/dist/types/commands/repository/cmd-repository-create.d.mts.map +1 -1
- package/dist/types/commands/repository/cmd-repository-del.d.mts.map +1 -1
- package/dist/types/commands/repository/cmd-repository-list.d.mts.map +1 -1
- package/dist/types/commands/repository/cmd-repository-update.d.mts.map +1 -1
- package/dist/types/commands/repository/cmd-repository-view.d.mts.map +1 -1
- package/dist/types/commands/repository/handle-create-repo.d.mts.map +1 -1
- package/dist/types/commands/scan/cmd-scan-create.d.mts.map +1 -1
- package/dist/types/commands/scan/cmd-scan-diff.d.mts.map +1 -1
- package/dist/types/commands/scan/cmd-scan-list.d.mts.map +1 -1
- package/dist/types/commands/scan/create-scan-from-github.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-report-data.d.mts.map +1 -1
- package/dist/types/commands/scan/handle-create-new-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/output-diff-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/output-scan-view.d.mts.map +1 -1
- package/dist/types/commands/threat-feed/cmd-threat-feed.d.mts.map +1 -1
- package/dist/types/commands/wrapper/postinstall-wrapper.d.mts.map +1 -1
- package/dist/types/commands/yarn/cmd-yarn.d.mts.map +1 -1
- package/dist/types/constants.d.mts +1 -0
- package/dist/types/constants.d.mts.map +1 -1
- package/dist/types/flags.d.mts.map +1 -1
- package/dist/types/shadow/common.d.mts +31 -0
- package/dist/types/shadow/common.d.mts.map +1 -0
- package/dist/types/shadow/npm/bin.d.mts +4 -10
- package/dist/types/shadow/npm/bin.d.mts.map +1 -1
- package/dist/types/shadow/npm-base.d.mts +11 -0
- package/dist/types/shadow/npm-base.d.mts.map +1 -0
- package/dist/types/shadow/npx/bin.d.mts +5 -0
- package/dist/types/shadow/npx/bin.d.mts.map +1 -0
- package/dist/types/shadow/pnpm/bin.d.mts +1 -1
- package/dist/types/shadow/pnpm/bin.d.mts.map +1 -1
- package/dist/types/shadow/stdio-ipc.d.mts +7 -0
- package/dist/types/shadow/stdio-ipc.d.mts.map +1 -0
- package/dist/types/shadow/yarn/bin.d.mts +1 -1
- package/dist/types/shadow/yarn/bin.d.mts.map +1 -1
- package/dist/types/utils/agent.d.mts.map +1 -1
- package/dist/types/utils/alerts-map.d.mts.map +1 -1
- package/dist/types/utils/api.d.mts.map +1 -1
- package/dist/types/utils/cmd.d.mts.map +1 -1
- package/dist/types/utils/coana.d.mts.map +1 -1
- package/dist/types/utils/color-or-markdown.d.mts.map +1 -1
- package/dist/types/utils/config.d.mts.map +1 -1
- package/dist/types/utils/cve-to-ghsa.d.mts.map +1 -1
- package/dist/types/utils/debug.d.mts +45 -0
- package/dist/types/utils/debug.d.mts.map +1 -0
- package/dist/types/utils/determine-org-slug.d.mts.map +1 -1
- package/dist/types/utils/dlx.d.mts +1 -1
- package/dist/types/utils/dlx.d.mts.map +1 -1
- package/dist/types/utils/ecosystem.d.mts.map +1 -1
- package/dist/types/utils/errors.d.mts +48 -0
- package/dist/types/utils/errors.d.mts.map +1 -1
- package/dist/types/utils/filter-config.d.mts.map +1 -1
- package/dist/types/utils/fs.d.mts.map +1 -1
- package/dist/types/utils/get-output-kind.d.mts.map +1 -1
- package/dist/types/utils/git.d.mts.map +1 -1
- package/dist/types/utils/github.d.mts.map +1 -1
- package/dist/types/utils/markdown.d.mts +17 -0
- package/dist/types/utils/markdown.d.mts.map +1 -1
- package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
- package/dist/types/utils/npm-package-arg.d.mts +5 -1
- package/dist/types/utils/npm-package-arg.d.mts.map +1 -1
- package/dist/types/utils/npm-paths.d.mts.map +1 -1
- package/dist/types/utils/npm-spec.d.mts +57 -0
- package/dist/types/utils/npm-spec.d.mts.map +1 -0
- package/dist/types/utils/output-formatting.d.mts.map +1 -1
- package/dist/types/utils/package-environment.d.mts.map +1 -1
- package/dist/types/utils/pnpm-paths.d.mts.map +1 -1
- package/dist/types/utils/purl-to-ghsa.d.mts.map +1 -1
- package/dist/types/utils/purl.d.mts +24 -0
- package/dist/types/utils/purl.d.mts.map +1 -1
- package/dist/types/utils/requirements.d.mts.map +1 -1
- package/dist/types/utils/sdk.d.mts.map +1 -1
- package/dist/types/utils/serialize-result-json.d.mts.map +1 -1
- package/dist/types/utils/socket-json.d.mts.map +1 -1
- package/dist/types/utils/socket-package-alert.d.mts.map +1 -1
- package/dist/types/utils/socket-url.d.mts.map +1 -1
- package/dist/types/utils/strings.d.mts +12 -0
- package/dist/types/utils/strings.d.mts.map +1 -1
- package/dist/types/utils/terminal-link.d.mts +45 -0
- package/dist/types/utils/terminal-link.d.mts.map +1 -0
- package/dist/types/utils/tildify.d.mts +0 -2
- package/dist/types/utils/tildify.d.mts.map +1 -1
- package/dist/types/utils/yarn-paths.d.mts.map +1 -1
- package/dist/types/utils/yarn-version.d.mts.map +1 -1
- package/dist/utils.js +1393 -453
- package/dist/utils.js.map +1 -1
- package/dist/vendor.js +682 -682
- package/package.json +3 -3
- package/shadow-bin/npm +2 -2
- package/shadow-bin/npx +2 -2
- package/shadow-bin/pnpm +2 -2
- 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
|
-
|
|
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.
|
|
104
|
-
|
|
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:
|
|
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
|
-
|
|
780
|
+
debugApiResponse(description, undefined, e);
|
|
473
781
|
} else {
|
|
474
|
-
|
|
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
|
-
|
|
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', `
|
|
523
|
-
require$$9.debugDir('
|
|
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', '
|
|
608
|
-
require$$9.debugDir('
|
|
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', '
|
|
644
|
-
require$$9.debugDir('
|
|
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', `
|
|
732
|
-
require$$9.debugDir('
|
|
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', '
|
|
772
|
-
require$$9.debugDir('
|
|
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.
|
|
908
|
-
|
|
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({
|
|
@@ -917,6 +1230,82 @@ function serializeResultJson(data) {
|
|
|
917
1230
|
}
|
|
918
1231
|
}
|
|
919
1232
|
|
|
1233
|
+
/**
|
|
1234
|
+
* Creates a terminal link to a local file.
|
|
1235
|
+
* @param filePath The file path to link to
|
|
1236
|
+
* @param text Optional display text (defaults to the file path itself)
|
|
1237
|
+
* @returns A terminal link to the file
|
|
1238
|
+
*/
|
|
1239
|
+
function fileLink(filePath, text) {
|
|
1240
|
+
const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
|
|
1241
|
+
return vendor.terminalLinkExports(filePath, `file://${absolutePath}`);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Creates a terminal link to an email address.
|
|
1246
|
+
* @param email The email address
|
|
1247
|
+
* @param text Optional display text (defaults to the email address itself)
|
|
1248
|
+
* @returns A terminal link to compose an email
|
|
1249
|
+
*/
|
|
1250
|
+
function mailtoLink(email, text) {
|
|
1251
|
+
return vendor.terminalLinkExports(email, `mailto:${email}`);
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* Creates a terminal link to a web URL.
|
|
1256
|
+
* @param url The web URL to link to
|
|
1257
|
+
* @param text Optional display text (defaults to the URL itself)
|
|
1258
|
+
* @returns A terminal link to the URL
|
|
1259
|
+
*/
|
|
1260
|
+
function webLink(url, text) {
|
|
1261
|
+
return vendor.terminalLinkExports(text ?? url, url);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* Creates a terminal link to the Socket.dev dashboard.
|
|
1266
|
+
* @param path The path within the dashboard (e.g., '/org/YOURORG/alerts')
|
|
1267
|
+
* @param text Optional display text
|
|
1268
|
+
* @returns A terminal link to the Socket.dev dashboard URL
|
|
1269
|
+
*/
|
|
1270
|
+
function socketDashboardLink(dashPath, text) {
|
|
1271
|
+
const url = `https://socket.dev/dashboard${dashPath.startsWith('/') ? dashPath : `/${dashPath}`}`;
|
|
1272
|
+
return vendor.terminalLinkExports(text, url);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* Creates a terminal link to Socket.dev documentation.
|
|
1277
|
+
* @param docPath The documentation path (e.g., '/docs/api-keys')
|
|
1278
|
+
* @param text Optional display text
|
|
1279
|
+
* @returns A terminal link to the Socket.dev documentation
|
|
1280
|
+
*/
|
|
1281
|
+
function socketDocsLink(docPath, text) {
|
|
1282
|
+
const url = `https://docs.socket.dev${docPath.startsWith('/') ? docPath : `/${docPath}`}`;
|
|
1283
|
+
return vendor.terminalLinkExports(text ?? url, url);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* Creates a terminal link to Socket.dev package page.
|
|
1288
|
+
* @param ecosystem The package ecosystem (e.g., 'npm')
|
|
1289
|
+
* @param packageName The package name
|
|
1290
|
+
* @param version Optional package version or path (e.g., 'files/1.0.0/CHANGELOG.md')
|
|
1291
|
+
* @param text Optional display text
|
|
1292
|
+
* @returns A terminal link to the Socket.dev package page
|
|
1293
|
+
*/
|
|
1294
|
+
function socketPackageLink(ecosystem, packageName, version, text) {
|
|
1295
|
+
let url;
|
|
1296
|
+
if (version) {
|
|
1297
|
+
// Check if version contains a path like 'files/1.0.0/CHANGELOG.md'.
|
|
1298
|
+
if (version.includes('/')) {
|
|
1299
|
+
url = `https://socket.dev/${ecosystem}/package/${packageName}/${version}`;
|
|
1300
|
+
} else {
|
|
1301
|
+
url = `https://socket.dev/${ecosystem}/package/${packageName}/overview/${version}`;
|
|
1302
|
+
}
|
|
1303
|
+
} else {
|
|
1304
|
+
url = `https://socket.dev/${ecosystem}/package/${packageName}`;
|
|
1305
|
+
}
|
|
1306
|
+
return vendor.terminalLinkExports(text, url);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
920
1309
|
function checkCommandInput(outputKind, ...checks) {
|
|
921
1310
|
if (checks.every(d => d.test)) {
|
|
922
1311
|
return true;
|
|
@@ -965,6 +1354,24 @@ function checkCommandInput(outputKind, ...checks) {
|
|
|
965
1354
|
return false;
|
|
966
1355
|
}
|
|
967
1356
|
|
|
1357
|
+
/**
|
|
1358
|
+
* Output format detection utilities for Socket CLI.
|
|
1359
|
+
* Determines output format based on command flags.
|
|
1360
|
+
*
|
|
1361
|
+
* Key Functions:
|
|
1362
|
+
* - getOutputKind: Determine output format from flags
|
|
1363
|
+
*
|
|
1364
|
+
* Supported Formats:
|
|
1365
|
+
* - JSON: Machine-readable JSON output
|
|
1366
|
+
* - Markdown: Formatted markdown for reports
|
|
1367
|
+
* - Text: Plain text for terminal display
|
|
1368
|
+
*
|
|
1369
|
+
* Usage:
|
|
1370
|
+
* - Processes --json and --markdown flags
|
|
1371
|
+
* - Returns appropriate output format constant
|
|
1372
|
+
* - Defaults to text format for terminal display
|
|
1373
|
+
*/
|
|
1374
|
+
|
|
968
1375
|
function getOutputKind(json, markdown) {
|
|
969
1376
|
if (json) {
|
|
970
1377
|
return constants.OUTPUT_JSON;
|
|
@@ -975,10 +1382,44 @@ function getOutputKind(json, markdown) {
|
|
|
975
1382
|
return constants.OUTPUT_TEXT;
|
|
976
1383
|
}
|
|
977
1384
|
|
|
1385
|
+
/**
|
|
1386
|
+
* String manipulation utilities for Socket CLI.
|
|
1387
|
+
* Provides common string transformations and formatting.
|
|
1388
|
+
*
|
|
1389
|
+
* Key Functions:
|
|
1390
|
+
* - camelToKebab: Convert camelCase to kebab-case
|
|
1391
|
+
*
|
|
1392
|
+
* Usage:
|
|
1393
|
+
* - Command name transformations
|
|
1394
|
+
* - Flag name conversions
|
|
1395
|
+
* - Consistent string formatting
|
|
1396
|
+
*/
|
|
1397
|
+
|
|
978
1398
|
function camelToKebab(str) {
|
|
979
1399
|
return str === '' ? '' : str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
980
1400
|
}
|
|
981
1401
|
|
|
1402
|
+
/**
|
|
1403
|
+
* Output formatting utilities for Socket CLI.
|
|
1404
|
+
* Provides consistent formatting for help text and command output.
|
|
1405
|
+
*
|
|
1406
|
+
* Key Functions:
|
|
1407
|
+
* - getFlagApiRequirementsOutput: Format API requirements for flags
|
|
1408
|
+
* - getHelpListOutput: Format help text lists with descriptions
|
|
1409
|
+
* - getFlagsHelpOutput: Generate formatted help for command flags
|
|
1410
|
+
*
|
|
1411
|
+
* Formatting Features:
|
|
1412
|
+
* - Automatic indentation and alignment
|
|
1413
|
+
* - Flag description formatting
|
|
1414
|
+
* - Requirements and permissions display
|
|
1415
|
+
* - Hidden flag filtering
|
|
1416
|
+
*
|
|
1417
|
+
* Usage:
|
|
1418
|
+
* - Used by command help systems
|
|
1419
|
+
* - Provides consistent terminal output formatting
|
|
1420
|
+
* - Handles kebab-case conversion for flags
|
|
1421
|
+
*/
|
|
1422
|
+
|
|
982
1423
|
function getFlagApiRequirementsOutput(cmdPath, options) {
|
|
983
1424
|
const {
|
|
984
1425
|
indent = 6
|
|
@@ -1049,8 +1490,19 @@ function getHelpListOutput(list, options) {
|
|
|
1049
1490
|
return result.trim() || '(none)';
|
|
1050
1491
|
}
|
|
1051
1492
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1493
|
+
/**
|
|
1494
|
+
* Path tildification utilities for Socket CLI.
|
|
1495
|
+
* Abbreviates home directory paths with tilde notation.
|
|
1496
|
+
*
|
|
1497
|
+
* Key Functions:
|
|
1498
|
+
* - tildify: Replace home directory with ~ in paths
|
|
1499
|
+
*
|
|
1500
|
+
* Usage:
|
|
1501
|
+
* - Shortens absolute paths for display
|
|
1502
|
+
* - Converts /Users/name/... to ~/...
|
|
1503
|
+
* - Common Unix convention for home directory
|
|
1504
|
+
*/
|
|
1505
|
+
|
|
1054
1506
|
function tildify(cwd) {
|
|
1055
1507
|
return cwd.replace(new RegExp(`^${regexps.escapeRegExp(constants.default.homePath)}(?:${path.sep}|$)`, 'i'), '~/');
|
|
1056
1508
|
}
|
|
@@ -1269,10 +1721,15 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1269
1721
|
// We want to detect whether a bool flag is given at all.
|
|
1270
1722
|
booleanDefault: undefined
|
|
1271
1723
|
});
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1724
|
+
const {
|
|
1725
|
+
config: configFlag,
|
|
1726
|
+
org: orgFlag,
|
|
1727
|
+
spinner: spinnerFlag
|
|
1728
|
+
} = cli1.flags;
|
|
1729
|
+
const noSpinner = spinnerFlag === false || require$$9.isDebug();
|
|
1274
1730
|
|
|
1275
|
-
// Use CI spinner style when --no-spinner is passed.
|
|
1731
|
+
// Use CI spinner style when --no-spinner is passed or debug mode is enabled.
|
|
1732
|
+
// This prevents the spinner from interfering with debug output.
|
|
1276
1733
|
if (noSpinner) {
|
|
1277
1734
|
constants.default.spinner.spinner = spinner.getCliSpinners('ci');
|
|
1278
1735
|
}
|
|
@@ -1282,8 +1739,8 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1282
1739
|
let configOverrideResult;
|
|
1283
1740
|
if (constants.default.ENV.SOCKET_CLI_CONFIG) {
|
|
1284
1741
|
configOverrideResult = overrideCachedConfig(constants.default.ENV.SOCKET_CLI_CONFIG);
|
|
1285
|
-
} else if (
|
|
1286
|
-
configOverrideResult = overrideCachedConfig(
|
|
1742
|
+
} else if (configFlag) {
|
|
1743
|
+
configOverrideResult = overrideCachedConfig(configFlag);
|
|
1287
1744
|
}
|
|
1288
1745
|
if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
1289
1746
|
// This overrides the config override and even the explicit token env var.
|
|
@@ -1479,9 +1936,10 @@ function meowOrExit({
|
|
|
1479
1936
|
spinner: spinnerFlag,
|
|
1480
1937
|
version: versionFlag
|
|
1481
1938
|
} = cli.flags;
|
|
1482
|
-
const noSpinner = spinnerFlag === false;
|
|
1939
|
+
const noSpinner = spinnerFlag === false || require$$9.isDebug();
|
|
1483
1940
|
|
|
1484
1941
|
// Use CI spinner style when --no-spinner is passed.
|
|
1942
|
+
// This prevents the spinner from interfering with debug output.
|
|
1485
1943
|
if (noSpinner) {
|
|
1486
1944
|
constants.default.spinner.spinner = spinner.getCliSpinners('ci');
|
|
1487
1945
|
}
|
|
@@ -1520,6 +1978,8 @@ function meowOrExit({
|
|
|
1520
1978
|
console.error('Unknown flag\n--version');
|
|
1521
1979
|
// eslint-disable-next-line n/no-process-exit
|
|
1522
1980
|
process.exit(2);
|
|
1981
|
+
// This line is never reached in production, but helps tests.
|
|
1982
|
+
throw new Error('process.exit called');
|
|
1523
1983
|
}
|
|
1524
1984
|
|
|
1525
1985
|
// Now test for help state. Run Meow again. If it exits now, it must be due
|
|
@@ -1683,7 +2143,7 @@ async function determineOrgSlug(orgFlag, interactive, dryRun) {
|
|
|
1683
2143
|
logger.logger.warn('');
|
|
1684
2144
|
logger.logger.warn('Note: When running in CI, you probably want to set the `--org` flag.');
|
|
1685
2145
|
logger.logger.warn('');
|
|
1686
|
-
logger.logger.warn(
|
|
2146
|
+
logger.logger.warn(`For details, see the ${webLink(constants.V1_MIGRATION_GUIDE_URL, 'v1 migration guide')}`);
|
|
1687
2147
|
logger.logger.warn('');
|
|
1688
2148
|
logger.logger.warn('This command will exit now because the org slug is required to proceed.');
|
|
1689
2149
|
return ['', undefined];
|
|
@@ -1753,6 +2213,33 @@ async function getDefaultOrgSlug() {
|
|
|
1753
2213
|
};
|
|
1754
2214
|
}
|
|
1755
2215
|
|
|
2216
|
+
/**
|
|
2217
|
+
* Git utilities for Socket CLI.
|
|
2218
|
+
* Provides git operations for repository management, branch handling, and commits.
|
|
2219
|
+
*
|
|
2220
|
+
* Branch Operations:
|
|
2221
|
+
* - gitCheckoutBranch: Switch to branch
|
|
2222
|
+
* - gitCreateBranch: Create new local branch
|
|
2223
|
+
* - gitDeleteBranch: Delete local branch
|
|
2224
|
+
* - gitDeleteRemoteBranch: Delete remote branch
|
|
2225
|
+
* - gitPushBranch: Push branch to remote with --force
|
|
2226
|
+
*
|
|
2227
|
+
* Commit Operations:
|
|
2228
|
+
* - gitCleanFdx: Remove untracked files
|
|
2229
|
+
* - gitCommit: Stage files and create commit
|
|
2230
|
+
* - gitEnsureIdentity: Configure git user.name/email
|
|
2231
|
+
* - gitResetHard: Reset to branch/commit
|
|
2232
|
+
*
|
|
2233
|
+
* Remote URL Parsing:
|
|
2234
|
+
* - parseGitRemoteUrl: Extract owner/repo from SSH or HTTPS URLs
|
|
2235
|
+
*
|
|
2236
|
+
* Repository Information:
|
|
2237
|
+
* - detectDefaultBranch: Find default branch (main/master/develop/etc)
|
|
2238
|
+
* - getBaseBranch: Determine base branch (respects GitHub Actions env)
|
|
2239
|
+
* - getRepoInfo: Extract owner/repo from git remote URL
|
|
2240
|
+
* - gitBranch: Get current branch or commit hash
|
|
2241
|
+
*/
|
|
2242
|
+
|
|
1756
2243
|
// Listed in order of check preference.
|
|
1757
2244
|
const COMMON_DEFAULT_BRANCH_NAMES = [
|
|
1758
2245
|
// Modern default (GitHub, GitLab, Bitbucket have switched to this).
|
|
@@ -1796,22 +2283,21 @@ async function getBaseBranch(cwd = process.cwd()) {
|
|
|
1796
2283
|
}
|
|
1797
2284
|
async function getRepoInfo(cwd = process.cwd()) {
|
|
1798
2285
|
let info;
|
|
1799
|
-
const quotedCmd = '`git remote get-url origin`';
|
|
1800
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1801
2286
|
try {
|
|
1802
2287
|
const remoteUrl = (await spawn.spawn('git', ['remote', 'get-url', 'origin'], {
|
|
1803
2288
|
cwd
|
|
1804
2289
|
})).stdout;
|
|
1805
2290
|
info = parseGitRemoteUrl(remoteUrl);
|
|
1806
2291
|
if (!info) {
|
|
1807
|
-
require$$9.debugFn('
|
|
1808
|
-
require$$9.debugDir('
|
|
2292
|
+
require$$9.debugFn('warn', `Unmatched git remote URL format: ${remoteUrl}`);
|
|
2293
|
+
require$$9.debugDir('warn', {
|
|
1809
2294
|
remoteUrl
|
|
1810
2295
|
});
|
|
1811
2296
|
}
|
|
1812
2297
|
} catch (e) {
|
|
1813
|
-
|
|
2298
|
+
// Expected failure when not in a git repo.
|
|
1814
2299
|
require$$9.debugDir('inspect', {
|
|
2300
|
+
message: 'git remote get-url failed',
|
|
1815
2301
|
error: e
|
|
1816
2302
|
});
|
|
1817
2303
|
}
|
|
@@ -1825,41 +2311,29 @@ async function gitBranch(cwd = process.cwd()) {
|
|
|
1825
2311
|
const stdioPipeOptions = {
|
|
1826
2312
|
cwd
|
|
1827
2313
|
};
|
|
1828
|
-
let quotedCmd = '`git symbolic-ref --short HEAD`';
|
|
1829
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1830
2314
|
// Try symbolic-ref first which returns the branch name or fails in a
|
|
1831
2315
|
// detached HEAD state.
|
|
1832
2316
|
try {
|
|
1833
2317
|
const gitSymbolicRefResult = await spawn.spawn('git', ['symbolic-ref', '--short', 'HEAD'], stdioPipeOptions);
|
|
1834
|
-
require$$9.debugDir('stdio', {
|
|
1835
|
-
gitSymbolicRefResult
|
|
1836
|
-
});
|
|
1837
2318
|
return gitSymbolicRefResult.stdout;
|
|
1838
2319
|
} catch (e) {
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
}
|
|
2320
|
+
// Expected in detached HEAD state, fallback to rev-parse.
|
|
2321
|
+
require$$9.debugDir('inspect', {
|
|
2322
|
+
message: 'In detached HEAD state',
|
|
2323
|
+
error: e
|
|
2324
|
+
});
|
|
1845
2325
|
}
|
|
1846
2326
|
// Fallback to using rev-parse to get the short commit hash in a
|
|
1847
2327
|
// detached HEAD state.
|
|
1848
|
-
quotedCmd = '`git rev-parse --short HEAD`';
|
|
1849
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1850
2328
|
try {
|
|
1851
2329
|
const gitRevParseResult = await spawn.spawn('git', ['rev-parse', '--short', 'HEAD'], stdioPipeOptions);
|
|
1852
|
-
require$$9.debugDir('stdio', {
|
|
1853
|
-
gitRevParseResult
|
|
1854
|
-
});
|
|
1855
2330
|
return gitRevParseResult.stdout;
|
|
1856
2331
|
} catch (e) {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
2332
|
+
// Both methods failed, likely not in a git repo.
|
|
2333
|
+
require$$9.debugDir('inspect', {
|
|
2334
|
+
message: 'Unable to determine git branch',
|
|
2335
|
+
error: e
|
|
2336
|
+
});
|
|
1863
2337
|
}
|
|
1864
2338
|
return undefined;
|
|
1865
2339
|
}
|
|
@@ -1890,14 +2364,12 @@ async function gitCleanFdx(cwd = process.cwd()) {
|
|
|
1890
2364
|
cwd,
|
|
1891
2365
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1892
2366
|
};
|
|
1893
|
-
const quotedCmd = '`git clean -fdx`';
|
|
1894
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1895
2367
|
try {
|
|
1896
2368
|
await spawn.spawn('git', ['clean', '-fdx'], stdioIgnoreOptions);
|
|
2369
|
+
debugGit('clean -fdx', true);
|
|
1897
2370
|
return true;
|
|
1898
2371
|
} catch (e) {
|
|
1899
|
-
|
|
1900
|
-
require$$9.debugDir('inspect', {
|
|
2372
|
+
debugGit('clean -fdx', false, {
|
|
1901
2373
|
error: e
|
|
1902
2374
|
});
|
|
1903
2375
|
}
|
|
@@ -1908,14 +2380,12 @@ async function gitCheckoutBranch(branch, cwd = process.cwd()) {
|
|
|
1908
2380
|
cwd,
|
|
1909
2381
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1910
2382
|
};
|
|
1911
|
-
const quotedCmd = `\`git checkout ${branch}\``;
|
|
1912
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1913
2383
|
try {
|
|
1914
2384
|
await spawn.spawn('git', ['checkout', branch], stdioIgnoreOptions);
|
|
2385
|
+
debugGit(`checkout ${branch}`, true);
|
|
1915
2386
|
return true;
|
|
1916
2387
|
} catch (e) {
|
|
1917
|
-
|
|
1918
|
-
require$$9.debugDir('inspect', {
|
|
2388
|
+
debugGit(`checkout ${branch}`, false, {
|
|
1919
2389
|
error: e
|
|
1920
2390
|
});
|
|
1921
2391
|
}
|
|
@@ -1929,14 +2399,12 @@ async function gitCreateBranch(branch, cwd = process.cwd()) {
|
|
|
1929
2399
|
cwd,
|
|
1930
2400
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1931
2401
|
};
|
|
1932
|
-
const quotedCmd = `\`git branch ${branch}\``;
|
|
1933
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1934
2402
|
try {
|
|
1935
2403
|
await spawn.spawn('git', ['branch', branch], stdioIgnoreOptions);
|
|
2404
|
+
debugGit(`branch ${branch}`, true);
|
|
1936
2405
|
return true;
|
|
1937
2406
|
} catch (e) {
|
|
1938
|
-
|
|
1939
|
-
require$$9.debugDir('inspect', {
|
|
2407
|
+
debugGit(`branch ${branch}`, false, {
|
|
1940
2408
|
error: e
|
|
1941
2409
|
});
|
|
1942
2410
|
}
|
|
@@ -1947,19 +2415,22 @@ async function gitPushBranch(branch, cwd = process.cwd()) {
|
|
|
1947
2415
|
cwd,
|
|
1948
2416
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1949
2417
|
};
|
|
1950
|
-
const quotedCmd = `\`git push --force --set-upstream origin ${branch}\``;
|
|
1951
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1952
2418
|
try {
|
|
1953
2419
|
await spawn.spawn('git', ['push', '--force', '--set-upstream', 'origin', branch], stdioIgnoreOptions);
|
|
2420
|
+
debugGit(`push ${branch}`, true);
|
|
1954
2421
|
return true;
|
|
1955
2422
|
} catch (e) {
|
|
1956
|
-
require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
|
|
1957
2423
|
if (spawn.isSpawnError(e) && e.code === 128) {
|
|
1958
|
-
require$$9.debugFn('error', "denied: token requires write permissions for 'contents' and 'pull-requests'");
|
|
2424
|
+
require$$9.debugFn('error', "Push denied: token requires write permissions for 'contents' and 'pull-requests'");
|
|
2425
|
+
require$$9.debugDir('error', e);
|
|
2426
|
+
require$$9.debugDir('inspect', {
|
|
2427
|
+
branch
|
|
2428
|
+
});
|
|
2429
|
+
} else {
|
|
2430
|
+
debugGit(`push ${branch}`, false, {
|
|
2431
|
+
error: e
|
|
2432
|
+
});
|
|
1959
2433
|
}
|
|
1960
|
-
require$$9.debugDir('inspect', {
|
|
1961
|
-
error: e
|
|
1962
|
-
});
|
|
1963
2434
|
}
|
|
1964
2435
|
return false;
|
|
1965
2436
|
}
|
|
@@ -1981,26 +2452,31 @@ async function gitCommit(commitMsg, filepaths, options) {
|
|
|
1981
2452
|
cwd,
|
|
1982
2453
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1983
2454
|
};
|
|
1984
|
-
const quotedAddCmd = `\`git add ${filepaths.join(' ')}\``;
|
|
1985
|
-
require$$9.debugFn('stdio', `spawn: ${quotedAddCmd}`);
|
|
1986
2455
|
try {
|
|
1987
2456
|
await spawn.spawn('git', ['add', ...filepaths], stdioIgnoreOptions);
|
|
2457
|
+
debugGit('add', true, {
|
|
2458
|
+
count: filepaths.length
|
|
2459
|
+
});
|
|
1988
2460
|
} catch (e) {
|
|
1989
|
-
|
|
1990
|
-
require$$9.debugDir('inspect', {
|
|
2461
|
+
debugGit('add', false, {
|
|
1991
2462
|
error: e
|
|
1992
2463
|
});
|
|
2464
|
+
require$$9.debugDir('inspect', {
|
|
2465
|
+
filepaths
|
|
2466
|
+
});
|
|
2467
|
+
return false;
|
|
1993
2468
|
}
|
|
1994
|
-
const quotedCommitCmd = `\`git commit -m ${commitMsg}\``;
|
|
1995
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCommitCmd}`);
|
|
1996
2469
|
try {
|
|
1997
2470
|
await spawn.spawn('git', ['commit', '-m', commitMsg], stdioIgnoreOptions);
|
|
2471
|
+
debugGit('commit', true);
|
|
1998
2472
|
return true;
|
|
1999
2473
|
} catch (e) {
|
|
2000
|
-
|
|
2001
|
-
require$$9.debugDir('inspect', {
|
|
2474
|
+
debugGit('commit', false, {
|
|
2002
2475
|
error: e
|
|
2003
2476
|
});
|
|
2477
|
+
require$$9.debugDir('inspect', {
|
|
2478
|
+
commitMsg
|
|
2479
|
+
});
|
|
2004
2480
|
}
|
|
2005
2481
|
return false;
|
|
2006
2482
|
}
|
|
@@ -2009,19 +2485,16 @@ async function gitDeleteBranch(branch, cwd = process.cwd()) {
|
|
|
2009
2485
|
cwd,
|
|
2010
2486
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2011
2487
|
};
|
|
2012
|
-
const quotedCmd = `\`git branch -D ${branch}\``;
|
|
2013
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2014
2488
|
try {
|
|
2015
2489
|
// Will throw with exit code 1 if branch does not exist.
|
|
2016
2490
|
await spawn.spawn('git', ['branch', '-D', branch], stdioIgnoreOptions);
|
|
2017
2491
|
return true;
|
|
2018
2492
|
} catch (e) {
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
}
|
|
2493
|
+
// Expected failure when branch doesn't exist.
|
|
2494
|
+
require$$9.debugDir('inspect', {
|
|
2495
|
+
message: `Branch deletion failed (may not exist): ${branch}`,
|
|
2496
|
+
error: e
|
|
2497
|
+
});
|
|
2025
2498
|
}
|
|
2026
2499
|
return false;
|
|
2027
2500
|
}
|
|
@@ -2035,41 +2508,30 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
|
|
|
2035
2508
|
1: value
|
|
2036
2509
|
}) => {
|
|
2037
2510
|
let configValue;
|
|
2038
|
-
{
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
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
|
-
}
|
|
2511
|
+
try {
|
|
2512
|
+
// Will throw with exit code 1 if the config property is not set.
|
|
2513
|
+
const gitConfigResult = await spawn.spawn('git', ['config', '--get', prop], stdioPipeOptions);
|
|
2514
|
+
configValue = gitConfigResult.stdout;
|
|
2515
|
+
} catch (e) {
|
|
2516
|
+
// Expected when config property is not set.
|
|
2517
|
+
require$$9.debugDir('inspect', {
|
|
2518
|
+
message: `Git config property not set: ${prop}`,
|
|
2519
|
+
error: e
|
|
2520
|
+
});
|
|
2056
2521
|
}
|
|
2057
2522
|
if (configValue !== value) {
|
|
2058
2523
|
const stdioIgnoreOptions = {
|
|
2059
2524
|
cwd,
|
|
2060
2525
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2061
2526
|
};
|
|
2062
|
-
const quotedCmd = `\`git config ${prop} ${value}\``;
|
|
2063
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2064
2527
|
try {
|
|
2065
2528
|
await spawn.spawn('git', ['config', prop, value], stdioIgnoreOptions);
|
|
2066
2529
|
} catch (e) {
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
}
|
|
2530
|
+
require$$9.debugFn('warn', `Failed to set git config: ${prop}`);
|
|
2531
|
+
require$$9.debugDir('warn', e);
|
|
2532
|
+
require$$9.debugDir('inspect', {
|
|
2533
|
+
value
|
|
2534
|
+
});
|
|
2073
2535
|
}
|
|
2074
2536
|
}
|
|
2075
2537
|
}));
|
|
@@ -2079,19 +2541,12 @@ async function gitLocalBranchExists(branch, cwd = process.cwd()) {
|
|
|
2079
2541
|
cwd,
|
|
2080
2542
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2081
2543
|
};
|
|
2082
|
-
const quotedCmd = `\`git show-ref --quiet refs/heads/${branch}\``;
|
|
2083
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2084
2544
|
try {
|
|
2085
2545
|
// Will throw with exit code 1 if the branch does not exist.
|
|
2086
2546
|
await spawn.spawn('git', ['show-ref', constants.FLAG_QUIET, `refs/heads/${branch}`], stdioIgnoreOptions);
|
|
2087
2547
|
return true;
|
|
2088
|
-
} catch
|
|
2089
|
-
|
|
2090
|
-
require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
|
|
2091
|
-
require$$9.debugDir('inspect', {
|
|
2092
|
-
error: e
|
|
2093
|
-
});
|
|
2094
|
-
}
|
|
2548
|
+
} catch {
|
|
2549
|
+
// Expected when branch doesn't exist - no logging needed.
|
|
2095
2550
|
}
|
|
2096
2551
|
return false;
|
|
2097
2552
|
}
|
|
@@ -2099,21 +2554,15 @@ async function gitRemoteBranchExists(branch, cwd = process.cwd()) {
|
|
|
2099
2554
|
const stdioPipeOptions = {
|
|
2100
2555
|
cwd
|
|
2101
2556
|
};
|
|
2102
|
-
const quotedCmd = `\`git ls-remote --heads origin ${branch}\``;
|
|
2103
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2104
2557
|
try {
|
|
2105
2558
|
const lsRemoteResult = await spawn.spawn('git', ['ls-remote', '--heads', 'origin', branch], stdioPipeOptions);
|
|
2106
|
-
require$$9.debugDir('stdio', {
|
|
2107
|
-
lsRemoteResult
|
|
2108
|
-
});
|
|
2109
2559
|
return lsRemoteResult.stdout.length > 0;
|
|
2110
2560
|
} catch (e) {
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
}
|
|
2561
|
+
// Expected when remote is not accessible or branch doesn't exist.
|
|
2562
|
+
require$$9.debugDir('inspect', {
|
|
2563
|
+
message: `Remote branch check failed: ${branch}`,
|
|
2564
|
+
error: e
|
|
2565
|
+
});
|
|
2117
2566
|
}
|
|
2118
2567
|
return false;
|
|
2119
2568
|
}
|
|
@@ -2128,14 +2577,12 @@ async function gitResetHard(branch = 'HEAD', cwd = process.cwd()) {
|
|
|
2128
2577
|
cwd,
|
|
2129
2578
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2130
2579
|
};
|
|
2131
|
-
const quotedCmd = `\`git reset --hard ${branch}\``;
|
|
2132
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2133
2580
|
try {
|
|
2134
2581
|
await spawn.spawn('git', ['reset', '--hard', branch], stdioIgnoreOptions);
|
|
2582
|
+
debugGit(`reset --hard ${branch}`, true);
|
|
2135
2583
|
return true;
|
|
2136
2584
|
} catch (e) {
|
|
2137
|
-
|
|
2138
|
-
require$$9.debugDir('inspect', {
|
|
2585
|
+
debugGit(`reset --hard ${branch}`, false, {
|
|
2139
2586
|
error: e
|
|
2140
2587
|
});
|
|
2141
2588
|
}
|
|
@@ -2145,13 +2592,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
|
|
|
2145
2592
|
const stdioPipeOptions = {
|
|
2146
2593
|
cwd
|
|
2147
2594
|
};
|
|
2148
|
-
const quotedCmd = `\`git diff --name-only\``;
|
|
2149
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2150
2595
|
try {
|
|
2151
2596
|
const gitDiffResult = await spawn.spawn('git', ['diff', '--name-only'], stdioPipeOptions);
|
|
2152
|
-
require$$9.debugDir('stdio', {
|
|
2153
|
-
gitDiffResult
|
|
2154
|
-
});
|
|
2155
2597
|
const changedFilesDetails = gitDiffResult.stdout;
|
|
2156
2598
|
const relPaths = changedFilesDetails.split('\n');
|
|
2157
2599
|
return {
|
|
@@ -2159,10 +2601,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
|
|
|
2159
2601
|
data: relPaths.map(p => path$1.normalizePath(p))
|
|
2160
2602
|
};
|
|
2161
2603
|
} catch (e) {
|
|
2162
|
-
require$$9.debugFn('error',
|
|
2163
|
-
require$$9.debugDir('
|
|
2164
|
-
error: e
|
|
2165
|
-
});
|
|
2604
|
+
require$$9.debugFn('error', 'Failed to get unstaged modified files');
|
|
2605
|
+
require$$9.debugDir('error', e);
|
|
2166
2606
|
return {
|
|
2167
2607
|
ok: false,
|
|
2168
2608
|
message: 'Git Error',
|
|
@@ -2210,6 +2650,72 @@ function parseGitRemoteUrl(remoteUrl) {
|
|
|
2210
2650
|
} : result;
|
|
2211
2651
|
}
|
|
2212
2652
|
|
|
2653
|
+
/**
|
|
2654
|
+
* Package URL (PURL) utilities for Socket CLI.
|
|
2655
|
+
* Implements the PURL specification for universal package identification.
|
|
2656
|
+
*
|
|
2657
|
+
* PURL Format:
|
|
2658
|
+
* pkg:type/namespace/name@version?qualifiers#subpath
|
|
2659
|
+
*
|
|
2660
|
+
* Key Functions:
|
|
2661
|
+
* - createPurlObject: Create PURL from components
|
|
2662
|
+
* - isPurl: Check if string is valid PURL
|
|
2663
|
+
* - normalizePurl: Normalize PURL format
|
|
2664
|
+
* - parsePurl: Parse PURL string to object
|
|
2665
|
+
* - purlToString: Convert PURL object to string
|
|
2666
|
+
*
|
|
2667
|
+
* Supported Types:
|
|
2668
|
+
* - cargo: Rust packages
|
|
2669
|
+
* - gem: Ruby packages
|
|
2670
|
+
* - go: Go modules
|
|
2671
|
+
* - maven: Java packages
|
|
2672
|
+
* - npm: Node.js packages
|
|
2673
|
+
* - pypi: Python packages
|
|
2674
|
+
*
|
|
2675
|
+
* See: https://github.com/package-url/purl-spec
|
|
2676
|
+
*/
|
|
2677
|
+
|
|
2678
|
+
function createPurlObject(type, name, options) {
|
|
2679
|
+
let opts;
|
|
2680
|
+
if (require$$11.isObjectObject(type)) {
|
|
2681
|
+
opts = {
|
|
2682
|
+
__proto__: null,
|
|
2683
|
+
...type
|
|
2684
|
+
};
|
|
2685
|
+
type = opts.type;
|
|
2686
|
+
name = opts.name;
|
|
2687
|
+
} else if (require$$11.isObjectObject(name)) {
|
|
2688
|
+
opts = {
|
|
2689
|
+
__proto__: null,
|
|
2690
|
+
...name
|
|
2691
|
+
};
|
|
2692
|
+
name = opts.name;
|
|
2693
|
+
} else {
|
|
2694
|
+
opts = {
|
|
2695
|
+
__proto__: null,
|
|
2696
|
+
...options
|
|
2697
|
+
};
|
|
2698
|
+
if (typeof name !== 'string') {
|
|
2699
|
+
name = opts.name;
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
const {
|
|
2703
|
+
namespace,
|
|
2704
|
+
qualifiers,
|
|
2705
|
+
subpath,
|
|
2706
|
+
throws,
|
|
2707
|
+
version
|
|
2708
|
+
} = opts;
|
|
2709
|
+
const shouldThrow = throws === undefined || !!throws;
|
|
2710
|
+
try {
|
|
2711
|
+
return new vendor.packageurlJsExports.PackageURL(type, namespace, name, version, qualifiers, subpath);
|
|
2712
|
+
} catch (e) {
|
|
2713
|
+
if (shouldThrow) {
|
|
2714
|
+
throw e;
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
return undefined;
|
|
2718
|
+
}
|
|
2213
2719
|
function getPurlObject(purl, options) {
|
|
2214
2720
|
const {
|
|
2215
2721
|
throws
|
|
@@ -2231,6 +2737,26 @@ function normalizePurl(rawPurl) {
|
|
|
2231
2737
|
return rawPurl.startsWith('pkg:') ? rawPurl : `pkg:${rawPurl}`;
|
|
2232
2738
|
}
|
|
2233
2739
|
|
|
2740
|
+
/**
|
|
2741
|
+
* Socket.dev URL utilities for Socket CLI.
|
|
2742
|
+
* Generates URLs for Socket.dev website features and resources.
|
|
2743
|
+
*
|
|
2744
|
+
* Key Functions:
|
|
2745
|
+
* - getPkgFullNameFromPurl: Extract full package name from PURL
|
|
2746
|
+
* - getSocketDevAlertUrl: Generate alert type documentation URL
|
|
2747
|
+
* - getSocketDevPackageOverviewUrl: Generate package overview URL
|
|
2748
|
+
* - getSocketDevPackageOverviewUrlFromPurl: Generate overview URL from PURL
|
|
2749
|
+
* - getSocketDevPackageUrl: Generate package detail URL
|
|
2750
|
+
* - getSocketDevPackageUrlFromPurl: Generate package URL from PURL
|
|
2751
|
+
* - getSocketDevReportUrl: Generate scan report URL
|
|
2752
|
+
*
|
|
2753
|
+
* URL Generation:
|
|
2754
|
+
* - Package overview and detail pages
|
|
2755
|
+
* - Security alert documentation
|
|
2756
|
+
* - Scan report links
|
|
2757
|
+
* - Ecosystem-specific URL formatting
|
|
2758
|
+
*/
|
|
2759
|
+
|
|
2234
2760
|
function getPkgFullNameFromPurl(purl) {
|
|
2235
2761
|
const purlObj = getPurlObject(purl);
|
|
2236
2762
|
const {
|
|
@@ -2273,6 +2799,19 @@ function* walkNestedMap(map, keys = []) {
|
|
|
2273
2799
|
}
|
|
2274
2800
|
}
|
|
2275
2801
|
|
|
2802
|
+
/**
|
|
2803
|
+
* Coana integration utilities for Socket CLI.
|
|
2804
|
+
* Manages reachability analysis via Coana tech CLI.
|
|
2805
|
+
*
|
|
2806
|
+
* Key Functions:
|
|
2807
|
+
* - extractTier1ReachabilityScanId: Extract scan ID from socket facts file
|
|
2808
|
+
*
|
|
2809
|
+
* Integration:
|
|
2810
|
+
* - Works with @coana-tech/cli for reachability analysis
|
|
2811
|
+
* - Processes socket facts JSON files
|
|
2812
|
+
* - Extracts tier 1 reachability scan identifiers
|
|
2813
|
+
*/
|
|
2814
|
+
|
|
2276
2815
|
function extractTier1ReachabilityScanId(socketFactsFile) {
|
|
2277
2816
|
const json = fs.readJsonSync(socketFactsFile, {
|
|
2278
2817
|
throws: false
|
|
@@ -2281,6 +2820,25 @@ function extractTier1ReachabilityScanId(socketFactsFile) {
|
|
|
2281
2820
|
return tier1ReachabilityScanId.length > 0 ? tier1ReachabilityScanId : undefined;
|
|
2282
2821
|
}
|
|
2283
2822
|
|
|
2823
|
+
/**
|
|
2824
|
+
* File system utilities for Socket CLI.
|
|
2825
|
+
* Provides file and directory search functionality.
|
|
2826
|
+
*
|
|
2827
|
+
* Key Functions:
|
|
2828
|
+
* - findUp: Search for files/directories up the directory tree
|
|
2829
|
+
*
|
|
2830
|
+
* Features:
|
|
2831
|
+
* - Upward directory traversal
|
|
2832
|
+
* - Supports file and directory searching
|
|
2833
|
+
* - Abort signal support for cancellation
|
|
2834
|
+
* - Multiple name search support
|
|
2835
|
+
*
|
|
2836
|
+
* Usage:
|
|
2837
|
+
* - Finding configuration files (package.json, lockfiles)
|
|
2838
|
+
* - Locating project root directories
|
|
2839
|
+
* - Searching for specific files in parent directories
|
|
2840
|
+
*/
|
|
2841
|
+
|
|
2284
2842
|
async function findUp(name, options) {
|
|
2285
2843
|
const opts = {
|
|
2286
2844
|
__proto__: null,
|
|
@@ -2622,13 +3180,15 @@ function exitWithBinPathError$2(binName) {
|
|
|
2622
3180
|
// could not be found.
|
|
2623
3181
|
// eslint-disable-next-line n/no-process-exit
|
|
2624
3182
|
process.exit(127);
|
|
3183
|
+
// This line is never reached in production, but helps tests.
|
|
3184
|
+
throw new Error('process.exit called');
|
|
2625
3185
|
}
|
|
2626
3186
|
let _yarnBinPath;
|
|
2627
3187
|
function getYarnBinPath() {
|
|
2628
3188
|
if (_yarnBinPath === undefined) {
|
|
2629
3189
|
_yarnBinPath = getYarnBinPathDetails().path;
|
|
2630
3190
|
if (!_yarnBinPath) {
|
|
2631
|
-
exitWithBinPathError$2(constants.
|
|
3191
|
+
exitWithBinPathError$2(constants.YARN);
|
|
2632
3192
|
}
|
|
2633
3193
|
}
|
|
2634
3194
|
return _yarnBinPath;
|
|
@@ -2636,7 +3196,7 @@ function getYarnBinPath() {
|
|
|
2636
3196
|
let _yarnBinPathDetails;
|
|
2637
3197
|
function getYarnBinPathDetails() {
|
|
2638
3198
|
if (_yarnBinPathDetails === undefined) {
|
|
2639
|
-
_yarnBinPathDetails = findBinPathDetailsSync(constants.
|
|
3199
|
+
_yarnBinPathDetails = findBinPathDetailsSync(constants.YARN);
|
|
2640
3200
|
}
|
|
2641
3201
|
return _yarnBinPathDetails;
|
|
2642
3202
|
}
|
|
@@ -2651,6 +3211,9 @@ function isYarnBerry() {
|
|
|
2651
3211
|
const yarnBinPath = getYarnBinPath();
|
|
2652
3212
|
const result = spawn.spawnSync(yarnBinPath, ['--version'], {
|
|
2653
3213
|
encoding: 'utf8',
|
|
3214
|
+
// On Windows, yarn is often a .cmd file that requires shell execution.
|
|
3215
|
+
// The spawn function from @socketsecurity/registry will handle this properly
|
|
3216
|
+
// when shell is true.
|
|
2654
3217
|
shell: constants.default.WIN32
|
|
2655
3218
|
});
|
|
2656
3219
|
if (result.status === 0 && result.stdout) {
|
|
@@ -2668,202 +3231,25 @@ function isYarnBerry() {
|
|
|
2668
3231
|
return _isYarnBerry;
|
|
2669
3232
|
}
|
|
2670
3233
|
|
|
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
|
-
/**
|
|
2755
|
-
* Convert command arguments to a properly formatted string representation.
|
|
2756
|
-
*/
|
|
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
3234
|
/**
|
|
2799
|
-
*
|
|
3235
|
+
* DLX execution utilities for Socket CLI.
|
|
3236
|
+
* Manages package execution via npx/pnpm dlx/yarn dlx commands.
|
|
3237
|
+
*
|
|
3238
|
+
* Key Functions:
|
|
3239
|
+
* - spawnCdxgenDlx: Execute CycloneDX generator via dlx
|
|
3240
|
+
* - spawnCoanaDlx: Execute Coana CLI tool via dlx
|
|
3241
|
+
* - spawnDlx: Execute packages using dlx-style commands
|
|
3242
|
+
* - spawnSynpDlx: Execute Synp converter via dlx
|
|
3243
|
+
*
|
|
3244
|
+
* Package Manager Detection:
|
|
3245
|
+
* - Auto-detects npm, pnpm, or yarn based on lockfiles
|
|
3246
|
+
* - Supports force-refresh and silent execution modes
|
|
3247
|
+
*
|
|
3248
|
+
* Integration:
|
|
3249
|
+
* - Works with shadow binaries for security scanning
|
|
3250
|
+
* - Handles version pinning and cache management
|
|
3251
|
+
* - Configures environment for third-party tools
|
|
2800
3252
|
*/
|
|
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
3253
|
|
|
2868
3254
|
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
3255
|
const {
|
|
@@ -2919,10 +3305,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2919
3305
|
const packageString = `${packageSpec.name}@${packageSpec.version}`;
|
|
2920
3306
|
|
|
2921
3307
|
// Build command args based on package manager.
|
|
2922
|
-
let binName;
|
|
2923
3308
|
let spawnArgs;
|
|
2924
3309
|
if (pm === constants.PNPM) {
|
|
2925
|
-
binName = constants.PNPM;
|
|
2926
3310
|
spawnArgs = ['dlx'];
|
|
2927
3311
|
if (force) {
|
|
2928
3312
|
// For pnpm, set dlx-cache-max-age to 0 via env to force fresh download.
|
|
@@ -2949,7 +3333,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2949
3333
|
const shadowPnpmBin = /*@__PURE__*/require$2(constants.default.shadowPnpmBinPath);
|
|
2950
3334
|
return await shadowPnpmBin(spawnArgs, finalShadowOptions, spawnExtra);
|
|
2951
3335
|
} else if (pm === constants.YARN && isYarnBerry()) {
|
|
2952
|
-
binName = constants.YARN;
|
|
2953
3336
|
spawnArgs = ['dlx'];
|
|
2954
3337
|
// Yarn dlx runs in a temporary environment by design and should always fetch fresh.
|
|
2955
3338
|
if (silent) {
|
|
@@ -2961,7 +3344,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2961
3344
|
} else {
|
|
2962
3345
|
// Use npm exec/npx.
|
|
2963
3346
|
// For consistency, we'll use npx which is more commonly used for one-off execution.
|
|
2964
|
-
binName = 'npx';
|
|
2965
3347
|
spawnArgs = ['--yes'];
|
|
2966
3348
|
if (force) {
|
|
2967
3349
|
// Use --force to bypass cache and get latest within range.
|
|
@@ -2971,7 +3353,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2971
3353
|
spawnArgs.push(constants.FLAG_SILENT);
|
|
2972
3354
|
}
|
|
2973
3355
|
spawnArgs.push(packageString, ...args);
|
|
2974
|
-
|
|
3356
|
+
const shadowNpxBin = /*@__PURE__*/require$2(constants.default.shadowNpxBinPath);
|
|
3357
|
+
return await shadowNpxBin(spawnArgs, finalShadowOptions, spawnExtra);
|
|
2975
3358
|
}
|
|
2976
3359
|
}
|
|
2977
3360
|
|
|
@@ -3036,8 +3419,8 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
|
|
|
3036
3419
|
};
|
|
3037
3420
|
} catch (e) {
|
|
3038
3421
|
const stderr = e?.stderr;
|
|
3039
|
-
const cause = e
|
|
3040
|
-
const message = stderr
|
|
3422
|
+
const cause = getErrorCause(e);
|
|
3423
|
+
const message = stderr || cause;
|
|
3041
3424
|
return {
|
|
3042
3425
|
ok: false,
|
|
3043
3426
|
data: e,
|
|
@@ -3084,6 +3467,26 @@ function hasEnterpriseOrgPlan(orgs) {
|
|
|
3084
3467
|
return orgs.some(o => o.plan === 'enterprise');
|
|
3085
3468
|
}
|
|
3086
3469
|
|
|
3470
|
+
/**
|
|
3471
|
+
* Socket JSON utilities for Socket CLI.
|
|
3472
|
+
* Manages .socket/socket.json configuration and scan metadata.
|
|
3473
|
+
*
|
|
3474
|
+
* Key Functions:
|
|
3475
|
+
* - loadDotSocketDirectory: Load .socket directory configuration
|
|
3476
|
+
* - saveSocketJson: Persist scan configuration to .socket/socket.json
|
|
3477
|
+
* - validateSocketJson: Validate socket.json structure
|
|
3478
|
+
*
|
|
3479
|
+
* File Structure:
|
|
3480
|
+
* - Contains scan metadata and configuration
|
|
3481
|
+
* - Stores scan IDs and repository information
|
|
3482
|
+
* - Tracks CLI version and scan timestamps
|
|
3483
|
+
*
|
|
3484
|
+
* Directory Management:
|
|
3485
|
+
* - Creates .socket directory as needed
|
|
3486
|
+
* - Handles nested directory structures
|
|
3487
|
+
* - Supports both read and write operations
|
|
3488
|
+
*/
|
|
3489
|
+
|
|
3087
3490
|
function readOrDefaultSocketJson(cwd) {
|
|
3088
3491
|
const jsonCResult = readSocketJsonSync(cwd, true);
|
|
3089
3492
|
return jsonCResult.ok ? jsonCResult.data :
|
|
@@ -3129,35 +3532,31 @@ function readSocketJsonSync(cwd, defaultOnError = false) {
|
|
|
3129
3532
|
} catch (e) {
|
|
3130
3533
|
if (defaultOnError) {
|
|
3131
3534
|
logger.logger.warn(`Failed to read ${constants.SOCKET_JSON}, using default`);
|
|
3132
|
-
require$$9.
|
|
3133
|
-
|
|
3134
|
-
});
|
|
3535
|
+
require$$9.debugFn('warn', `Failed to read ${constants.SOCKET_JSON} sync`);
|
|
3536
|
+
require$$9.debugDir('warn', e);
|
|
3135
3537
|
return {
|
|
3136
3538
|
ok: true,
|
|
3137
3539
|
data: getDefaultSocketJson()
|
|
3138
3540
|
};
|
|
3139
3541
|
}
|
|
3140
|
-
const cause = e
|
|
3141
|
-
require$$9.
|
|
3142
|
-
|
|
3143
|
-
});
|
|
3542
|
+
const cause = formatErrorWithDetail(`An error occurred while trying to read ${constants.SOCKET_JSON}`, e);
|
|
3543
|
+
require$$9.debugFn('error', `Failed to read ${constants.SOCKET_JSON} sync`);
|
|
3544
|
+
require$$9.debugDir('error', e);
|
|
3144
3545
|
return {
|
|
3145
3546
|
ok: false,
|
|
3146
3547
|
message: `Failed to read ${constants.SOCKET_JSON}`,
|
|
3147
|
-
cause
|
|
3548
|
+
cause
|
|
3148
3549
|
};
|
|
3149
3550
|
}
|
|
3150
3551
|
let jsonObj;
|
|
3151
3552
|
try {
|
|
3152
3553
|
jsonObj = JSON.parse(jsonContent);
|
|
3153
3554
|
} catch (e) {
|
|
3154
|
-
require$$9.debugFn('error',
|
|
3555
|
+
require$$9.debugFn('error', `Failed to parse ${constants.SOCKET_JSON} as JSON (sync)`);
|
|
3155
3556
|
require$$9.debugDir('inspect', {
|
|
3156
3557
|
jsonContent
|
|
3157
3558
|
});
|
|
3158
|
-
require$$9.debugDir('
|
|
3159
|
-
error: e
|
|
3160
|
-
});
|
|
3559
|
+
require$$9.debugDir('error', e);
|
|
3161
3560
|
if (defaultOnError) {
|
|
3162
3561
|
logger.logger.warn(`Failed to parse ${constants.SOCKET_JSON}, using default`);
|
|
3163
3562
|
return {
|
|
@@ -3191,11 +3590,11 @@ async function writeSocketJson(cwd, sockJson) {
|
|
|
3191
3590
|
try {
|
|
3192
3591
|
jsonContent = JSON.stringify(sockJson, null, 2);
|
|
3193
3592
|
} catch (e) {
|
|
3194
|
-
require$$9.debugFn('error',
|
|
3593
|
+
require$$9.debugFn('error', `Failed to serialize ${constants.SOCKET_JSON} to JSON`);
|
|
3195
3594
|
require$$9.debugDir('inspect', {
|
|
3196
|
-
error: e,
|
|
3197
3595
|
sockJson
|
|
3198
3596
|
});
|
|
3597
|
+
require$$9.debugDir('error', e);
|
|
3199
3598
|
return {
|
|
3200
3599
|
ok: false,
|
|
3201
3600
|
message: 'Failed to serialize to JSON',
|
|
@@ -3210,6 +3609,32 @@ async function writeSocketJson(cwd, sockJson) {
|
|
|
3210
3609
|
};
|
|
3211
3610
|
}
|
|
3212
3611
|
|
|
3612
|
+
/**
|
|
3613
|
+
* GitHub utilities for Socket CLI.
|
|
3614
|
+
* Provides GitHub API integration for repository operations and GHSA vulnerability data.
|
|
3615
|
+
*
|
|
3616
|
+
* Authentication:
|
|
3617
|
+
* - getGitHubToken: Retrieve GitHub token from env/git config
|
|
3618
|
+
* - getOctokit: Get authenticated Octokit instance
|
|
3619
|
+
* - getOctokitGraphql: Get authenticated GraphQL client
|
|
3620
|
+
*
|
|
3621
|
+
* Caching:
|
|
3622
|
+
* - 5-minute TTL for API responses
|
|
3623
|
+
* - Automatic cache invalidation
|
|
3624
|
+
* - Persistent cache in node_modules/.cache
|
|
3625
|
+
*
|
|
3626
|
+
* GHSA Operations:
|
|
3627
|
+
* - cacheFetch: Cache API responses with TTL
|
|
3628
|
+
* - fetchGhsaDetails: Fetch GitHub Security Advisory details
|
|
3629
|
+
* - getGhsaUrl: Generate GHSA advisory URL
|
|
3630
|
+
* - readCache/writeCache: Persistent cache operations
|
|
3631
|
+
*
|
|
3632
|
+
* Repository Operations:
|
|
3633
|
+
* - GraphQL queries for complex operations
|
|
3634
|
+
* - Integration with Octokit REST API
|
|
3635
|
+
* - Support for GitHub Actions environment variables
|
|
3636
|
+
*/
|
|
3637
|
+
|
|
3213
3638
|
async function readCache(key,
|
|
3214
3639
|
// 5 minute in milliseconds time to live (TTL).
|
|
3215
3640
|
ttlMs = 5 * 60 * 1000) {
|
|
@@ -3289,11 +3714,8 @@ async function fetchGhsaDetails(ids) {
|
|
|
3289
3714
|
}
|
|
3290
3715
|
}
|
|
3291
3716
|
} catch (e) {
|
|
3292
|
-
|
|
3293
|
-
require$$9.
|
|
3294
|
-
require$$9.debugDir('inspect', {
|
|
3295
|
-
error: e
|
|
3296
|
-
});
|
|
3717
|
+
require$$9.debugFn('error', formatErrorWithDetail('Failed to fetch GHSA details', e));
|
|
3718
|
+
require$$9.debugDir('error', e);
|
|
3297
3719
|
}
|
|
3298
3720
|
return results;
|
|
3299
3721
|
}
|
|
@@ -3397,12 +3819,153 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
|
|
|
3397
3819
|
await spawn.spawn('git', ['remote', 'set-url', 'origin', url], stdioIgnoreOptions);
|
|
3398
3820
|
return true;
|
|
3399
3821
|
} catch (e) {
|
|
3400
|
-
require$$9.debugFn('error', `
|
|
3822
|
+
require$$9.debugFn('error', `Git command failed: ${quotedCmd}`);
|
|
3401
3823
|
require$$9.debugDir('inspect', {
|
|
3402
|
-
|
|
3824
|
+
cmd: quotedCmd
|
|
3403
3825
|
});
|
|
3826
|
+
require$$9.debugDir('error', e);
|
|
3827
|
+
}
|
|
3828
|
+
return false;
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
/**
|
|
3832
|
+
* Command-line utilities for Socket CLI.
|
|
3833
|
+
* Handles argument parsing, flag processing, and command formatting.
|
|
3834
|
+
*
|
|
3835
|
+
* Argument Handling:
|
|
3836
|
+
* - Handles both long (--flag) and short (-f) formats
|
|
3837
|
+
* - Preserves special characters and escaping
|
|
3838
|
+
* - Properly quotes arguments containing spaces
|
|
3839
|
+
*
|
|
3840
|
+
* Command Names:
|
|
3841
|
+
* - commandNameFromCamel: Convert camelCase to kebab-case command names
|
|
3842
|
+
* - commandNameFromKebab: Convert kebab-case to camelCase
|
|
3843
|
+
*
|
|
3844
|
+
* Flag Processing:
|
|
3845
|
+
* - cmdFlagsToString: Format arguments for display with proper escaping
|
|
3846
|
+
* - cmdPrefixMessage: Generate command prefix message
|
|
3847
|
+
* - stripConfigFlags: Remove --config flags from argument list
|
|
3848
|
+
* - stripDebugFlags: Remove debug-related flags
|
|
3849
|
+
* - stripHelpFlags: Remove help flags (-h, --help)
|
|
3850
|
+
*/
|
|
3851
|
+
|
|
3852
|
+
const helpFlags = new Set([constants.FLAG_HELP, '-h']);
|
|
3853
|
+
|
|
3854
|
+
/**
|
|
3855
|
+
* Convert command arguments to a properly formatted string representation.
|
|
3856
|
+
*/
|
|
3857
|
+
function cmdFlagsToString(args) {
|
|
3858
|
+
const result = [];
|
|
3859
|
+
for (let i = 0, {
|
|
3860
|
+
length
|
|
3861
|
+
} = args; i < length; i += 1) {
|
|
3862
|
+
const arg = args[i].trim();
|
|
3863
|
+
if (arg.startsWith('--')) {
|
|
3864
|
+
const nextArg = i + 1 < length ? args[i + 1].trim() : undefined;
|
|
3865
|
+
// Check if the next item exists and is NOT another flag.
|
|
3866
|
+
if (nextArg && !nextArg.startsWith('--') && !nextArg.startsWith('-')) {
|
|
3867
|
+
result.push(`${arg}=${nextArg}`);
|
|
3868
|
+
i += 1;
|
|
3869
|
+
} else {
|
|
3870
|
+
result.push(arg);
|
|
3871
|
+
}
|
|
3872
|
+
} else {
|
|
3873
|
+
// Include non-flag arguments (commands, package names, etc.).
|
|
3874
|
+
result.push(arg);
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
return result.join(' ');
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
/**
|
|
3881
|
+
* Convert flag values to array format for processing.
|
|
3882
|
+
*/
|
|
3883
|
+
function cmdFlagValueToArray(value) {
|
|
3884
|
+
if (typeof value === 'string') {
|
|
3885
|
+
return value.trim().split(/, */).filter(Boolean);
|
|
3886
|
+
}
|
|
3887
|
+
if (Array.isArray(value)) {
|
|
3888
|
+
return value.flatMap(cmdFlagValueToArray);
|
|
3889
|
+
}
|
|
3890
|
+
return [];
|
|
3891
|
+
}
|
|
3892
|
+
|
|
3893
|
+
/**
|
|
3894
|
+
* Add command name prefix to message text.
|
|
3895
|
+
*/
|
|
3896
|
+
function cmdPrefixMessage(cmdName, text) {
|
|
3897
|
+
const cmdPrefix = cmdName ? `${cmdName}: ` : '';
|
|
3898
|
+
return `${cmdPrefix}${text}`;
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
/**
|
|
3902
|
+
* Filter out Socket flags from argv before passing to subcommands.
|
|
3903
|
+
*/
|
|
3904
|
+
function filterFlags(argv, flagsToFilter, exceptions) {
|
|
3905
|
+
const filtered = [];
|
|
3906
|
+
|
|
3907
|
+
// Build set of flags to filter from the provided flag objects.
|
|
3908
|
+
const flagsToFilterSet = new Set();
|
|
3909
|
+
const flagsWithValueSet = new Set();
|
|
3910
|
+
for (const [flagName, flag] of Object.entries(flagsToFilter)) {
|
|
3911
|
+
const longFlag = `--${camelToKebab(flagName)}`;
|
|
3912
|
+
// Special case for negated booleans.
|
|
3913
|
+
if (flagName === 'spinner' || flagName === 'banner') {
|
|
3914
|
+
flagsToFilterSet.add(`--no-${flagName}`);
|
|
3915
|
+
} else {
|
|
3916
|
+
flagsToFilterSet.add(longFlag);
|
|
3917
|
+
}
|
|
3918
|
+
if (flag?.shortFlag) {
|
|
3919
|
+
flagsToFilterSet.add(`-${flag.shortFlag}`);
|
|
3920
|
+
}
|
|
3921
|
+
// Track flags that take values.
|
|
3922
|
+
if (flag.type !== 'boolean') {
|
|
3923
|
+
flagsWithValueSet.add(longFlag);
|
|
3924
|
+
if (flag?.shortFlag) {
|
|
3925
|
+
flagsWithValueSet.add(`-${flag.shortFlag}`);
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
for (let i = 0, {
|
|
3930
|
+
length
|
|
3931
|
+
} = argv; i < length; i += 1) {
|
|
3932
|
+
const arg = argv[i];
|
|
3933
|
+
// Check if this flag should be kept as an exception.
|
|
3934
|
+
if (exceptions?.includes(arg)) {
|
|
3935
|
+
filtered.push(arg);
|
|
3936
|
+
// Handle flags that take values.
|
|
3937
|
+
if (flagsWithValueSet.has(arg)) {
|
|
3938
|
+
// Include the next argument (the flag value).
|
|
3939
|
+
i += 1;
|
|
3940
|
+
if (i < length) {
|
|
3941
|
+
filtered.push(argv[i]);
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
} else if (flagsToFilterSet.has(arg)) {
|
|
3945
|
+
// Skip flags that take values.
|
|
3946
|
+
if (flagsWithValueSet.has(arg)) {
|
|
3947
|
+
// Skip the next argument (the flag value).
|
|
3948
|
+
i += 1;
|
|
3949
|
+
}
|
|
3950
|
+
// Skip boolean flags (no additional argument to skip).
|
|
3951
|
+
} else if (arg && Array.from(flagsWithValueSet).some(flag => arg.startsWith(`${flag}=`))) {
|
|
3952
|
+
// Skip --flag=value format for Socket flags unless it's an exception.
|
|
3953
|
+
if (exceptions?.some(exc => arg.startsWith(`${exc}=`))) {
|
|
3954
|
+
filtered.push(arg);
|
|
3955
|
+
}
|
|
3956
|
+
// Otherwise skip it.
|
|
3957
|
+
} else {
|
|
3958
|
+
filtered.push(arg);
|
|
3959
|
+
}
|
|
3404
3960
|
}
|
|
3405
|
-
return
|
|
3961
|
+
return filtered;
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
/**
|
|
3965
|
+
* Check if argument is a help flag.
|
|
3966
|
+
*/
|
|
3967
|
+
function isHelpFlag(cmdArg) {
|
|
3968
|
+
return helpFlags.has(cmdArg);
|
|
3406
3969
|
}
|
|
3407
3970
|
|
|
3408
3971
|
/**
|
|
@@ -3429,7 +3992,7 @@ async function convertCveToGhsa(cveId) {
|
|
|
3429
3992
|
} catch (e) {
|
|
3430
3993
|
return {
|
|
3431
3994
|
ok: false,
|
|
3432
|
-
message: `Failed to convert CVE to GHSA: ${e
|
|
3995
|
+
message: `Failed to convert CVE to GHSA: ${getErrorCause(e)}`
|
|
3433
3996
|
};
|
|
3434
3997
|
}
|
|
3435
3998
|
}
|
|
@@ -3493,7 +4056,7 @@ async function convertPurlToGhsas(purl) {
|
|
|
3493
4056
|
} catch (e) {
|
|
3494
4057
|
return {
|
|
3495
4058
|
ok: false,
|
|
3496
|
-
message: `Failed to convert PURL to GHSA: ${e
|
|
4059
|
+
message: `Failed to convert PURL to GHSA: ${getErrorCause(e)}`
|
|
3497
4060
|
};
|
|
3498
4061
|
}
|
|
3499
4062
|
}
|
|
@@ -3564,39 +4127,100 @@ fi
|
|
|
3564
4127
|
};
|
|
3565
4128
|
}
|
|
3566
4129
|
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
4130
|
+
/**
|
|
4131
|
+
* Safe wrapper for npm-package-arg that doesn't throw.
|
|
4132
|
+
* Returns undefined if parsing fails.
|
|
4133
|
+
*/
|
|
4134
|
+
function safeNpa$1(...args) {
|
|
4135
|
+
try {
|
|
4136
|
+
return Reflect.apply(vendor.npaExports, undefined, args);
|
|
4137
|
+
} catch {}
|
|
4138
|
+
return undefined;
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
function exitWithBinPathError$1(binName) {
|
|
4142
|
+
logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
|
|
4143
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
4144
|
+
// could not be found.
|
|
4145
|
+
// eslint-disable-next-line n/no-process-exit
|
|
4146
|
+
process.exit(127);
|
|
4147
|
+
// This line is never reached in production, but helps tests.
|
|
4148
|
+
throw new Error('process.exit called');
|
|
4149
|
+
}
|
|
4150
|
+
let _npmBinPath;
|
|
4151
|
+
function getNpmBinPath() {
|
|
4152
|
+
if (_npmBinPath === undefined) {
|
|
4153
|
+
_npmBinPath = getNpmBinPathDetails().path;
|
|
4154
|
+
if (!_npmBinPath) {
|
|
4155
|
+
exitWithBinPathError$1(constants.NPM);
|
|
4156
|
+
}
|
|
3571
4157
|
}
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
4158
|
+
return _npmBinPath;
|
|
4159
|
+
}
|
|
4160
|
+
let _npmBinPathDetails;
|
|
4161
|
+
function getNpmBinPathDetails() {
|
|
4162
|
+
if (_npmBinPathDetails === undefined) {
|
|
4163
|
+
_npmBinPathDetails = findBinPathDetailsSync(constants.NPM);
|
|
3578
4164
|
}
|
|
4165
|
+
return _npmBinPathDetails;
|
|
3579
4166
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
4167
|
+
let _npmDirPath;
|
|
4168
|
+
function getNpmDirPath() {
|
|
4169
|
+
if (_npmDirPath === undefined) {
|
|
4170
|
+
const npmBinPath = getNpmBinPath();
|
|
4171
|
+
_npmDirPath = npmBinPath ? findNpmDirPathSync(npmBinPath) : undefined;
|
|
4172
|
+
if (!_npmDirPath) {
|
|
4173
|
+
_npmDirPath = constants.default.ENV.SOCKET_CLI_NPM_PATH || undefined;
|
|
4174
|
+
}
|
|
4175
|
+
if (!_npmDirPath) {
|
|
4176
|
+
let message = 'Unable to find npm CLI install directory.';
|
|
4177
|
+
if (npmBinPath) {
|
|
4178
|
+
message += `\nSearched parent directories of ${path.dirname(npmBinPath)}.`;
|
|
4179
|
+
}
|
|
4180
|
+
message += '\n\nThis is may be a bug with socket-npm related to changes to the npm CLI.';
|
|
4181
|
+
message += `\nPlease report to ${constants.default.SOCKET_CLI_ISSUES_URL}.`;
|
|
4182
|
+
logger.logger.fail(message);
|
|
4183
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
4184
|
+
// could not be found.
|
|
4185
|
+
// eslint-disable-next-line n/no-process-exit
|
|
4186
|
+
process.exit(127);
|
|
4187
|
+
// This line is never reached in production, but helps tests.
|
|
4188
|
+
throw new Error('process.exit called');
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
return _npmDirPath;
|
|
3585
4192
|
}
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
if (
|
|
3589
|
-
|
|
4193
|
+
let _npmRequire;
|
|
4194
|
+
function getNpmRequire() {
|
|
4195
|
+
if (_npmRequire === undefined) {
|
|
4196
|
+
const npmDirPath = getNpmDirPath();
|
|
4197
|
+
const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
|
|
4198
|
+
_npmRequire = require$$5.createRequire(path.join(fs$1.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
|
|
3590
4199
|
}
|
|
3591
|
-
|
|
3592
|
-
return Sentry.captureException(exception, hint);
|
|
4200
|
+
return _npmRequire;
|
|
3593
4201
|
}
|
|
3594
|
-
|
|
3595
|
-
function
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
4202
|
+
let _npxBinPath;
|
|
4203
|
+
function getNpxBinPath() {
|
|
4204
|
+
if (_npxBinPath === undefined) {
|
|
4205
|
+
_npxBinPath = getNpxBinPathDetails().path;
|
|
4206
|
+
if (!_npxBinPath) {
|
|
4207
|
+
exitWithBinPathError$1('npx');
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
return _npxBinPath;
|
|
4211
|
+
}
|
|
4212
|
+
let _npxBinPathDetails;
|
|
4213
|
+
function getNpxBinPathDetails() {
|
|
4214
|
+
if (_npxBinPathDetails === undefined) {
|
|
4215
|
+
_npxBinPathDetails = findBinPathDetailsSync('npx');
|
|
4216
|
+
}
|
|
4217
|
+
return _npxBinPathDetails;
|
|
4218
|
+
}
|
|
4219
|
+
function isNpmBinPathShadowed() {
|
|
4220
|
+
return getNpmBinPathDetails().shadowed;
|
|
4221
|
+
}
|
|
4222
|
+
function isNpxBinPathShadowed() {
|
|
4223
|
+
return getNpxBinPathDetails().shadowed;
|
|
3600
4224
|
}
|
|
3601
4225
|
|
|
3602
4226
|
function shadowNpmInstall(options) {
|
|
@@ -3662,6 +4286,24 @@ function shadowNpmInstall(options) {
|
|
|
3662
4286
|
return spawnPromise;
|
|
3663
4287
|
}
|
|
3664
4288
|
|
|
4289
|
+
/**
|
|
4290
|
+
* Package manager agent utilities for Socket CLI.
|
|
4291
|
+
* Manages package installation via different package managers.
|
|
4292
|
+
*
|
|
4293
|
+
* Key Functions:
|
|
4294
|
+
* - runAgentInstall: Execute package installation with detected agent
|
|
4295
|
+
*
|
|
4296
|
+
* Supported Agents:
|
|
4297
|
+
* - npm: Node Package Manager
|
|
4298
|
+
* - pnpm: Fast, disk space efficient package manager
|
|
4299
|
+
* - yarn: Alternative package manager
|
|
4300
|
+
*
|
|
4301
|
+
* Features:
|
|
4302
|
+
* - Automatic agent detection
|
|
4303
|
+
* - Shadow installation for security scanning
|
|
4304
|
+
* - Spinner support for progress indication
|
|
4305
|
+
*/
|
|
4306
|
+
|
|
3665
4307
|
function runAgentInstall(pkgEnvDetails, options) {
|
|
3666
4308
|
const {
|
|
3667
4309
|
agent,
|
|
@@ -3693,6 +4335,9 @@ function runAgentInstall(pkgEnvDetails, options) {
|
|
|
3693
4335
|
const installArgs = isPnpm && isCi ? ['install', '--no-frozen-lockfile', ...args] : ['install', ...args];
|
|
3694
4336
|
return spawn.spawn(agentExecPath, installArgs, {
|
|
3695
4337
|
cwd: pkgPath,
|
|
4338
|
+
// On Windows, package managers are often .cmd files that require shell execution.
|
|
4339
|
+
// The spawn function from @socketsecurity/registry will handle this properly
|
|
4340
|
+
// when shell is true.
|
|
3696
4341
|
shell: constants.default.WIN32,
|
|
3697
4342
|
spinner,
|
|
3698
4343
|
stdio: 'inherit',
|
|
@@ -3706,6 +4351,32 @@ function runAgentInstall(pkgEnvDetails, options) {
|
|
|
3706
4351
|
});
|
|
3707
4352
|
}
|
|
3708
4353
|
|
|
4354
|
+
/**
|
|
4355
|
+
* Package environment detection utilities for Socket CLI.
|
|
4356
|
+
* Analyzes project environment and package manager configuration.
|
|
4357
|
+
*
|
|
4358
|
+
* Key Functions:
|
|
4359
|
+
* - getPackageEnvironment: Detect package manager and project details
|
|
4360
|
+
* - makeConcurrentExecLimit: Calculate concurrent execution limits
|
|
4361
|
+
*
|
|
4362
|
+
* Environment Detection:
|
|
4363
|
+
* - Detects npm, pnpm, yarn, bun package managers
|
|
4364
|
+
* - Analyzes lockfiles for version information
|
|
4365
|
+
* - Determines Node.js and engine requirements
|
|
4366
|
+
* - Identifies workspace configurations
|
|
4367
|
+
*
|
|
4368
|
+
* Features:
|
|
4369
|
+
* - Browser target detection via browserslist
|
|
4370
|
+
* - Engine compatibility checking
|
|
4371
|
+
* - Package manager version detection
|
|
4372
|
+
* - Workspace and monorepo support
|
|
4373
|
+
*
|
|
4374
|
+
* Usage:
|
|
4375
|
+
* - Auto-detecting appropriate package manager
|
|
4376
|
+
* - Validating environment compatibility
|
|
4377
|
+
* - Configuring concurrent execution limits
|
|
4378
|
+
*/
|
|
4379
|
+
|
|
3709
4380
|
const {
|
|
3710
4381
|
BUN,
|
|
3711
4382
|
BUN_LOCK,
|
|
@@ -3755,6 +4426,9 @@ const readLockFileByAgent = (() => {
|
|
|
3755
4426
|
// https://bun.sh/guides/install/yarnlock
|
|
3756
4427
|
return (await spawn.spawn(agentExecPath, [lockPath], {
|
|
3757
4428
|
cwd,
|
|
4429
|
+
// On Windows, bun is often a .cmd file that requires shell execution.
|
|
4430
|
+
// The spawn function from @socketsecurity/registry will handle this properly
|
|
4431
|
+
// when shell is true.
|
|
3758
4432
|
shell: constants.default.WIN32
|
|
3759
4433
|
})).stdout;
|
|
3760
4434
|
}
|
|
@@ -3775,7 +4449,7 @@ const LOCKS = {
|
|
|
3775
4449
|
[constants.PNPM_LOCK_YAML]: PNPM,
|
|
3776
4450
|
[constants.YARN_LOCK]: YARN_CLASSIC,
|
|
3777
4451
|
[VLT_LOCK_JSON]: VLT,
|
|
3778
|
-
// Lastly, look for a hidden
|
|
4452
|
+
// Lastly, look for a hidden lockfile which is present if .npmrc has package-lock=false:
|
|
3779
4453
|
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
|
|
3780
4454
|
//
|
|
3781
4455
|
// Unlike the other LOCKS keys this key contains a directory AND filename so
|
|
@@ -3830,13 +4504,17 @@ async function getAgentVersion(agent, agentExecPath, cwd) {
|
|
|
3830
4504
|
// All package managers support the "--version" flag.
|
|
3831
4505
|
(await spawn.spawn(agentExecPath, [constants.FLAG_VERSION], {
|
|
3832
4506
|
cwd,
|
|
4507
|
+
// On Windows, package managers are often .cmd files that require shell execution.
|
|
4508
|
+
// The spawn function from @socketsecurity/registry will handle this properly
|
|
4509
|
+
// when shell is true.
|
|
3833
4510
|
shell: constants.default.WIN32
|
|
3834
4511
|
})).stdout) ?? undefined;
|
|
3835
4512
|
} catch (e) {
|
|
3836
|
-
require$$9.debugFn('error', `
|
|
4513
|
+
require$$9.debugFn('error', `Package manager command failed: ${quotedCmd}`);
|
|
3837
4514
|
require$$9.debugDir('inspect', {
|
|
3838
|
-
|
|
4515
|
+
cmd: quotedCmd
|
|
3839
4516
|
});
|
|
4517
|
+
require$$9.debugDir('error', e);
|
|
3840
4518
|
}
|
|
3841
4519
|
return result;
|
|
3842
4520
|
}
|
|
@@ -4026,7 +4704,7 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
|
4026
4704
|
cause: cmdPrefixMessage(cmdName, `Package engine "node" requires ${pkgRequirements.node}. Current version: ${nodeVersion}`)
|
|
4027
4705
|
};
|
|
4028
4706
|
}
|
|
4029
|
-
const lockName = details.lockName ?? '
|
|
4707
|
+
const lockName = details.lockName ?? 'lockfile';
|
|
4030
4708
|
if (details.lockName === undefined || details.lockSrc === undefined) {
|
|
4031
4709
|
return {
|
|
4032
4710
|
ok: false,
|
|
@@ -4065,39 +4743,47 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
|
4065
4743
|
};
|
|
4066
4744
|
}
|
|
4067
4745
|
|
|
4746
|
+
/**
|
|
4747
|
+
* Ecosystem type utilities for Socket CLI.
|
|
4748
|
+
* Manages package ecosystem identifiers and mappings.
|
|
4749
|
+
*
|
|
4750
|
+
* Constants:
|
|
4751
|
+
* - ALL_ECOSYSTEMS: Complete list of supported ecosystems
|
|
4752
|
+
* - ECOSYSTEM_MAP: Map ecosystem strings to PURL types
|
|
4753
|
+
*
|
|
4754
|
+
* Type Definitions:
|
|
4755
|
+
* - PURL_Type: Package URL type from Socket SDK
|
|
4756
|
+
*
|
|
4757
|
+
* Supported Ecosystems:
|
|
4758
|
+
* - apk, bitbucket, cargo, chrome, cocoapods, composer
|
|
4759
|
+
* - conan, conda, cran, deb, docker, gem, generic
|
|
4760
|
+
* - github, gitlab, go, hackage, hex, huggingface
|
|
4761
|
+
* - maven, mlflow, npm, nuget, oci, pub, pypi, rpm, swift
|
|
4762
|
+
*
|
|
4763
|
+
* Usage:
|
|
4764
|
+
* - Validates ecosystem types
|
|
4765
|
+
* - Maps between different ecosystem representations
|
|
4766
|
+
* - Ensures type safety for ecosystem operations
|
|
4767
|
+
*/
|
|
4768
|
+
|
|
4068
4769
|
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
4770
|
new Set(ALL_ECOSYSTEMS);
|
|
4070
4771
|
function getEcosystemChoicesForMeow() {
|
|
4071
4772
|
return [...ALL_ECOSYSTEMS];
|
|
4072
4773
|
}
|
|
4073
4774
|
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
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
|
-
}
|
|
4775
|
+
/**
|
|
4776
|
+
* Filter configuration utilities for Socket CLI.
|
|
4777
|
+
* Manages filter configuration normalization for security scanning.
|
|
4778
|
+
*
|
|
4779
|
+
* Key Functions:
|
|
4780
|
+
* - toFilterConfig: Normalize filter configuration objects
|
|
4781
|
+
*
|
|
4782
|
+
* Usage:
|
|
4783
|
+
* - Normalizes user-provided filter objects
|
|
4784
|
+
* - Ensures proper structure for filter configuration
|
|
4785
|
+
* - Validates boolean and array values
|
|
4786
|
+
*/
|
|
4101
4787
|
|
|
4102
4788
|
function toFilterConfig(obj) {
|
|
4103
4789
|
const normalized = {
|
|
@@ -4197,6 +4883,30 @@ const ALERT_SEVERITY = createEnum({
|
|
|
4197
4883
|
low: 'low'
|
|
4198
4884
|
});
|
|
4199
4885
|
|
|
4886
|
+
/**
|
|
4887
|
+
* Color and markdown formatting utilities for Socket CLI.
|
|
4888
|
+
* Provides dual-mode formatting for terminal colors or markdown output.
|
|
4889
|
+
*
|
|
4890
|
+
* Key Class:
|
|
4891
|
+
* - ColorOrMarkdown: Dual-mode formatter for terminal/markdown output
|
|
4892
|
+
*
|
|
4893
|
+
* Formatting Methods:
|
|
4894
|
+
* - bold: Bold text formatting
|
|
4895
|
+
* - codeBlock: Code block formatting
|
|
4896
|
+
* - codeInline: Inline code formatting
|
|
4897
|
+
* - header: Section headers
|
|
4898
|
+
* - hyperlink: Clickable links
|
|
4899
|
+
* - indent: Text indentation
|
|
4900
|
+
* - italic: Italic text formatting
|
|
4901
|
+
* - list: Bullet list formatting
|
|
4902
|
+
* - table: Table formatting
|
|
4903
|
+
*
|
|
4904
|
+
* Usage:
|
|
4905
|
+
* - Switches between terminal colors and markdown based on output format
|
|
4906
|
+
* - Supports both interactive terminal and report generation
|
|
4907
|
+
* - Handles hyperlink fallbacks for terminals without link support
|
|
4908
|
+
*/
|
|
4909
|
+
|
|
4200
4910
|
class ColorOrMarkdown {
|
|
4201
4911
|
constructor(useMarkdown) {
|
|
4202
4912
|
this.useMarkdown = !!useMarkdown;
|
|
@@ -4242,6 +4952,28 @@ function getTranslations() {
|
|
|
4242
4952
|
return _translations;
|
|
4243
4953
|
}
|
|
4244
4954
|
|
|
4955
|
+
/**
|
|
4956
|
+
* Socket package alert utilities for Socket CLI.
|
|
4957
|
+
* Handles security alerts, vulnerabilities, and package risk assessment.
|
|
4958
|
+
*
|
|
4959
|
+
* Key Functions:
|
|
4960
|
+
* - addArtifactToAlertsMap: Add security alert to package map
|
|
4961
|
+
* - logAlertsMap: Display alerts in formatted output
|
|
4962
|
+
* - shouldSkipPackageAlert: Filter alerts based on criteria
|
|
4963
|
+
*
|
|
4964
|
+
* Alert Types:
|
|
4965
|
+
* - CVE: Common Vulnerabilities and Exposures
|
|
4966
|
+
* - GHSA: GitHub Security Advisories
|
|
4967
|
+
* - Package quality issues
|
|
4968
|
+
* - Supply chain risks
|
|
4969
|
+
*
|
|
4970
|
+
* Features:
|
|
4971
|
+
* - Alert severity classification (critical/high/medium/low)
|
|
4972
|
+
* - Fix type detection (major/minor/patch/none)
|
|
4973
|
+
* - Alert filtering and suppression
|
|
4974
|
+
* - Colorized terminal output
|
|
4975
|
+
*/
|
|
4976
|
+
|
|
4245
4977
|
const ALERT_SEVERITY_COLOR = createEnum({
|
|
4246
4978
|
critical: 'magenta',
|
|
4247
4979
|
high: 'red',
|
|
@@ -4586,6 +5318,26 @@ function logAlertsMap(alertsMap, options) {
|
|
|
4586
5318
|
output.write('\n');
|
|
4587
5319
|
}
|
|
4588
5320
|
|
|
5321
|
+
/**
|
|
5322
|
+
* Alerts map utilities for Socket CLI.
|
|
5323
|
+
* Manages security alerts and vulnerability mappings for packages.
|
|
5324
|
+
*
|
|
5325
|
+
* Key Functions:
|
|
5326
|
+
* - getAlertsMapFromPnpmLockfile: Extract alerts from pnpm lockfile
|
|
5327
|
+
* - getAlertsMapFromPurls: Get alerts for specific package URLs
|
|
5328
|
+
* - processAlertsApiResponse: Process API response into alerts map
|
|
5329
|
+
*
|
|
5330
|
+
* Alert Processing:
|
|
5331
|
+
* - Filters alerts based on socket.yml configuration
|
|
5332
|
+
* - Maps package URLs to security vulnerabilities
|
|
5333
|
+
* - Supports batch processing for performance
|
|
5334
|
+
*
|
|
5335
|
+
* Integration:
|
|
5336
|
+
* - Works with pnpm lockfiles for dependency scanning
|
|
5337
|
+
* - Uses Socket API for vulnerability data
|
|
5338
|
+
* - Respects filter configurations from socket.yml
|
|
5339
|
+
*/
|
|
5340
|
+
|
|
4589
5341
|
async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
4590
5342
|
const purls = await extractPurlsFromPnpmLockfile(lockfile);
|
|
4591
5343
|
return await getAlertsMapFromPurls(purls, {
|
|
@@ -4686,6 +5438,183 @@ async function getAlertsMapFromPurls(purls, options) {
|
|
|
4686
5438
|
return alertsByPurl;
|
|
4687
5439
|
}
|
|
4688
5440
|
|
|
5441
|
+
/**
|
|
5442
|
+
* npm package specification utilities for Socket CLI.
|
|
5443
|
+
* Parses and handles various npm package specification formats.
|
|
5444
|
+
*
|
|
5445
|
+
* Supported Formats:
|
|
5446
|
+
* - Regular packages: lodash, lodash@4.17.21
|
|
5447
|
+
* - Scoped packages: @types/node, @types/node@20.0.0
|
|
5448
|
+
* - Version ranges: lodash@^4.0.0, lodash@~4.17.0
|
|
5449
|
+
* - Git URLs: git+https://github.com/user/repo.git
|
|
5450
|
+
* - File paths: file:../local-package
|
|
5451
|
+
* - Aliases: my-alias@npm:real-package@1.0.0
|
|
5452
|
+
*
|
|
5453
|
+
* Key Functions:
|
|
5454
|
+
* - safeNpa: Safe wrapper for npm-package-arg
|
|
5455
|
+
* - safeNpmSpecToPurl: Convert npm spec to PURL
|
|
5456
|
+
* - safeParseNpmSpec: Parse npm spec to name/version
|
|
5457
|
+
*
|
|
5458
|
+
* Error Handling:
|
|
5459
|
+
* - Returns undefined for invalid specs
|
|
5460
|
+
* - Fallback parsing for edge cases
|
|
5461
|
+
* - Safe against malformed input
|
|
5462
|
+
*/
|
|
5463
|
+
|
|
5464
|
+
|
|
5465
|
+
// @ts-expect-error - Result is re-exported below.
|
|
5466
|
+
|
|
5467
|
+
/**
|
|
5468
|
+
* Safe wrapper for npm-package-arg that doesn't throw.
|
|
5469
|
+
* Returns undefined if parsing fails.
|
|
5470
|
+
*/
|
|
5471
|
+
function safeNpa(...args) {
|
|
5472
|
+
try {
|
|
5473
|
+
return Reflect.apply(vendor.npaExports, undefined, args);
|
|
5474
|
+
} catch {}
|
|
5475
|
+
return undefined;
|
|
5476
|
+
}
|
|
5477
|
+
|
|
5478
|
+
/**
|
|
5479
|
+
* Parse npm package specification into name and version.
|
|
5480
|
+
* Uses npm-package-arg for proper handling of various spec formats:
|
|
5481
|
+
* - Regular packages: lodash, lodash@4.17.21
|
|
5482
|
+
* - Scoped packages: @types/node, @types/node@20.0.0
|
|
5483
|
+
* - Version ranges: lodash@^4.0.0
|
|
5484
|
+
* - Git URLs, file paths, etc.
|
|
5485
|
+
*
|
|
5486
|
+
* Returns undefined if parsing fails.
|
|
5487
|
+
*/
|
|
5488
|
+
function safeParseNpmSpec(pkgSpec) {
|
|
5489
|
+
// Use npm-package-arg for proper spec parsing.
|
|
5490
|
+
const parsed = safeNpa(pkgSpec);
|
|
5491
|
+
if (!parsed) {
|
|
5492
|
+
// Fallback to simple parsing if npm-package-arg fails.
|
|
5493
|
+
// Handle scoped packages first to avoid confusion with version delimiter.
|
|
5494
|
+
if (pkgSpec.startsWith('@')) {
|
|
5495
|
+
const scopedMatch = pkgSpec.match(/^(@[^/@]+\/[^/@]+)(?:@(.+))?$/);
|
|
5496
|
+
if (scopedMatch) {
|
|
5497
|
+
return {
|
|
5498
|
+
name: scopedMatch[1],
|
|
5499
|
+
version: scopedMatch[2]
|
|
5500
|
+
};
|
|
5501
|
+
}
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
// Handle regular packages.
|
|
5505
|
+
const atIndex = pkgSpec.indexOf('@');
|
|
5506
|
+
if (atIndex === -1) {
|
|
5507
|
+
return {
|
|
5508
|
+
name: pkgSpec,
|
|
5509
|
+
version: undefined
|
|
5510
|
+
};
|
|
5511
|
+
}
|
|
5512
|
+
return {
|
|
5513
|
+
name: pkgSpec.slice(0, atIndex),
|
|
5514
|
+
version: pkgSpec.slice(atIndex + 1)
|
|
5515
|
+
};
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5518
|
+
// Extract name and version from parsed spec.
|
|
5519
|
+
const name = parsed.name || pkgSpec;
|
|
5520
|
+
let version;
|
|
5521
|
+
|
|
5522
|
+
// Handle different spec types from npm-package-arg.
|
|
5523
|
+
if (parsed.type === 'tag' || parsed.type === 'version' || parsed.type === 'range') {
|
|
5524
|
+
// For npm registry packages:
|
|
5525
|
+
// - type 'tag': latest, beta, etc.
|
|
5526
|
+
// - type 'version': exact version like 1.0.0
|
|
5527
|
+
// - type 'range': version range like ^1.0.0, ~1.0.0, or * for bare names
|
|
5528
|
+
// Don't include '*' as a version - it means "any version".
|
|
5529
|
+
if (parsed.fetchSpec && parsed.fetchSpec !== '*') {
|
|
5530
|
+
version = parsed.fetchSpec;
|
|
5531
|
+
} else if (parsed.rawSpec && parsed.rawSpec !== '*' && parsed.rawSpec !== parsed.name) {
|
|
5532
|
+
version = parsed.rawSpec;
|
|
5533
|
+
}
|
|
5534
|
+
} else if (parsed.type === 'git' || parsed.type === 'remote' || parsed.type === 'file') {
|
|
5535
|
+
// For non-registry specs, use rawSpec if different from name.
|
|
5536
|
+
if (parsed.rawSpec && parsed.rawSpec !== parsed.name) {
|
|
5537
|
+
version = parsed.rawSpec;
|
|
5538
|
+
}
|
|
5539
|
+
}
|
|
5540
|
+
return {
|
|
5541
|
+
name,
|
|
5542
|
+
version
|
|
5543
|
+
};
|
|
5544
|
+
}
|
|
5545
|
+
|
|
5546
|
+
/**
|
|
5547
|
+
* Convert npm package spec to PURL string.
|
|
5548
|
+
* Handles various npm spec formats and converts them to standardized PURLs.
|
|
5549
|
+
* Returns undefined if conversion fails.
|
|
5550
|
+
*/
|
|
5551
|
+
function safeNpmSpecToPurl(pkgSpec) {
|
|
5552
|
+
const parsed = safeParseNpmSpec(pkgSpec);
|
|
5553
|
+
if (!parsed) {
|
|
5554
|
+
return undefined;
|
|
5555
|
+
}
|
|
5556
|
+
const {
|
|
5557
|
+
name,
|
|
5558
|
+
version
|
|
5559
|
+
} = parsed;
|
|
5560
|
+
|
|
5561
|
+
// Create PURL object to ensure proper formatting.
|
|
5562
|
+
const purlObj = createPurlObject({
|
|
5563
|
+
type: constants.NPM,
|
|
5564
|
+
name,
|
|
5565
|
+
version,
|
|
5566
|
+
throws: false
|
|
5567
|
+
});
|
|
5568
|
+
return purlObj?.toString() ?? `pkg:${constants.NPM}/${name}${version ? `@${version}` : ''}`;
|
|
5569
|
+
}
|
|
5570
|
+
|
|
5571
|
+
/**
|
|
5572
|
+
* PNPM path resolution utilities for Socket CLI.
|
|
5573
|
+
* Locates and caches PNPM binary paths.
|
|
5574
|
+
*
|
|
5575
|
+
* Key Functions:
|
|
5576
|
+
* - getPnpmBinPath: Get cached PNPM binary path
|
|
5577
|
+
* - getPnpmBinPathDetails: Get detailed PNPM path information
|
|
5578
|
+
*
|
|
5579
|
+
* Error Handling:
|
|
5580
|
+
* - Exits with code 127 if PNPM not found
|
|
5581
|
+
* - Provides clear error messages for missing binaries
|
|
5582
|
+
*
|
|
5583
|
+
* Caching:
|
|
5584
|
+
* - Caches binary path lookups for performance
|
|
5585
|
+
* - Prevents repeated PATH searches
|
|
5586
|
+
*/
|
|
5587
|
+
|
|
5588
|
+
function exitWithBinPathError(binName) {
|
|
5589
|
+
logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
|
|
5590
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
5591
|
+
// could not be found.
|
|
5592
|
+
// eslint-disable-next-line n/no-process-exit
|
|
5593
|
+
process.exit(127);
|
|
5594
|
+
// This line is never reached in production, but helps tests.
|
|
5595
|
+
throw new Error('process.exit called');
|
|
5596
|
+
}
|
|
5597
|
+
let _pnpmBinPath;
|
|
5598
|
+
function getPnpmBinPath() {
|
|
5599
|
+
if (_pnpmBinPath === undefined) {
|
|
5600
|
+
_pnpmBinPath = getPnpmBinPathDetails().path;
|
|
5601
|
+
if (!_pnpmBinPath) {
|
|
5602
|
+
exitWithBinPathError('pnpm');
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
return _pnpmBinPath;
|
|
5606
|
+
}
|
|
5607
|
+
let _pnpmBinPathDetails;
|
|
5608
|
+
function getPnpmBinPathDetails() {
|
|
5609
|
+
if (_pnpmBinPathDetails === undefined) {
|
|
5610
|
+
_pnpmBinPathDetails = findBinPathDetailsSync('pnpm');
|
|
5611
|
+
}
|
|
5612
|
+
return _pnpmBinPathDetails;
|
|
5613
|
+
}
|
|
5614
|
+
function isPnpmBinPathShadowed() {
|
|
5615
|
+
return getPnpmBinPathDetails().shadowed;
|
|
5616
|
+
}
|
|
5617
|
+
|
|
4689
5618
|
exports.AuthError = AuthError;
|
|
4690
5619
|
exports.COMPLETION_CMD_PREFIX = COMPLETION_CMD_PREFIX;
|
|
4691
5620
|
exports.InputError = InputError;
|
|
@@ -4699,6 +5628,8 @@ exports.cmdPrefixMessage = cmdPrefixMessage;
|
|
|
4699
5628
|
exports.convertCveToGhsa = convertCveToGhsa;
|
|
4700
5629
|
exports.convertPurlToGhsas = convertPurlToGhsas;
|
|
4701
5630
|
exports.createEnum = createEnum;
|
|
5631
|
+
exports.debugFileOp = debugFileOp;
|
|
5632
|
+
exports.debugScan = debugScan;
|
|
4702
5633
|
exports.detectAndValidatePackageEnvironment = detectAndValidatePackageEnvironment;
|
|
4703
5634
|
exports.detectDefaultBranch = detectDefaultBranch;
|
|
4704
5635
|
exports.determineOrgSlug = determineOrgSlug;
|
|
@@ -4707,8 +5638,10 @@ exports.extractTier1ReachabilityScanId = extractTier1ReachabilityScanId;
|
|
|
4707
5638
|
exports.failMsgWithBadge = failMsgWithBadge;
|
|
4708
5639
|
exports.fetchGhsaDetails = fetchGhsaDetails;
|
|
4709
5640
|
exports.fetchOrganization = fetchOrganization;
|
|
5641
|
+
exports.fileLink = fileLink;
|
|
4710
5642
|
exports.filterFlags = filterFlags;
|
|
4711
5643
|
exports.findUp = findUp;
|
|
5644
|
+
exports.formatErrorWithDetail = formatErrorWithDetail;
|
|
4712
5645
|
exports.getAlertsMapFromPnpmLockfile = getAlertsMapFromPnpmLockfile;
|
|
4713
5646
|
exports.getAlertsMapFromPurls = getAlertsMapFromPurls;
|
|
4714
5647
|
exports.getBaseBranch = getBaseBranch;
|
|
@@ -4718,6 +5651,7 @@ exports.getConfigValueOrUndef = getConfigValueOrUndef;
|
|
|
4718
5651
|
exports.getDefaultOrgSlug = getDefaultOrgSlug;
|
|
4719
5652
|
exports.getEcosystemChoicesForMeow = getEcosystemChoicesForMeow;
|
|
4720
5653
|
exports.getEnterpriseOrgs = getEnterpriseOrgs;
|
|
5654
|
+
exports.getErrorCause = getErrorCause;
|
|
4721
5655
|
exports.getFlagApiRequirementsOutput = getFlagApiRequirementsOutput;
|
|
4722
5656
|
exports.getFlagListOutput = getFlagListOutput;
|
|
4723
5657
|
exports.getMajor = getMajor;
|
|
@@ -4765,6 +5699,7 @@ exports.isSupportedConfigKey = isSupportedConfigKey;
|
|
|
4765
5699
|
exports.isYarnBerry = isYarnBerry;
|
|
4766
5700
|
exports.isYarnBinPathShadowed = isYarnBinPathShadowed;
|
|
4767
5701
|
exports.logAlertsMap = logAlertsMap;
|
|
5702
|
+
exports.mailtoLink = mailtoLink;
|
|
4768
5703
|
exports.mapToObject = mapToObject;
|
|
4769
5704
|
exports.mdTable = mdTable;
|
|
4770
5705
|
exports.mdTableOfPairs = mdTableOfPairs;
|
|
@@ -4773,7 +5708,6 @@ exports.meowOrExit = meowOrExit;
|
|
|
4773
5708
|
exports.meowWithSubcommands = meowWithSubcommands;
|
|
4774
5709
|
exports.msAtHome = msAtHome;
|
|
4775
5710
|
exports.normalizePurl = normalizePurl;
|
|
4776
|
-
exports.npa = npa;
|
|
4777
5711
|
exports.parsePnpmLockfile = parsePnpmLockfile;
|
|
4778
5712
|
exports.queryApiSafeJson = queryApiSafeJson;
|
|
4779
5713
|
exports.queryApiSafeText = queryApiSafeText;
|
|
@@ -4782,10 +5716,15 @@ exports.readOrDefaultSocketJsonUp = readOrDefaultSocketJsonUp;
|
|
|
4782
5716
|
exports.readPnpmLockfile = readPnpmLockfile;
|
|
4783
5717
|
exports.readSocketJsonSync = readSocketJsonSync;
|
|
4784
5718
|
exports.runAgentInstall = runAgentInstall;
|
|
5719
|
+
exports.safeNpa = safeNpa$1;
|
|
5720
|
+
exports.safeNpmSpecToPurl = safeNpmSpecToPurl;
|
|
4785
5721
|
exports.sendApiRequest = sendApiRequest;
|
|
4786
5722
|
exports.serializeResultJson = serializeResultJson;
|
|
4787
5723
|
exports.setGitRemoteGithubRepoUrl = setGitRemoteGithubRepoUrl;
|
|
4788
5724
|
exports.setupSdk = setupSdk;
|
|
5725
|
+
exports.socketDashboardLink = socketDashboardLink;
|
|
5726
|
+
exports.socketDocsLink = socketDocsLink;
|
|
5727
|
+
exports.socketPackageLink = socketPackageLink;
|
|
4789
5728
|
exports.spawnCdxgenDlx = spawnCdxgenDlx;
|
|
4790
5729
|
exports.spawnCoanaDlx = spawnCoanaDlx;
|
|
4791
5730
|
exports.spawnSynpDlx = spawnSynpDlx;
|
|
@@ -4794,6 +5733,7 @@ exports.tildify = tildify;
|
|
|
4794
5733
|
exports.toFilterConfig = toFilterConfig;
|
|
4795
5734
|
exports.updateConfigValue = updateConfigValue;
|
|
4796
5735
|
exports.walkNestedMap = walkNestedMap;
|
|
5736
|
+
exports.webLink = webLink;
|
|
4797
5737
|
exports.writeSocketJson = writeSocketJson;
|
|
4798
|
-
//# debugId=
|
|
5738
|
+
//# debugId=ea20d1df-782c-49c5-bbda-ab4eac27ce58
|
|
4799
5739
|
//# sourceMappingURL=utils.js.map
|