@socketsecurity/cli-with-sentry 1.1.17 → 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -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 +238 -94
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +5 -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 +319 -0
- package/dist/shadow-pnpm-bin2.js.map +1 -0
- package/dist/shadow-yarn-bin.js +58 -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/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/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/repository/cmd-repository-list.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-diff.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/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/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/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/utils.js +1303 -457
- package/dist/utils.js.map +1 -1
- package/dist/vendor.js +317 -316
- package/package.json +4 -4
- 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({
|
|
@@ -965,6 +1278,24 @@ function checkCommandInput(outputKind, ...checks) {
|
|
|
965
1278
|
return false;
|
|
966
1279
|
}
|
|
967
1280
|
|
|
1281
|
+
/**
|
|
1282
|
+
* Output format detection utilities for Socket CLI.
|
|
1283
|
+
* Determines output format based on command flags.
|
|
1284
|
+
*
|
|
1285
|
+
* Key Functions:
|
|
1286
|
+
* - getOutputKind: Determine output format from flags
|
|
1287
|
+
*
|
|
1288
|
+
* Supported Formats:
|
|
1289
|
+
* - JSON: Machine-readable JSON output
|
|
1290
|
+
* - Markdown: Formatted markdown for reports
|
|
1291
|
+
* - Text: Plain text for terminal display
|
|
1292
|
+
*
|
|
1293
|
+
* Usage:
|
|
1294
|
+
* - Processes --json and --markdown flags
|
|
1295
|
+
* - Returns appropriate output format constant
|
|
1296
|
+
* - Defaults to text format for terminal display
|
|
1297
|
+
*/
|
|
1298
|
+
|
|
968
1299
|
function getOutputKind(json, markdown) {
|
|
969
1300
|
if (json) {
|
|
970
1301
|
return constants.OUTPUT_JSON;
|
|
@@ -975,10 +1306,44 @@ function getOutputKind(json, markdown) {
|
|
|
975
1306
|
return constants.OUTPUT_TEXT;
|
|
976
1307
|
}
|
|
977
1308
|
|
|
1309
|
+
/**
|
|
1310
|
+
* String manipulation utilities for Socket CLI.
|
|
1311
|
+
* Provides common string transformations and formatting.
|
|
1312
|
+
*
|
|
1313
|
+
* Key Functions:
|
|
1314
|
+
* - camelToKebab: Convert camelCase to kebab-case
|
|
1315
|
+
*
|
|
1316
|
+
* Usage:
|
|
1317
|
+
* - Command name transformations
|
|
1318
|
+
* - Flag name conversions
|
|
1319
|
+
* - Consistent string formatting
|
|
1320
|
+
*/
|
|
1321
|
+
|
|
978
1322
|
function camelToKebab(str) {
|
|
979
1323
|
return str === '' ? '' : str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
980
1324
|
}
|
|
981
1325
|
|
|
1326
|
+
/**
|
|
1327
|
+
* Output formatting utilities for Socket CLI.
|
|
1328
|
+
* Provides consistent formatting for help text and command output.
|
|
1329
|
+
*
|
|
1330
|
+
* Key Functions:
|
|
1331
|
+
* - getFlagApiRequirementsOutput: Format API requirements for flags
|
|
1332
|
+
* - getHelpListOutput: Format help text lists with descriptions
|
|
1333
|
+
* - getFlagsHelpOutput: Generate formatted help for command flags
|
|
1334
|
+
*
|
|
1335
|
+
* Formatting Features:
|
|
1336
|
+
* - Automatic indentation and alignment
|
|
1337
|
+
* - Flag description formatting
|
|
1338
|
+
* - Requirements and permissions display
|
|
1339
|
+
* - Hidden flag filtering
|
|
1340
|
+
*
|
|
1341
|
+
* Usage:
|
|
1342
|
+
* - Used by command help systems
|
|
1343
|
+
* - Provides consistent terminal output formatting
|
|
1344
|
+
* - Handles kebab-case conversion for flags
|
|
1345
|
+
*/
|
|
1346
|
+
|
|
982
1347
|
function getFlagApiRequirementsOutput(cmdPath, options) {
|
|
983
1348
|
const {
|
|
984
1349
|
indent = 6
|
|
@@ -1049,8 +1414,19 @@ function getHelpListOutput(list, options) {
|
|
|
1049
1414
|
return result.trim() || '(none)';
|
|
1050
1415
|
}
|
|
1051
1416
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1417
|
+
/**
|
|
1418
|
+
* Path tildification utilities for Socket CLI.
|
|
1419
|
+
* Abbreviates home directory paths with tilde notation.
|
|
1420
|
+
*
|
|
1421
|
+
* Key Functions:
|
|
1422
|
+
* - tildify: Replace home directory with ~ in paths
|
|
1423
|
+
*
|
|
1424
|
+
* Usage:
|
|
1425
|
+
* - Shortens absolute paths for display
|
|
1426
|
+
* - Converts /Users/name/... to ~/...
|
|
1427
|
+
* - Common Unix convention for home directory
|
|
1428
|
+
*/
|
|
1429
|
+
|
|
1054
1430
|
function tildify(cwd) {
|
|
1055
1431
|
return cwd.replace(new RegExp(`^${regexps.escapeRegExp(constants.default.homePath)}(?:${path.sep}|$)`, 'i'), '~/');
|
|
1056
1432
|
}
|
|
@@ -1269,10 +1645,15 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1269
1645
|
// We want to detect whether a bool flag is given at all.
|
|
1270
1646
|
booleanDefault: undefined
|
|
1271
1647
|
});
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1648
|
+
const {
|
|
1649
|
+
config: configFlag,
|
|
1650
|
+
org: orgFlag,
|
|
1651
|
+
spinner: spinnerFlag
|
|
1652
|
+
} = cli1.flags;
|
|
1653
|
+
const noSpinner = spinnerFlag === false || require$$9.isDebug();
|
|
1274
1654
|
|
|
1275
|
-
// Use CI spinner style when --no-spinner is passed.
|
|
1655
|
+
// Use CI spinner style when --no-spinner is passed or debug mode is enabled.
|
|
1656
|
+
// This prevents the spinner from interfering with debug output.
|
|
1276
1657
|
if (noSpinner) {
|
|
1277
1658
|
constants.default.spinner.spinner = spinner.getCliSpinners('ci');
|
|
1278
1659
|
}
|
|
@@ -1282,8 +1663,8 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1282
1663
|
let configOverrideResult;
|
|
1283
1664
|
if (constants.default.ENV.SOCKET_CLI_CONFIG) {
|
|
1284
1665
|
configOverrideResult = overrideCachedConfig(constants.default.ENV.SOCKET_CLI_CONFIG);
|
|
1285
|
-
} else if (
|
|
1286
|
-
configOverrideResult = overrideCachedConfig(
|
|
1666
|
+
} else if (configFlag) {
|
|
1667
|
+
configOverrideResult = overrideCachedConfig(configFlag);
|
|
1287
1668
|
}
|
|
1288
1669
|
if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
1289
1670
|
// This overrides the config override and even the explicit token env var.
|
|
@@ -1479,9 +1860,10 @@ function meowOrExit({
|
|
|
1479
1860
|
spinner: spinnerFlag,
|
|
1480
1861
|
version: versionFlag
|
|
1481
1862
|
} = cli.flags;
|
|
1482
|
-
const noSpinner = spinnerFlag === false;
|
|
1863
|
+
const noSpinner = spinnerFlag === false || require$$9.isDebug();
|
|
1483
1864
|
|
|
1484
1865
|
// Use CI spinner style when --no-spinner is passed.
|
|
1866
|
+
// This prevents the spinner from interfering with debug output.
|
|
1485
1867
|
if (noSpinner) {
|
|
1486
1868
|
constants.default.spinner.spinner = spinner.getCliSpinners('ci');
|
|
1487
1869
|
}
|
|
@@ -1520,6 +1902,8 @@ function meowOrExit({
|
|
|
1520
1902
|
console.error('Unknown flag\n--version');
|
|
1521
1903
|
// eslint-disable-next-line n/no-process-exit
|
|
1522
1904
|
process.exit(2);
|
|
1905
|
+
// This line is never reached in production, but helps tests.
|
|
1906
|
+
throw new Error('process.exit called');
|
|
1523
1907
|
}
|
|
1524
1908
|
|
|
1525
1909
|
// Now test for help state. Run Meow again. If it exits now, it must be due
|
|
@@ -1753,6 +2137,33 @@ async function getDefaultOrgSlug() {
|
|
|
1753
2137
|
};
|
|
1754
2138
|
}
|
|
1755
2139
|
|
|
2140
|
+
/**
|
|
2141
|
+
* Git utilities for Socket CLI.
|
|
2142
|
+
* Provides git operations for repository management, branch handling, and commits.
|
|
2143
|
+
*
|
|
2144
|
+
* Branch Operations:
|
|
2145
|
+
* - gitCheckoutBranch: Switch to branch
|
|
2146
|
+
* - gitCreateBranch: Create new local branch
|
|
2147
|
+
* - gitDeleteBranch: Delete local branch
|
|
2148
|
+
* - gitDeleteRemoteBranch: Delete remote branch
|
|
2149
|
+
* - gitPushBranch: Push branch to remote with --force
|
|
2150
|
+
*
|
|
2151
|
+
* Commit Operations:
|
|
2152
|
+
* - gitCleanFdx: Remove untracked files
|
|
2153
|
+
* - gitCommit: Stage files and create commit
|
|
2154
|
+
* - gitEnsureIdentity: Configure git user.name/email
|
|
2155
|
+
* - gitResetHard: Reset to branch/commit
|
|
2156
|
+
*
|
|
2157
|
+
* Remote URL Parsing:
|
|
2158
|
+
* - parseGitRemoteUrl: Extract owner/repo from SSH or HTTPS URLs
|
|
2159
|
+
*
|
|
2160
|
+
* Repository Information:
|
|
2161
|
+
* - detectDefaultBranch: Find default branch (main/master/develop/etc)
|
|
2162
|
+
* - getBaseBranch: Determine base branch (respects GitHub Actions env)
|
|
2163
|
+
* - getRepoInfo: Extract owner/repo from git remote URL
|
|
2164
|
+
* - gitBranch: Get current branch or commit hash
|
|
2165
|
+
*/
|
|
2166
|
+
|
|
1756
2167
|
// Listed in order of check preference.
|
|
1757
2168
|
const COMMON_DEFAULT_BRANCH_NAMES = [
|
|
1758
2169
|
// Modern default (GitHub, GitLab, Bitbucket have switched to this).
|
|
@@ -1796,22 +2207,21 @@ async function getBaseBranch(cwd = process.cwd()) {
|
|
|
1796
2207
|
}
|
|
1797
2208
|
async function getRepoInfo(cwd = process.cwd()) {
|
|
1798
2209
|
let info;
|
|
1799
|
-
const quotedCmd = '`git remote get-url origin`';
|
|
1800
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1801
2210
|
try {
|
|
1802
2211
|
const remoteUrl = (await spawn.spawn('git', ['remote', 'get-url', 'origin'], {
|
|
1803
2212
|
cwd
|
|
1804
2213
|
})).stdout;
|
|
1805
2214
|
info = parseGitRemoteUrl(remoteUrl);
|
|
1806
2215
|
if (!info) {
|
|
1807
|
-
require$$9.debugFn('
|
|
1808
|
-
require$$9.debugDir('
|
|
2216
|
+
require$$9.debugFn('warn', `Unmatched git remote URL format: ${remoteUrl}`);
|
|
2217
|
+
require$$9.debugDir('warn', {
|
|
1809
2218
|
remoteUrl
|
|
1810
2219
|
});
|
|
1811
2220
|
}
|
|
1812
2221
|
} catch (e) {
|
|
1813
|
-
|
|
2222
|
+
// Expected failure when not in a git repo.
|
|
1814
2223
|
require$$9.debugDir('inspect', {
|
|
2224
|
+
message: 'git remote get-url failed',
|
|
1815
2225
|
error: e
|
|
1816
2226
|
});
|
|
1817
2227
|
}
|
|
@@ -1825,41 +2235,29 @@ async function gitBranch(cwd = process.cwd()) {
|
|
|
1825
2235
|
const stdioPipeOptions = {
|
|
1826
2236
|
cwd
|
|
1827
2237
|
};
|
|
1828
|
-
let quotedCmd = '`git symbolic-ref --short HEAD`';
|
|
1829
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1830
2238
|
// Try symbolic-ref first which returns the branch name or fails in a
|
|
1831
2239
|
// detached HEAD state.
|
|
1832
2240
|
try {
|
|
1833
2241
|
const gitSymbolicRefResult = await spawn.spawn('git', ['symbolic-ref', '--short', 'HEAD'], stdioPipeOptions);
|
|
1834
|
-
require$$9.debugDir('stdio', {
|
|
1835
|
-
gitSymbolicRefResult
|
|
1836
|
-
});
|
|
1837
2242
|
return gitSymbolicRefResult.stdout;
|
|
1838
2243
|
} catch (e) {
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
}
|
|
2244
|
+
// Expected in detached HEAD state, fallback to rev-parse.
|
|
2245
|
+
require$$9.debugDir('inspect', {
|
|
2246
|
+
message: 'In detached HEAD state',
|
|
2247
|
+
error: e
|
|
2248
|
+
});
|
|
1845
2249
|
}
|
|
1846
2250
|
// Fallback to using rev-parse to get the short commit hash in a
|
|
1847
2251
|
// detached HEAD state.
|
|
1848
|
-
quotedCmd = '`git rev-parse --short HEAD`';
|
|
1849
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1850
2252
|
try {
|
|
1851
2253
|
const gitRevParseResult = await spawn.spawn('git', ['rev-parse', '--short', 'HEAD'], stdioPipeOptions);
|
|
1852
|
-
require$$9.debugDir('stdio', {
|
|
1853
|
-
gitRevParseResult
|
|
1854
|
-
});
|
|
1855
2254
|
return gitRevParseResult.stdout;
|
|
1856
2255
|
} catch (e) {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
2256
|
+
// Both methods failed, likely not in a git repo.
|
|
2257
|
+
require$$9.debugDir('inspect', {
|
|
2258
|
+
message: 'Unable to determine git branch',
|
|
2259
|
+
error: e
|
|
2260
|
+
});
|
|
1863
2261
|
}
|
|
1864
2262
|
return undefined;
|
|
1865
2263
|
}
|
|
@@ -1890,14 +2288,12 @@ async function gitCleanFdx(cwd = process.cwd()) {
|
|
|
1890
2288
|
cwd,
|
|
1891
2289
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1892
2290
|
};
|
|
1893
|
-
const quotedCmd = '`git clean -fdx`';
|
|
1894
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1895
2291
|
try {
|
|
1896
2292
|
await spawn.spawn('git', ['clean', '-fdx'], stdioIgnoreOptions);
|
|
2293
|
+
debugGit('clean -fdx', true);
|
|
1897
2294
|
return true;
|
|
1898
2295
|
} catch (e) {
|
|
1899
|
-
|
|
1900
|
-
require$$9.debugDir('inspect', {
|
|
2296
|
+
debugGit('clean -fdx', false, {
|
|
1901
2297
|
error: e
|
|
1902
2298
|
});
|
|
1903
2299
|
}
|
|
@@ -1908,14 +2304,12 @@ async function gitCheckoutBranch(branch, cwd = process.cwd()) {
|
|
|
1908
2304
|
cwd,
|
|
1909
2305
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1910
2306
|
};
|
|
1911
|
-
const quotedCmd = `\`git checkout ${branch}\``;
|
|
1912
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1913
2307
|
try {
|
|
1914
2308
|
await spawn.spawn('git', ['checkout', branch], stdioIgnoreOptions);
|
|
2309
|
+
debugGit(`checkout ${branch}`, true);
|
|
1915
2310
|
return true;
|
|
1916
2311
|
} catch (e) {
|
|
1917
|
-
|
|
1918
|
-
require$$9.debugDir('inspect', {
|
|
2312
|
+
debugGit(`checkout ${branch}`, false, {
|
|
1919
2313
|
error: e
|
|
1920
2314
|
});
|
|
1921
2315
|
}
|
|
@@ -1929,14 +2323,12 @@ async function gitCreateBranch(branch, cwd = process.cwd()) {
|
|
|
1929
2323
|
cwd,
|
|
1930
2324
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1931
2325
|
};
|
|
1932
|
-
const quotedCmd = `\`git branch ${branch}\``;
|
|
1933
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1934
2326
|
try {
|
|
1935
2327
|
await spawn.spawn('git', ['branch', branch], stdioIgnoreOptions);
|
|
2328
|
+
debugGit(`branch ${branch}`, true);
|
|
1936
2329
|
return true;
|
|
1937
2330
|
} catch (e) {
|
|
1938
|
-
|
|
1939
|
-
require$$9.debugDir('inspect', {
|
|
2331
|
+
debugGit(`branch ${branch}`, false, {
|
|
1940
2332
|
error: e
|
|
1941
2333
|
});
|
|
1942
2334
|
}
|
|
@@ -1947,19 +2339,22 @@ async function gitPushBranch(branch, cwd = process.cwd()) {
|
|
|
1947
2339
|
cwd,
|
|
1948
2340
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1949
2341
|
};
|
|
1950
|
-
const quotedCmd = `\`git push --force --set-upstream origin ${branch}\``;
|
|
1951
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
1952
2342
|
try {
|
|
1953
2343
|
await spawn.spawn('git', ['push', '--force', '--set-upstream', 'origin', branch], stdioIgnoreOptions);
|
|
2344
|
+
debugGit(`push ${branch}`, true);
|
|
1954
2345
|
return true;
|
|
1955
2346
|
} catch (e) {
|
|
1956
|
-
require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
|
|
1957
2347
|
if (spawn.isSpawnError(e) && e.code === 128) {
|
|
1958
|
-
require$$9.debugFn('error', "denied: token requires write permissions for 'contents' and 'pull-requests'");
|
|
2348
|
+
require$$9.debugFn('error', "Push denied: token requires write permissions for 'contents' and 'pull-requests'");
|
|
2349
|
+
require$$9.debugDir('error', e);
|
|
2350
|
+
require$$9.debugDir('inspect', {
|
|
2351
|
+
branch
|
|
2352
|
+
});
|
|
2353
|
+
} else {
|
|
2354
|
+
debugGit(`push ${branch}`, false, {
|
|
2355
|
+
error: e
|
|
2356
|
+
});
|
|
1959
2357
|
}
|
|
1960
|
-
require$$9.debugDir('inspect', {
|
|
1961
|
-
error: e
|
|
1962
|
-
});
|
|
1963
2358
|
}
|
|
1964
2359
|
return false;
|
|
1965
2360
|
}
|
|
@@ -1981,26 +2376,31 @@ async function gitCommit(commitMsg, filepaths, options) {
|
|
|
1981
2376
|
cwd,
|
|
1982
2377
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
1983
2378
|
};
|
|
1984
|
-
const quotedAddCmd = `\`git add ${filepaths.join(' ')}\``;
|
|
1985
|
-
require$$9.debugFn('stdio', `spawn: ${quotedAddCmd}`);
|
|
1986
2379
|
try {
|
|
1987
2380
|
await spawn.spawn('git', ['add', ...filepaths], stdioIgnoreOptions);
|
|
2381
|
+
debugGit('add', true, {
|
|
2382
|
+
count: filepaths.length
|
|
2383
|
+
});
|
|
1988
2384
|
} catch (e) {
|
|
1989
|
-
|
|
1990
|
-
require$$9.debugDir('inspect', {
|
|
2385
|
+
debugGit('add', false, {
|
|
1991
2386
|
error: e
|
|
1992
2387
|
});
|
|
2388
|
+
require$$9.debugDir('inspect', {
|
|
2389
|
+
filepaths
|
|
2390
|
+
});
|
|
2391
|
+
return false;
|
|
1993
2392
|
}
|
|
1994
|
-
const quotedCommitCmd = `\`git commit -m ${commitMsg}\``;
|
|
1995
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCommitCmd}`);
|
|
1996
2393
|
try {
|
|
1997
2394
|
await spawn.spawn('git', ['commit', '-m', commitMsg], stdioIgnoreOptions);
|
|
2395
|
+
debugGit('commit', true);
|
|
1998
2396
|
return true;
|
|
1999
2397
|
} catch (e) {
|
|
2000
|
-
|
|
2001
|
-
require$$9.debugDir('inspect', {
|
|
2398
|
+
debugGit('commit', false, {
|
|
2002
2399
|
error: e
|
|
2003
2400
|
});
|
|
2401
|
+
require$$9.debugDir('inspect', {
|
|
2402
|
+
commitMsg
|
|
2403
|
+
});
|
|
2004
2404
|
}
|
|
2005
2405
|
return false;
|
|
2006
2406
|
}
|
|
@@ -2009,19 +2409,16 @@ async function gitDeleteBranch(branch, cwd = process.cwd()) {
|
|
|
2009
2409
|
cwd,
|
|
2010
2410
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2011
2411
|
};
|
|
2012
|
-
const quotedCmd = `\`git branch -D ${branch}\``;
|
|
2013
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2014
2412
|
try {
|
|
2015
2413
|
// Will throw with exit code 1 if branch does not exist.
|
|
2016
2414
|
await spawn.spawn('git', ['branch', '-D', branch], stdioIgnoreOptions);
|
|
2017
2415
|
return true;
|
|
2018
2416
|
} catch (e) {
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
}
|
|
2417
|
+
// Expected failure when branch doesn't exist.
|
|
2418
|
+
require$$9.debugDir('inspect', {
|
|
2419
|
+
message: `Branch deletion failed (may not exist): ${branch}`,
|
|
2420
|
+
error: e
|
|
2421
|
+
});
|
|
2025
2422
|
}
|
|
2026
2423
|
return false;
|
|
2027
2424
|
}
|
|
@@ -2035,41 +2432,30 @@ async function gitEnsureIdentity(name, email, cwd = process.cwd()) {
|
|
|
2035
2432
|
1: value
|
|
2036
2433
|
}) => {
|
|
2037
2434
|
let configValue;
|
|
2038
|
-
{
|
|
2039
|
-
|
|
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
|
-
}
|
|
2435
|
+
try {
|
|
2436
|
+
// Will throw with exit code 1 if the config property is not set.
|
|
2437
|
+
const gitConfigResult = await spawn.spawn('git', ['config', '--get', prop], stdioPipeOptions);
|
|
2438
|
+
configValue = gitConfigResult.stdout;
|
|
2439
|
+
} catch (e) {
|
|
2440
|
+
// Expected when config property is not set.
|
|
2441
|
+
require$$9.debugDir('inspect', {
|
|
2442
|
+
message: `Git config property not set: ${prop}`,
|
|
2443
|
+
error: e
|
|
2444
|
+
});
|
|
2056
2445
|
}
|
|
2057
2446
|
if (configValue !== value) {
|
|
2058
2447
|
const stdioIgnoreOptions = {
|
|
2059
2448
|
cwd,
|
|
2060
2449
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2061
2450
|
};
|
|
2062
|
-
const quotedCmd = `\`git config ${prop} ${value}\``;
|
|
2063
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2064
2451
|
try {
|
|
2065
2452
|
await spawn.spawn('git', ['config', prop, value], stdioIgnoreOptions);
|
|
2066
2453
|
} catch (e) {
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
}
|
|
2454
|
+
require$$9.debugFn('warn', `Failed to set git config: ${prop}`);
|
|
2455
|
+
require$$9.debugDir('warn', e);
|
|
2456
|
+
require$$9.debugDir('inspect', {
|
|
2457
|
+
value
|
|
2458
|
+
});
|
|
2073
2459
|
}
|
|
2074
2460
|
}
|
|
2075
2461
|
}));
|
|
@@ -2079,19 +2465,12 @@ async function gitLocalBranchExists(branch, cwd = process.cwd()) {
|
|
|
2079
2465
|
cwd,
|
|
2080
2466
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2081
2467
|
};
|
|
2082
|
-
const quotedCmd = `\`git show-ref --quiet refs/heads/${branch}\``;
|
|
2083
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2084
2468
|
try {
|
|
2085
2469
|
// Will throw with exit code 1 if the branch does not exist.
|
|
2086
2470
|
await spawn.spawn('git', ['show-ref', constants.FLAG_QUIET, `refs/heads/${branch}`], stdioIgnoreOptions);
|
|
2087
2471
|
return true;
|
|
2088
|
-
} catch
|
|
2089
|
-
|
|
2090
|
-
require$$9.debugFn('error', `caught: ${quotedCmd} failed`);
|
|
2091
|
-
require$$9.debugDir('inspect', {
|
|
2092
|
-
error: e
|
|
2093
|
-
});
|
|
2094
|
-
}
|
|
2472
|
+
} catch {
|
|
2473
|
+
// Expected when branch doesn't exist - no logging needed.
|
|
2095
2474
|
}
|
|
2096
2475
|
return false;
|
|
2097
2476
|
}
|
|
@@ -2099,21 +2478,15 @@ async function gitRemoteBranchExists(branch, cwd = process.cwd()) {
|
|
|
2099
2478
|
const stdioPipeOptions = {
|
|
2100
2479
|
cwd
|
|
2101
2480
|
};
|
|
2102
|
-
const quotedCmd = `\`git ls-remote --heads origin ${branch}\``;
|
|
2103
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2104
2481
|
try {
|
|
2105
2482
|
const lsRemoteResult = await spawn.spawn('git', ['ls-remote', '--heads', 'origin', branch], stdioPipeOptions);
|
|
2106
|
-
require$$9.debugDir('stdio', {
|
|
2107
|
-
lsRemoteResult
|
|
2108
|
-
});
|
|
2109
2483
|
return lsRemoteResult.stdout.length > 0;
|
|
2110
2484
|
} catch (e) {
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
}
|
|
2485
|
+
// Expected when remote is not accessible or branch doesn't exist.
|
|
2486
|
+
require$$9.debugDir('inspect', {
|
|
2487
|
+
message: `Remote branch check failed: ${branch}`,
|
|
2488
|
+
error: e
|
|
2489
|
+
});
|
|
2117
2490
|
}
|
|
2118
2491
|
return false;
|
|
2119
2492
|
}
|
|
@@ -2128,14 +2501,12 @@ async function gitResetHard(branch = 'HEAD', cwd = process.cwd()) {
|
|
|
2128
2501
|
cwd,
|
|
2129
2502
|
stdio: require$$9.isDebug('stdio') ? 'inherit' : 'ignore'
|
|
2130
2503
|
};
|
|
2131
|
-
const quotedCmd = `\`git reset --hard ${branch}\``;
|
|
2132
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2133
2504
|
try {
|
|
2134
2505
|
await spawn.spawn('git', ['reset', '--hard', branch], stdioIgnoreOptions);
|
|
2506
|
+
debugGit(`reset --hard ${branch}`, true);
|
|
2135
2507
|
return true;
|
|
2136
2508
|
} catch (e) {
|
|
2137
|
-
|
|
2138
|
-
require$$9.debugDir('inspect', {
|
|
2509
|
+
debugGit(`reset --hard ${branch}`, false, {
|
|
2139
2510
|
error: e
|
|
2140
2511
|
});
|
|
2141
2512
|
}
|
|
@@ -2145,13 +2516,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
|
|
|
2145
2516
|
const stdioPipeOptions = {
|
|
2146
2517
|
cwd
|
|
2147
2518
|
};
|
|
2148
|
-
const quotedCmd = `\`git diff --name-only\``;
|
|
2149
|
-
require$$9.debugFn('stdio', `spawn: ${quotedCmd}`);
|
|
2150
2519
|
try {
|
|
2151
2520
|
const gitDiffResult = await spawn.spawn('git', ['diff', '--name-only'], stdioPipeOptions);
|
|
2152
|
-
require$$9.debugDir('stdio', {
|
|
2153
|
-
gitDiffResult
|
|
2154
|
-
});
|
|
2155
2521
|
const changedFilesDetails = gitDiffResult.stdout;
|
|
2156
2522
|
const relPaths = changedFilesDetails.split('\n');
|
|
2157
2523
|
return {
|
|
@@ -2159,10 +2525,8 @@ async function gitUnstagedModifiedFiles(cwd = process.cwd()) {
|
|
|
2159
2525
|
data: relPaths.map(p => path$1.normalizePath(p))
|
|
2160
2526
|
};
|
|
2161
2527
|
} catch (e) {
|
|
2162
|
-
require$$9.debugFn('error',
|
|
2163
|
-
require$$9.debugDir('
|
|
2164
|
-
error: e
|
|
2165
|
-
});
|
|
2528
|
+
require$$9.debugFn('error', 'Failed to get unstaged modified files');
|
|
2529
|
+
require$$9.debugDir('error', e);
|
|
2166
2530
|
return {
|
|
2167
2531
|
ok: false,
|
|
2168
2532
|
message: 'Git Error',
|
|
@@ -2210,16 +2574,82 @@ function parseGitRemoteUrl(remoteUrl) {
|
|
|
2210
2574
|
} : result;
|
|
2211
2575
|
}
|
|
2212
2576
|
|
|
2213
|
-
|
|
2577
|
+
/**
|
|
2578
|
+
* Package URL (PURL) utilities for Socket CLI.
|
|
2579
|
+
* Implements the PURL specification for universal package identification.
|
|
2580
|
+
*
|
|
2581
|
+
* PURL Format:
|
|
2582
|
+
* pkg:type/namespace/name@version?qualifiers#subpath
|
|
2583
|
+
*
|
|
2584
|
+
* Key Functions:
|
|
2585
|
+
* - createPurlObject: Create PURL from components
|
|
2586
|
+
* - isPurl: Check if string is valid PURL
|
|
2587
|
+
* - normalizePurl: Normalize PURL format
|
|
2588
|
+
* - parsePurl: Parse PURL string to object
|
|
2589
|
+
* - purlToString: Convert PURL object to string
|
|
2590
|
+
*
|
|
2591
|
+
* Supported Types:
|
|
2592
|
+
* - cargo: Rust packages
|
|
2593
|
+
* - gem: Ruby packages
|
|
2594
|
+
* - go: Go modules
|
|
2595
|
+
* - maven: Java packages
|
|
2596
|
+
* - npm: Node.js packages
|
|
2597
|
+
* - pypi: Python packages
|
|
2598
|
+
*
|
|
2599
|
+
* See: https://github.com/package-url/purl-spec
|
|
2600
|
+
*/
|
|
2601
|
+
|
|
2602
|
+
function createPurlObject(type, name, options) {
|
|
2603
|
+
let opts;
|
|
2604
|
+
if (require$$11.isObjectObject(type)) {
|
|
2605
|
+
opts = {
|
|
2606
|
+
__proto__: null,
|
|
2607
|
+
...type
|
|
2608
|
+
};
|
|
2609
|
+
type = opts.type;
|
|
2610
|
+
name = opts.name;
|
|
2611
|
+
} else if (require$$11.isObjectObject(name)) {
|
|
2612
|
+
opts = {
|
|
2613
|
+
__proto__: null,
|
|
2614
|
+
...name
|
|
2615
|
+
};
|
|
2616
|
+
name = opts.name;
|
|
2617
|
+
} else {
|
|
2618
|
+
opts = {
|
|
2619
|
+
__proto__: null,
|
|
2620
|
+
...options
|
|
2621
|
+
};
|
|
2622
|
+
if (typeof name !== 'string') {
|
|
2623
|
+
name = opts.name;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2214
2626
|
const {
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2627
|
+
namespace,
|
|
2628
|
+
qualifiers,
|
|
2629
|
+
subpath,
|
|
2630
|
+
throws,
|
|
2631
|
+
version
|
|
2632
|
+
} = opts;
|
|
2220
2633
|
const shouldThrow = throws === undefined || !!throws;
|
|
2221
2634
|
try {
|
|
2222
|
-
return
|
|
2635
|
+
return new vendor.packageurlJsExports.PackageURL(type, namespace, name, version, qualifiers, subpath);
|
|
2636
|
+
} catch (e) {
|
|
2637
|
+
if (shouldThrow) {
|
|
2638
|
+
throw e;
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
return undefined;
|
|
2642
|
+
}
|
|
2643
|
+
function getPurlObject(purl, options) {
|
|
2644
|
+
const {
|
|
2645
|
+
throws
|
|
2646
|
+
} = {
|
|
2647
|
+
__proto__: null,
|
|
2648
|
+
...options
|
|
2649
|
+
};
|
|
2650
|
+
const shouldThrow = throws === undefined || !!throws;
|
|
2651
|
+
try {
|
|
2652
|
+
return typeof purl === 'string' ? vendor.packageurlJsExports.PackageURL.fromString(normalizePurl(purl)) : purl;
|
|
2223
2653
|
} catch (e) {
|
|
2224
2654
|
if (shouldThrow) {
|
|
2225
2655
|
throw e;
|
|
@@ -2231,6 +2661,26 @@ function normalizePurl(rawPurl) {
|
|
|
2231
2661
|
return rawPurl.startsWith('pkg:') ? rawPurl : `pkg:${rawPurl}`;
|
|
2232
2662
|
}
|
|
2233
2663
|
|
|
2664
|
+
/**
|
|
2665
|
+
* Socket.dev URL utilities for Socket CLI.
|
|
2666
|
+
* Generates URLs for Socket.dev website features and resources.
|
|
2667
|
+
*
|
|
2668
|
+
* Key Functions:
|
|
2669
|
+
* - getPkgFullNameFromPurl: Extract full package name from PURL
|
|
2670
|
+
* - getSocketDevAlertUrl: Generate alert type documentation URL
|
|
2671
|
+
* - getSocketDevPackageOverviewUrl: Generate package overview URL
|
|
2672
|
+
* - getSocketDevPackageOverviewUrlFromPurl: Generate overview URL from PURL
|
|
2673
|
+
* - getSocketDevPackageUrl: Generate package detail URL
|
|
2674
|
+
* - getSocketDevPackageUrlFromPurl: Generate package URL from PURL
|
|
2675
|
+
* - getSocketDevReportUrl: Generate scan report URL
|
|
2676
|
+
*
|
|
2677
|
+
* URL Generation:
|
|
2678
|
+
* - Package overview and detail pages
|
|
2679
|
+
* - Security alert documentation
|
|
2680
|
+
* - Scan report links
|
|
2681
|
+
* - Ecosystem-specific URL formatting
|
|
2682
|
+
*/
|
|
2683
|
+
|
|
2234
2684
|
function getPkgFullNameFromPurl(purl) {
|
|
2235
2685
|
const purlObj = getPurlObject(purl);
|
|
2236
2686
|
const {
|
|
@@ -2273,6 +2723,19 @@ function* walkNestedMap(map, keys = []) {
|
|
|
2273
2723
|
}
|
|
2274
2724
|
}
|
|
2275
2725
|
|
|
2726
|
+
/**
|
|
2727
|
+
* Coana integration utilities for Socket CLI.
|
|
2728
|
+
* Manages reachability analysis via Coana tech CLI.
|
|
2729
|
+
*
|
|
2730
|
+
* Key Functions:
|
|
2731
|
+
* - extractTier1ReachabilityScanId: Extract scan ID from socket facts file
|
|
2732
|
+
*
|
|
2733
|
+
* Integration:
|
|
2734
|
+
* - Works with @coana-tech/cli for reachability analysis
|
|
2735
|
+
* - Processes socket facts JSON files
|
|
2736
|
+
* - Extracts tier 1 reachability scan identifiers
|
|
2737
|
+
*/
|
|
2738
|
+
|
|
2276
2739
|
function extractTier1ReachabilityScanId(socketFactsFile) {
|
|
2277
2740
|
const json = fs.readJsonSync(socketFactsFile, {
|
|
2278
2741
|
throws: false
|
|
@@ -2281,6 +2744,25 @@ function extractTier1ReachabilityScanId(socketFactsFile) {
|
|
|
2281
2744
|
return tier1ReachabilityScanId.length > 0 ? tier1ReachabilityScanId : undefined;
|
|
2282
2745
|
}
|
|
2283
2746
|
|
|
2747
|
+
/**
|
|
2748
|
+
* File system utilities for Socket CLI.
|
|
2749
|
+
* Provides file and directory search functionality.
|
|
2750
|
+
*
|
|
2751
|
+
* Key Functions:
|
|
2752
|
+
* - findUp: Search for files/directories up the directory tree
|
|
2753
|
+
*
|
|
2754
|
+
* Features:
|
|
2755
|
+
* - Upward directory traversal
|
|
2756
|
+
* - Supports file and directory searching
|
|
2757
|
+
* - Abort signal support for cancellation
|
|
2758
|
+
* - Multiple name search support
|
|
2759
|
+
*
|
|
2760
|
+
* Usage:
|
|
2761
|
+
* - Finding configuration files (package.json, lockfiles)
|
|
2762
|
+
* - Locating project root directories
|
|
2763
|
+
* - Searching for specific files in parent directories
|
|
2764
|
+
*/
|
|
2765
|
+
|
|
2284
2766
|
async function findUp(name, options) {
|
|
2285
2767
|
const opts = {
|
|
2286
2768
|
__proto__: null,
|
|
@@ -2622,13 +3104,15 @@ function exitWithBinPathError$2(binName) {
|
|
|
2622
3104
|
// could not be found.
|
|
2623
3105
|
// eslint-disable-next-line n/no-process-exit
|
|
2624
3106
|
process.exit(127);
|
|
3107
|
+
// This line is never reached in production, but helps tests.
|
|
3108
|
+
throw new Error('process.exit called');
|
|
2625
3109
|
}
|
|
2626
3110
|
let _yarnBinPath;
|
|
2627
3111
|
function getYarnBinPath() {
|
|
2628
3112
|
if (_yarnBinPath === undefined) {
|
|
2629
3113
|
_yarnBinPath = getYarnBinPathDetails().path;
|
|
2630
3114
|
if (!_yarnBinPath) {
|
|
2631
|
-
exitWithBinPathError$2(constants.
|
|
3115
|
+
exitWithBinPathError$2(constants.YARN);
|
|
2632
3116
|
}
|
|
2633
3117
|
}
|
|
2634
3118
|
return _yarnBinPath;
|
|
@@ -2636,7 +3120,7 @@ function getYarnBinPath() {
|
|
|
2636
3120
|
let _yarnBinPathDetails;
|
|
2637
3121
|
function getYarnBinPathDetails() {
|
|
2638
3122
|
if (_yarnBinPathDetails === undefined) {
|
|
2639
|
-
_yarnBinPathDetails = findBinPathDetailsSync(constants.
|
|
3123
|
+
_yarnBinPathDetails = findBinPathDetailsSync(constants.YARN);
|
|
2640
3124
|
}
|
|
2641
3125
|
return _yarnBinPathDetails;
|
|
2642
3126
|
}
|
|
@@ -2668,202 +3152,25 @@ function isYarnBerry() {
|
|
|
2668
3152
|
return _isYarnBerry;
|
|
2669
3153
|
}
|
|
2670
3154
|
|
|
2671
|
-
function exitWithBinPathError$1(binName) {
|
|
2672
|
-
logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
|
|
2673
|
-
// The exit code 127 indicates that the command or binary being executed
|
|
2674
|
-
// could not be found.
|
|
2675
|
-
// eslint-disable-next-line n/no-process-exit
|
|
2676
|
-
process.exit(127);
|
|
2677
|
-
}
|
|
2678
|
-
let _npmBinPath;
|
|
2679
|
-
function getNpmBinPath() {
|
|
2680
|
-
if (_npmBinPath === undefined) {
|
|
2681
|
-
_npmBinPath = getNpmBinPathDetails().path;
|
|
2682
|
-
if (!_npmBinPath) {
|
|
2683
|
-
exitWithBinPathError$1(constants.NPM);
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
return _npmBinPath;
|
|
2687
|
-
}
|
|
2688
|
-
let _npmBinPathDetails;
|
|
2689
|
-
function getNpmBinPathDetails() {
|
|
2690
|
-
if (_npmBinPathDetails === undefined) {
|
|
2691
|
-
_npmBinPathDetails = findBinPathDetailsSync(constants.NPM);
|
|
2692
|
-
}
|
|
2693
|
-
return _npmBinPathDetails;
|
|
2694
|
-
}
|
|
2695
|
-
let _npmDirPath;
|
|
2696
|
-
function getNpmDirPath() {
|
|
2697
|
-
if (_npmDirPath === undefined) {
|
|
2698
|
-
const npmBinPath = getNpmBinPath();
|
|
2699
|
-
_npmDirPath = npmBinPath ? findNpmDirPathSync(npmBinPath) : undefined;
|
|
2700
|
-
if (!_npmDirPath) {
|
|
2701
|
-
_npmDirPath = constants.default.ENV.SOCKET_CLI_NPM_PATH || undefined;
|
|
2702
|
-
}
|
|
2703
|
-
if (!_npmDirPath) {
|
|
2704
|
-
let message = 'Unable to find npm CLI install directory.';
|
|
2705
|
-
if (npmBinPath) {
|
|
2706
|
-
message += `\nSearched parent directories of ${path.dirname(npmBinPath)}.`;
|
|
2707
|
-
}
|
|
2708
|
-
message += '\n\nThis is may be a bug with socket-npm related to changes to the npm CLI.';
|
|
2709
|
-
message += `\nPlease report to ${constants.default.SOCKET_CLI_ISSUES_URL}.`;
|
|
2710
|
-
logger.logger.fail(message);
|
|
2711
|
-
// The exit code 127 indicates that the command or binary being executed
|
|
2712
|
-
// could not be found.
|
|
2713
|
-
// eslint-disable-next-line n/no-process-exit
|
|
2714
|
-
process.exit(127);
|
|
2715
|
-
}
|
|
2716
|
-
}
|
|
2717
|
-
return _npmDirPath;
|
|
2718
|
-
}
|
|
2719
|
-
let _npmRequire;
|
|
2720
|
-
function getNpmRequire() {
|
|
2721
|
-
if (_npmRequire === undefined) {
|
|
2722
|
-
const npmDirPath = getNpmDirPath();
|
|
2723
|
-
const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
|
|
2724
|
-
_npmRequire = require$$5.createRequire(path.join(fs$1.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
|
|
2725
|
-
}
|
|
2726
|
-
return _npmRequire;
|
|
2727
|
-
}
|
|
2728
|
-
let _npxBinPath;
|
|
2729
|
-
function getNpxBinPath() {
|
|
2730
|
-
if (_npxBinPath === undefined) {
|
|
2731
|
-
_npxBinPath = getNpxBinPathDetails().path;
|
|
2732
|
-
if (!_npxBinPath) {
|
|
2733
|
-
exitWithBinPathError$1('npx');
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2736
|
-
return _npxBinPath;
|
|
2737
|
-
}
|
|
2738
|
-
let _npxBinPathDetails;
|
|
2739
|
-
function getNpxBinPathDetails() {
|
|
2740
|
-
if (_npxBinPathDetails === undefined) {
|
|
2741
|
-
_npxBinPathDetails = findBinPathDetailsSync('npx');
|
|
2742
|
-
}
|
|
2743
|
-
return _npxBinPathDetails;
|
|
2744
|
-
}
|
|
2745
|
-
function isNpmBinPathShadowed() {
|
|
2746
|
-
return getNpmBinPathDetails().shadowed;
|
|
2747
|
-
}
|
|
2748
|
-
function isNpxBinPathShadowed() {
|
|
2749
|
-
return getNpxBinPathDetails().shadowed;
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
const helpFlags = new Set([constants.FLAG_HELP, '-h']);
|
|
2753
|
-
|
|
2754
3155
|
/**
|
|
2755
|
-
*
|
|
3156
|
+
* DLX execution utilities for Socket CLI.
|
|
3157
|
+
* Manages package execution via npx/pnpm dlx/yarn dlx commands.
|
|
3158
|
+
*
|
|
3159
|
+
* Key Functions:
|
|
3160
|
+
* - spawnCdxgenDlx: Execute CycloneDX generator via dlx
|
|
3161
|
+
* - spawnCoanaDlx: Execute Coana CLI tool via dlx
|
|
3162
|
+
* - spawnDlx: Execute packages using dlx-style commands
|
|
3163
|
+
* - spawnSynpDlx: Execute Synp converter via dlx
|
|
3164
|
+
*
|
|
3165
|
+
* Package Manager Detection:
|
|
3166
|
+
* - Auto-detects npm, pnpm, or yarn based on lockfiles
|
|
3167
|
+
* - Supports force-refresh and silent execution modes
|
|
3168
|
+
*
|
|
3169
|
+
* Integration:
|
|
3170
|
+
* - Works with shadow binaries for security scanning
|
|
3171
|
+
* - Handles version pinning and cache management
|
|
3172
|
+
* - Configures environment for third-party tools
|
|
2756
3173
|
*/
|
|
2757
|
-
function cmdFlagsToString(args) {
|
|
2758
|
-
const result = [];
|
|
2759
|
-
for (let i = 0, {
|
|
2760
|
-
length
|
|
2761
|
-
} = args; i < length; i += 1) {
|
|
2762
|
-
const arg = args[i].trim();
|
|
2763
|
-
if (arg.startsWith('--')) {
|
|
2764
|
-
const nextArg = i + 1 < length ? args[i + 1].trim() : undefined;
|
|
2765
|
-
// Check if the next item exists and is NOT another flag.
|
|
2766
|
-
if (nextArg && !nextArg.startsWith('--')) {
|
|
2767
|
-
result.push(`${arg}=${nextArg}`);
|
|
2768
|
-
i += 1;
|
|
2769
|
-
} else {
|
|
2770
|
-
result.push(arg);
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
}
|
|
2774
|
-
return result.join(' ');
|
|
2775
|
-
}
|
|
2776
|
-
|
|
2777
|
-
/**
|
|
2778
|
-
* Convert flag values to array format for processing.
|
|
2779
|
-
*/
|
|
2780
|
-
function cmdFlagValueToArray(value) {
|
|
2781
|
-
if (typeof value === 'string') {
|
|
2782
|
-
return value.trim().split(/, */).filter(Boolean);
|
|
2783
|
-
}
|
|
2784
|
-
if (Array.isArray(value)) {
|
|
2785
|
-
return value.flatMap(cmdFlagValueToArray);
|
|
2786
|
-
}
|
|
2787
|
-
return [];
|
|
2788
|
-
}
|
|
2789
|
-
|
|
2790
|
-
/**
|
|
2791
|
-
* Add command name prefix to message text.
|
|
2792
|
-
*/
|
|
2793
|
-
function cmdPrefixMessage(cmdName, text) {
|
|
2794
|
-
const cmdPrefix = cmdName ? `${cmdName}: ` : '';
|
|
2795
|
-
return `${cmdPrefix}${text}`;
|
|
2796
|
-
}
|
|
2797
|
-
|
|
2798
|
-
/**
|
|
2799
|
-
* Filter out Socket flags from argv before passing to subcommands.
|
|
2800
|
-
*/
|
|
2801
|
-
function filterFlags(argv, flagsToFilter, exceptions) {
|
|
2802
|
-
const filtered = [];
|
|
2803
|
-
|
|
2804
|
-
// Build set of flags to filter from the provided flag objects.
|
|
2805
|
-
const flagsToFilterSet = new Set();
|
|
2806
|
-
const flagsWithValueSet = new Set();
|
|
2807
|
-
for (const [flagName, flag] of Object.entries(flagsToFilter)) {
|
|
2808
|
-
const longFlag = `--${camelToKebab(flagName)}`;
|
|
2809
|
-
// Special case for negated booleans.
|
|
2810
|
-
if (flagName === 'spinner' || flagName === 'banner') {
|
|
2811
|
-
flagsToFilterSet.add(`--no-${flagName}`);
|
|
2812
|
-
} else {
|
|
2813
|
-
flagsToFilterSet.add(longFlag);
|
|
2814
|
-
}
|
|
2815
|
-
if (flag?.shortFlag) {
|
|
2816
|
-
flagsToFilterSet.add(`-${flag.shortFlag}`);
|
|
2817
|
-
}
|
|
2818
|
-
// Track flags that take values.
|
|
2819
|
-
if (flag.type !== 'boolean') {
|
|
2820
|
-
flagsWithValueSet.add(longFlag);
|
|
2821
|
-
if (flag?.shortFlag) {
|
|
2822
|
-
flagsWithValueSet.add(`-${flag.shortFlag}`);
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
for (let i = 0, {
|
|
2827
|
-
length
|
|
2828
|
-
} = argv; i < length; i += 1) {
|
|
2829
|
-
const arg = argv[i];
|
|
2830
|
-
// Check if this flag should be kept as an exception.
|
|
2831
|
-
if (exceptions?.includes(arg)) {
|
|
2832
|
-
filtered.push(arg);
|
|
2833
|
-
// Handle flags that take values.
|
|
2834
|
-
if (flagsWithValueSet.has(arg)) {
|
|
2835
|
-
// Include the next argument (the flag value).
|
|
2836
|
-
i += 1;
|
|
2837
|
-
if (i < length) {
|
|
2838
|
-
filtered.push(argv[i]);
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
} else if (flagsToFilterSet.has(arg)) {
|
|
2842
|
-
// Skip flags that take values.
|
|
2843
|
-
if (flagsWithValueSet.has(arg)) {
|
|
2844
|
-
// Skip the next argument (the flag value).
|
|
2845
|
-
i += 1;
|
|
2846
|
-
}
|
|
2847
|
-
// Skip boolean flags (no additional argument to skip).
|
|
2848
|
-
} else if (arg && Array.from(flagsWithValueSet).some(flag => arg.startsWith(`${flag}=`))) {
|
|
2849
|
-
// Skip --flag=value format for Socket flags unless it's an exception.
|
|
2850
|
-
if (exceptions?.some(exc => arg.startsWith(`${exc}=`))) {
|
|
2851
|
-
filtered.push(arg);
|
|
2852
|
-
}
|
|
2853
|
-
// Otherwise skip it.
|
|
2854
|
-
} else {
|
|
2855
|
-
filtered.push(arg);
|
|
2856
|
-
}
|
|
2857
|
-
}
|
|
2858
|
-
return filtered;
|
|
2859
|
-
}
|
|
2860
|
-
|
|
2861
|
-
/**
|
|
2862
|
-
* Check if argument is a help flag.
|
|
2863
|
-
*/
|
|
2864
|
-
function isHelpFlag(cmdArg) {
|
|
2865
|
-
return helpFlags.has(cmdArg);
|
|
2866
|
-
}
|
|
2867
3174
|
|
|
2868
3175
|
const require$2 = require$$5.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('utils.js', document.baseURI).href)));
|
|
2869
3176
|
const {
|
|
@@ -2919,10 +3226,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2919
3226
|
const packageString = `${packageSpec.name}@${packageSpec.version}`;
|
|
2920
3227
|
|
|
2921
3228
|
// Build command args based on package manager.
|
|
2922
|
-
let binName;
|
|
2923
3229
|
let spawnArgs;
|
|
2924
3230
|
if (pm === constants.PNPM) {
|
|
2925
|
-
binName = constants.PNPM;
|
|
2926
3231
|
spawnArgs = ['dlx'];
|
|
2927
3232
|
if (force) {
|
|
2928
3233
|
// For pnpm, set dlx-cache-max-age to 0 via env to force fresh download.
|
|
@@ -2949,7 +3254,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2949
3254
|
const shadowPnpmBin = /*@__PURE__*/require$2(constants.default.shadowPnpmBinPath);
|
|
2950
3255
|
return await shadowPnpmBin(spawnArgs, finalShadowOptions, spawnExtra);
|
|
2951
3256
|
} else if (pm === constants.YARN && isYarnBerry()) {
|
|
2952
|
-
binName = constants.YARN;
|
|
2953
3257
|
spawnArgs = ['dlx'];
|
|
2954
3258
|
// Yarn dlx runs in a temporary environment by design and should always fetch fresh.
|
|
2955
3259
|
if (silent) {
|
|
@@ -2961,7 +3265,6 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2961
3265
|
} else {
|
|
2962
3266
|
// Use npm exec/npx.
|
|
2963
3267
|
// For consistency, we'll use npx which is more commonly used for one-off execution.
|
|
2964
|
-
binName = 'npx';
|
|
2965
3268
|
spawnArgs = ['--yes'];
|
|
2966
3269
|
if (force) {
|
|
2967
3270
|
// Use --force to bypass cache and get latest within range.
|
|
@@ -2971,7 +3274,8 @@ async function spawnDlx(packageSpec, args, options, spawnExtra) {
|
|
|
2971
3274
|
spawnArgs.push(constants.FLAG_SILENT);
|
|
2972
3275
|
}
|
|
2973
3276
|
spawnArgs.push(packageString, ...args);
|
|
2974
|
-
|
|
3277
|
+
const shadowNpxBin = /*@__PURE__*/require$2(constants.default.shadowNpxBinPath);
|
|
3278
|
+
return await shadowNpxBin(spawnArgs, finalShadowOptions, spawnExtra);
|
|
2975
3279
|
}
|
|
2976
3280
|
}
|
|
2977
3281
|
|
|
@@ -3036,8 +3340,8 @@ async function spawnCoanaDlx(args, orgSlug, options, spawnExtra) {
|
|
|
3036
3340
|
};
|
|
3037
3341
|
} catch (e) {
|
|
3038
3342
|
const stderr = e?.stderr;
|
|
3039
|
-
const cause = e
|
|
3040
|
-
const message = stderr
|
|
3343
|
+
const cause = getErrorCause(e);
|
|
3344
|
+
const message = stderr || cause;
|
|
3041
3345
|
return {
|
|
3042
3346
|
ok: false,
|
|
3043
3347
|
data: e,
|
|
@@ -3084,6 +3388,26 @@ function hasEnterpriseOrgPlan(orgs) {
|
|
|
3084
3388
|
return orgs.some(o => o.plan === 'enterprise');
|
|
3085
3389
|
}
|
|
3086
3390
|
|
|
3391
|
+
/**
|
|
3392
|
+
* Socket JSON utilities for Socket CLI.
|
|
3393
|
+
* Manages .socket/socket.json configuration and scan metadata.
|
|
3394
|
+
*
|
|
3395
|
+
* Key Functions:
|
|
3396
|
+
* - loadDotSocketDirectory: Load .socket directory configuration
|
|
3397
|
+
* - saveSocketJson: Persist scan configuration to .socket/socket.json
|
|
3398
|
+
* - validateSocketJson: Validate socket.json structure
|
|
3399
|
+
*
|
|
3400
|
+
* File Structure:
|
|
3401
|
+
* - Contains scan metadata and configuration
|
|
3402
|
+
* - Stores scan IDs and repository information
|
|
3403
|
+
* - Tracks CLI version and scan timestamps
|
|
3404
|
+
*
|
|
3405
|
+
* Directory Management:
|
|
3406
|
+
* - Creates .socket directory as needed
|
|
3407
|
+
* - Handles nested directory structures
|
|
3408
|
+
* - Supports both read and write operations
|
|
3409
|
+
*/
|
|
3410
|
+
|
|
3087
3411
|
function readOrDefaultSocketJson(cwd) {
|
|
3088
3412
|
const jsonCResult = readSocketJsonSync(cwd, true);
|
|
3089
3413
|
return jsonCResult.ok ? jsonCResult.data :
|
|
@@ -3129,35 +3453,31 @@ function readSocketJsonSync(cwd, defaultOnError = false) {
|
|
|
3129
3453
|
} catch (e) {
|
|
3130
3454
|
if (defaultOnError) {
|
|
3131
3455
|
logger.logger.warn(`Failed to read ${constants.SOCKET_JSON}, using default`);
|
|
3132
|
-
require$$9.
|
|
3133
|
-
|
|
3134
|
-
});
|
|
3456
|
+
require$$9.debugFn('warn', `Failed to read ${constants.SOCKET_JSON} sync`);
|
|
3457
|
+
require$$9.debugDir('warn', e);
|
|
3135
3458
|
return {
|
|
3136
3459
|
ok: true,
|
|
3137
3460
|
data: getDefaultSocketJson()
|
|
3138
3461
|
};
|
|
3139
3462
|
}
|
|
3140
|
-
const cause = e
|
|
3141
|
-
require$$9.
|
|
3142
|
-
|
|
3143
|
-
});
|
|
3463
|
+
const cause = formatErrorWithDetail(`An error occurred while trying to read ${constants.SOCKET_JSON}`, e);
|
|
3464
|
+
require$$9.debugFn('error', `Failed to read ${constants.SOCKET_JSON} sync`);
|
|
3465
|
+
require$$9.debugDir('error', e);
|
|
3144
3466
|
return {
|
|
3145
3467
|
ok: false,
|
|
3146
3468
|
message: `Failed to read ${constants.SOCKET_JSON}`,
|
|
3147
|
-
cause
|
|
3469
|
+
cause
|
|
3148
3470
|
};
|
|
3149
3471
|
}
|
|
3150
3472
|
let jsonObj;
|
|
3151
3473
|
try {
|
|
3152
3474
|
jsonObj = JSON.parse(jsonContent);
|
|
3153
3475
|
} catch (e) {
|
|
3154
|
-
require$$9.debugFn('error',
|
|
3476
|
+
require$$9.debugFn('error', `Failed to parse ${constants.SOCKET_JSON} as JSON (sync)`);
|
|
3155
3477
|
require$$9.debugDir('inspect', {
|
|
3156
3478
|
jsonContent
|
|
3157
3479
|
});
|
|
3158
|
-
require$$9.debugDir('
|
|
3159
|
-
error: e
|
|
3160
|
-
});
|
|
3480
|
+
require$$9.debugDir('error', e);
|
|
3161
3481
|
if (defaultOnError) {
|
|
3162
3482
|
logger.logger.warn(`Failed to parse ${constants.SOCKET_JSON}, using default`);
|
|
3163
3483
|
return {
|
|
@@ -3191,11 +3511,11 @@ async function writeSocketJson(cwd, sockJson) {
|
|
|
3191
3511
|
try {
|
|
3192
3512
|
jsonContent = JSON.stringify(sockJson, null, 2);
|
|
3193
3513
|
} catch (e) {
|
|
3194
|
-
require$$9.debugFn('error',
|
|
3514
|
+
require$$9.debugFn('error', `Failed to serialize ${constants.SOCKET_JSON} to JSON`);
|
|
3195
3515
|
require$$9.debugDir('inspect', {
|
|
3196
|
-
error: e,
|
|
3197
3516
|
sockJson
|
|
3198
3517
|
});
|
|
3518
|
+
require$$9.debugDir('error', e);
|
|
3199
3519
|
return {
|
|
3200
3520
|
ok: false,
|
|
3201
3521
|
message: 'Failed to serialize to JSON',
|
|
@@ -3210,6 +3530,32 @@ async function writeSocketJson(cwd, sockJson) {
|
|
|
3210
3530
|
};
|
|
3211
3531
|
}
|
|
3212
3532
|
|
|
3533
|
+
/**
|
|
3534
|
+
* GitHub utilities for Socket CLI.
|
|
3535
|
+
* Provides GitHub API integration for repository operations and GHSA vulnerability data.
|
|
3536
|
+
*
|
|
3537
|
+
* Authentication:
|
|
3538
|
+
* - getGitHubToken: Retrieve GitHub token from env/git config
|
|
3539
|
+
* - getOctokit: Get authenticated Octokit instance
|
|
3540
|
+
* - getOctokitGraphql: Get authenticated GraphQL client
|
|
3541
|
+
*
|
|
3542
|
+
* Caching:
|
|
3543
|
+
* - 5-minute TTL for API responses
|
|
3544
|
+
* - Automatic cache invalidation
|
|
3545
|
+
* - Persistent cache in node_modules/.cache
|
|
3546
|
+
*
|
|
3547
|
+
* GHSA Operations:
|
|
3548
|
+
* - cacheFetch: Cache API responses with TTL
|
|
3549
|
+
* - fetchGhsaDetails: Fetch GitHub Security Advisory details
|
|
3550
|
+
* - getGhsaUrl: Generate GHSA advisory URL
|
|
3551
|
+
* - readCache/writeCache: Persistent cache operations
|
|
3552
|
+
*
|
|
3553
|
+
* Repository Operations:
|
|
3554
|
+
* - GraphQL queries for complex operations
|
|
3555
|
+
* - Integration with Octokit REST API
|
|
3556
|
+
* - Support for GitHub Actions environment variables
|
|
3557
|
+
*/
|
|
3558
|
+
|
|
3213
3559
|
async function readCache(key,
|
|
3214
3560
|
// 5 minute in milliseconds time to live (TTL).
|
|
3215
3561
|
ttlMs = 5 * 60 * 1000) {
|
|
@@ -3289,11 +3635,8 @@ async function fetchGhsaDetails(ids) {
|
|
|
3289
3635
|
}
|
|
3290
3636
|
}
|
|
3291
3637
|
} catch (e) {
|
|
3292
|
-
|
|
3293
|
-
require$$9.
|
|
3294
|
-
require$$9.debugDir('inspect', {
|
|
3295
|
-
error: e
|
|
3296
|
-
});
|
|
3638
|
+
require$$9.debugFn('error', formatErrorWithDetail('Failed to fetch GHSA details', e));
|
|
3639
|
+
require$$9.debugDir('error', e);
|
|
3297
3640
|
}
|
|
3298
3641
|
return results;
|
|
3299
3642
|
}
|
|
@@ -3397,12 +3740,153 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
|
|
|
3397
3740
|
await spawn.spawn('git', ['remote', 'set-url', 'origin', url], stdioIgnoreOptions);
|
|
3398
3741
|
return true;
|
|
3399
3742
|
} catch (e) {
|
|
3400
|
-
require$$9.debugFn('error', `
|
|
3743
|
+
require$$9.debugFn('error', `Git command failed: ${quotedCmd}`);
|
|
3401
3744
|
require$$9.debugDir('inspect', {
|
|
3402
|
-
|
|
3745
|
+
cmd: quotedCmd
|
|
3403
3746
|
});
|
|
3747
|
+
require$$9.debugDir('error', e);
|
|
3748
|
+
}
|
|
3749
|
+
return false;
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
/**
|
|
3753
|
+
* Command-line utilities for Socket CLI.
|
|
3754
|
+
* Handles argument parsing, flag processing, and command formatting.
|
|
3755
|
+
*
|
|
3756
|
+
* Argument Handling:
|
|
3757
|
+
* - Handles both long (--flag) and short (-f) formats
|
|
3758
|
+
* - Preserves special characters and escaping
|
|
3759
|
+
* - Properly quotes arguments containing spaces
|
|
3760
|
+
*
|
|
3761
|
+
* Command Names:
|
|
3762
|
+
* - commandNameFromCamel: Convert camelCase to kebab-case command names
|
|
3763
|
+
* - commandNameFromKebab: Convert kebab-case to camelCase
|
|
3764
|
+
*
|
|
3765
|
+
* Flag Processing:
|
|
3766
|
+
* - cmdFlagsToString: Format arguments for display with proper escaping
|
|
3767
|
+
* - cmdPrefixMessage: Generate command prefix message
|
|
3768
|
+
* - stripConfigFlags: Remove --config flags from argument list
|
|
3769
|
+
* - stripDebugFlags: Remove debug-related flags
|
|
3770
|
+
* - stripHelpFlags: Remove help flags (-h, --help)
|
|
3771
|
+
*/
|
|
3772
|
+
|
|
3773
|
+
const helpFlags = new Set([constants.FLAG_HELP, '-h']);
|
|
3774
|
+
|
|
3775
|
+
/**
|
|
3776
|
+
* Convert command arguments to a properly formatted string representation.
|
|
3777
|
+
*/
|
|
3778
|
+
function cmdFlagsToString(args) {
|
|
3779
|
+
const result = [];
|
|
3780
|
+
for (let i = 0, {
|
|
3781
|
+
length
|
|
3782
|
+
} = args; i < length; i += 1) {
|
|
3783
|
+
const arg = args[i].trim();
|
|
3784
|
+
if (arg.startsWith('--')) {
|
|
3785
|
+
const nextArg = i + 1 < length ? args[i + 1].trim() : undefined;
|
|
3786
|
+
// Check if the next item exists and is NOT another flag.
|
|
3787
|
+
if (nextArg && !nextArg.startsWith('--') && !nextArg.startsWith('-')) {
|
|
3788
|
+
result.push(`${arg}=${nextArg}`);
|
|
3789
|
+
i += 1;
|
|
3790
|
+
} else {
|
|
3791
|
+
result.push(arg);
|
|
3792
|
+
}
|
|
3793
|
+
} else {
|
|
3794
|
+
// Include non-flag arguments (commands, package names, etc.).
|
|
3795
|
+
result.push(arg);
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
return result.join(' ');
|
|
3799
|
+
}
|
|
3800
|
+
|
|
3801
|
+
/**
|
|
3802
|
+
* Convert flag values to array format for processing.
|
|
3803
|
+
*/
|
|
3804
|
+
function cmdFlagValueToArray(value) {
|
|
3805
|
+
if (typeof value === 'string') {
|
|
3806
|
+
return value.trim().split(/, */).filter(Boolean);
|
|
3807
|
+
}
|
|
3808
|
+
if (Array.isArray(value)) {
|
|
3809
|
+
return value.flatMap(cmdFlagValueToArray);
|
|
3810
|
+
}
|
|
3811
|
+
return [];
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
/**
|
|
3815
|
+
* Add command name prefix to message text.
|
|
3816
|
+
*/
|
|
3817
|
+
function cmdPrefixMessage(cmdName, text) {
|
|
3818
|
+
const cmdPrefix = cmdName ? `${cmdName}: ` : '';
|
|
3819
|
+
return `${cmdPrefix}${text}`;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
/**
|
|
3823
|
+
* Filter out Socket flags from argv before passing to subcommands.
|
|
3824
|
+
*/
|
|
3825
|
+
function filterFlags(argv, flagsToFilter, exceptions) {
|
|
3826
|
+
const filtered = [];
|
|
3827
|
+
|
|
3828
|
+
// Build set of flags to filter from the provided flag objects.
|
|
3829
|
+
const flagsToFilterSet = new Set();
|
|
3830
|
+
const flagsWithValueSet = new Set();
|
|
3831
|
+
for (const [flagName, flag] of Object.entries(flagsToFilter)) {
|
|
3832
|
+
const longFlag = `--${camelToKebab(flagName)}`;
|
|
3833
|
+
// Special case for negated booleans.
|
|
3834
|
+
if (flagName === 'spinner' || flagName === 'banner') {
|
|
3835
|
+
flagsToFilterSet.add(`--no-${flagName}`);
|
|
3836
|
+
} else {
|
|
3837
|
+
flagsToFilterSet.add(longFlag);
|
|
3838
|
+
}
|
|
3839
|
+
if (flag?.shortFlag) {
|
|
3840
|
+
flagsToFilterSet.add(`-${flag.shortFlag}`);
|
|
3841
|
+
}
|
|
3842
|
+
// Track flags that take values.
|
|
3843
|
+
if (flag.type !== 'boolean') {
|
|
3844
|
+
flagsWithValueSet.add(longFlag);
|
|
3845
|
+
if (flag?.shortFlag) {
|
|
3846
|
+
flagsWithValueSet.add(`-${flag.shortFlag}`);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
for (let i = 0, {
|
|
3851
|
+
length
|
|
3852
|
+
} = argv; i < length; i += 1) {
|
|
3853
|
+
const arg = argv[i];
|
|
3854
|
+
// Check if this flag should be kept as an exception.
|
|
3855
|
+
if (exceptions?.includes(arg)) {
|
|
3856
|
+
filtered.push(arg);
|
|
3857
|
+
// Handle flags that take values.
|
|
3858
|
+
if (flagsWithValueSet.has(arg)) {
|
|
3859
|
+
// Include the next argument (the flag value).
|
|
3860
|
+
i += 1;
|
|
3861
|
+
if (i < length) {
|
|
3862
|
+
filtered.push(argv[i]);
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
} else if (flagsToFilterSet.has(arg)) {
|
|
3866
|
+
// Skip flags that take values.
|
|
3867
|
+
if (flagsWithValueSet.has(arg)) {
|
|
3868
|
+
// Skip the next argument (the flag value).
|
|
3869
|
+
i += 1;
|
|
3870
|
+
}
|
|
3871
|
+
// Skip boolean flags (no additional argument to skip).
|
|
3872
|
+
} else if (arg && Array.from(flagsWithValueSet).some(flag => arg.startsWith(`${flag}=`))) {
|
|
3873
|
+
// Skip --flag=value format for Socket flags unless it's an exception.
|
|
3874
|
+
if (exceptions?.some(exc => arg.startsWith(`${exc}=`))) {
|
|
3875
|
+
filtered.push(arg);
|
|
3876
|
+
}
|
|
3877
|
+
// Otherwise skip it.
|
|
3878
|
+
} else {
|
|
3879
|
+
filtered.push(arg);
|
|
3880
|
+
}
|
|
3404
3881
|
}
|
|
3405
|
-
return
|
|
3882
|
+
return filtered;
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3885
|
+
/**
|
|
3886
|
+
* Check if argument is a help flag.
|
|
3887
|
+
*/
|
|
3888
|
+
function isHelpFlag(cmdArg) {
|
|
3889
|
+
return helpFlags.has(cmdArg);
|
|
3406
3890
|
}
|
|
3407
3891
|
|
|
3408
3892
|
/**
|
|
@@ -3429,7 +3913,7 @@ async function convertCveToGhsa(cveId) {
|
|
|
3429
3913
|
} catch (e) {
|
|
3430
3914
|
return {
|
|
3431
3915
|
ok: false,
|
|
3432
|
-
message: `Failed to convert CVE to GHSA: ${e
|
|
3916
|
+
message: `Failed to convert CVE to GHSA: ${getErrorCause(e)}`
|
|
3433
3917
|
};
|
|
3434
3918
|
}
|
|
3435
3919
|
}
|
|
@@ -3493,7 +3977,7 @@ async function convertPurlToGhsas(purl) {
|
|
|
3493
3977
|
} catch (e) {
|
|
3494
3978
|
return {
|
|
3495
3979
|
ok: false,
|
|
3496
|
-
message: `Failed to convert PURL to GHSA: ${e
|
|
3980
|
+
message: `Failed to convert PURL to GHSA: ${getErrorCause(e)}`
|
|
3497
3981
|
};
|
|
3498
3982
|
}
|
|
3499
3983
|
}
|
|
@@ -3564,39 +4048,100 @@ fi
|
|
|
3564
4048
|
};
|
|
3565
4049
|
}
|
|
3566
4050
|
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
4051
|
+
/**
|
|
4052
|
+
* Safe wrapper for npm-package-arg that doesn't throw.
|
|
4053
|
+
* Returns undefined if parsing fails.
|
|
4054
|
+
*/
|
|
4055
|
+
function safeNpa$1(...args) {
|
|
4056
|
+
try {
|
|
4057
|
+
return Reflect.apply(vendor.npaExports, undefined, args);
|
|
4058
|
+
} catch {}
|
|
4059
|
+
return undefined;
|
|
4060
|
+
}
|
|
4061
|
+
|
|
4062
|
+
function exitWithBinPathError$1(binName) {
|
|
4063
|
+
logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
|
|
4064
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
4065
|
+
// could not be found.
|
|
4066
|
+
// eslint-disable-next-line n/no-process-exit
|
|
4067
|
+
process.exit(127);
|
|
4068
|
+
// This line is never reached in production, but helps tests.
|
|
4069
|
+
throw new Error('process.exit called');
|
|
4070
|
+
}
|
|
4071
|
+
let _npmBinPath;
|
|
4072
|
+
function getNpmBinPath() {
|
|
4073
|
+
if (_npmBinPath === undefined) {
|
|
4074
|
+
_npmBinPath = getNpmBinPathDetails().path;
|
|
4075
|
+
if (!_npmBinPath) {
|
|
4076
|
+
exitWithBinPathError$1(constants.NPM);
|
|
4077
|
+
}
|
|
3571
4078
|
}
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
4079
|
+
return _npmBinPath;
|
|
4080
|
+
}
|
|
4081
|
+
let _npmBinPathDetails;
|
|
4082
|
+
function getNpmBinPathDetails() {
|
|
4083
|
+
if (_npmBinPathDetails === undefined) {
|
|
4084
|
+
_npmBinPathDetails = findBinPathDetailsSync(constants.NPM);
|
|
3578
4085
|
}
|
|
4086
|
+
return _npmBinPathDetails;
|
|
3579
4087
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
4088
|
+
let _npmDirPath;
|
|
4089
|
+
function getNpmDirPath() {
|
|
4090
|
+
if (_npmDirPath === undefined) {
|
|
4091
|
+
const npmBinPath = getNpmBinPath();
|
|
4092
|
+
_npmDirPath = npmBinPath ? findNpmDirPathSync(npmBinPath) : undefined;
|
|
4093
|
+
if (!_npmDirPath) {
|
|
4094
|
+
_npmDirPath = constants.default.ENV.SOCKET_CLI_NPM_PATH || undefined;
|
|
4095
|
+
}
|
|
4096
|
+
if (!_npmDirPath) {
|
|
4097
|
+
let message = 'Unable to find npm CLI install directory.';
|
|
4098
|
+
if (npmBinPath) {
|
|
4099
|
+
message += `\nSearched parent directories of ${path.dirname(npmBinPath)}.`;
|
|
4100
|
+
}
|
|
4101
|
+
message += '\n\nThis is may be a bug with socket-npm related to changes to the npm CLI.';
|
|
4102
|
+
message += `\nPlease report to ${constants.default.SOCKET_CLI_ISSUES_URL}.`;
|
|
4103
|
+
logger.logger.fail(message);
|
|
4104
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
4105
|
+
// could not be found.
|
|
4106
|
+
// eslint-disable-next-line n/no-process-exit
|
|
4107
|
+
process.exit(127);
|
|
4108
|
+
// This line is never reached in production, but helps tests.
|
|
4109
|
+
throw new Error('process.exit called');
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
return _npmDirPath;
|
|
3585
4113
|
}
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
if (
|
|
3589
|
-
|
|
4114
|
+
let _npmRequire;
|
|
4115
|
+
function getNpmRequire() {
|
|
4116
|
+
if (_npmRequire === undefined) {
|
|
4117
|
+
const npmDirPath = getNpmDirPath();
|
|
4118
|
+
const npmNmPath = path.join(npmDirPath, `${constants.NODE_MODULES}/npm`);
|
|
4119
|
+
_npmRequire = require$$5.createRequire(path.join(fs$1.existsSync(npmNmPath) ? npmNmPath : npmDirPath, '<dummy-basename>'));
|
|
3590
4120
|
}
|
|
3591
|
-
|
|
3592
|
-
return Sentry.captureException(exception, hint);
|
|
4121
|
+
return _npmRequire;
|
|
3593
4122
|
}
|
|
3594
|
-
|
|
3595
|
-
function
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
4123
|
+
let _npxBinPath;
|
|
4124
|
+
function getNpxBinPath() {
|
|
4125
|
+
if (_npxBinPath === undefined) {
|
|
4126
|
+
_npxBinPath = getNpxBinPathDetails().path;
|
|
4127
|
+
if (!_npxBinPath) {
|
|
4128
|
+
exitWithBinPathError$1('npx');
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
return _npxBinPath;
|
|
4132
|
+
}
|
|
4133
|
+
let _npxBinPathDetails;
|
|
4134
|
+
function getNpxBinPathDetails() {
|
|
4135
|
+
if (_npxBinPathDetails === undefined) {
|
|
4136
|
+
_npxBinPathDetails = findBinPathDetailsSync('npx');
|
|
4137
|
+
}
|
|
4138
|
+
return _npxBinPathDetails;
|
|
4139
|
+
}
|
|
4140
|
+
function isNpmBinPathShadowed() {
|
|
4141
|
+
return getNpmBinPathDetails().shadowed;
|
|
4142
|
+
}
|
|
4143
|
+
function isNpxBinPathShadowed() {
|
|
4144
|
+
return getNpxBinPathDetails().shadowed;
|
|
3600
4145
|
}
|
|
3601
4146
|
|
|
3602
4147
|
function shadowNpmInstall(options) {
|
|
@@ -3662,6 +4207,24 @@ function shadowNpmInstall(options) {
|
|
|
3662
4207
|
return spawnPromise;
|
|
3663
4208
|
}
|
|
3664
4209
|
|
|
4210
|
+
/**
|
|
4211
|
+
* Package manager agent utilities for Socket CLI.
|
|
4212
|
+
* Manages package installation via different package managers.
|
|
4213
|
+
*
|
|
4214
|
+
* Key Functions:
|
|
4215
|
+
* - runAgentInstall: Execute package installation with detected agent
|
|
4216
|
+
*
|
|
4217
|
+
* Supported Agents:
|
|
4218
|
+
* - npm: Node Package Manager
|
|
4219
|
+
* - pnpm: Fast, disk space efficient package manager
|
|
4220
|
+
* - yarn: Alternative package manager
|
|
4221
|
+
*
|
|
4222
|
+
* Features:
|
|
4223
|
+
* - Automatic agent detection
|
|
4224
|
+
* - Shadow installation for security scanning
|
|
4225
|
+
* - Spinner support for progress indication
|
|
4226
|
+
*/
|
|
4227
|
+
|
|
3665
4228
|
function runAgentInstall(pkgEnvDetails, options) {
|
|
3666
4229
|
const {
|
|
3667
4230
|
agent,
|
|
@@ -3706,6 +4269,32 @@ function runAgentInstall(pkgEnvDetails, options) {
|
|
|
3706
4269
|
});
|
|
3707
4270
|
}
|
|
3708
4271
|
|
|
4272
|
+
/**
|
|
4273
|
+
* Package environment detection utilities for Socket CLI.
|
|
4274
|
+
* Analyzes project environment and package manager configuration.
|
|
4275
|
+
*
|
|
4276
|
+
* Key Functions:
|
|
4277
|
+
* - getPackageEnvironment: Detect package manager and project details
|
|
4278
|
+
* - makeConcurrentExecLimit: Calculate concurrent execution limits
|
|
4279
|
+
*
|
|
4280
|
+
* Environment Detection:
|
|
4281
|
+
* - Detects npm, pnpm, yarn, bun package managers
|
|
4282
|
+
* - Analyzes lockfiles for version information
|
|
4283
|
+
* - Determines Node.js and engine requirements
|
|
4284
|
+
* - Identifies workspace configurations
|
|
4285
|
+
*
|
|
4286
|
+
* Features:
|
|
4287
|
+
* - Browser target detection via browserslist
|
|
4288
|
+
* - Engine compatibility checking
|
|
4289
|
+
* - Package manager version detection
|
|
4290
|
+
* - Workspace and monorepo support
|
|
4291
|
+
*
|
|
4292
|
+
* Usage:
|
|
4293
|
+
* - Auto-detecting appropriate package manager
|
|
4294
|
+
* - Validating environment compatibility
|
|
4295
|
+
* - Configuring concurrent execution limits
|
|
4296
|
+
*/
|
|
4297
|
+
|
|
3709
4298
|
const {
|
|
3710
4299
|
BUN,
|
|
3711
4300
|
BUN_LOCK,
|
|
@@ -3833,10 +4422,11 @@ async function getAgentVersion(agent, agentExecPath, cwd) {
|
|
|
3833
4422
|
shell: constants.default.WIN32
|
|
3834
4423
|
})).stdout) ?? undefined;
|
|
3835
4424
|
} catch (e) {
|
|
3836
|
-
require$$9.debugFn('error', `
|
|
4425
|
+
require$$9.debugFn('error', `Package manager command failed: ${quotedCmd}`);
|
|
3837
4426
|
require$$9.debugDir('inspect', {
|
|
3838
|
-
|
|
4427
|
+
cmd: quotedCmd
|
|
3839
4428
|
});
|
|
4429
|
+
require$$9.debugDir('error', e);
|
|
3840
4430
|
}
|
|
3841
4431
|
return result;
|
|
3842
4432
|
}
|
|
@@ -4065,39 +4655,47 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
|
4065
4655
|
};
|
|
4066
4656
|
}
|
|
4067
4657
|
|
|
4658
|
+
/**
|
|
4659
|
+
* Ecosystem type utilities for Socket CLI.
|
|
4660
|
+
* Manages package ecosystem identifiers and mappings.
|
|
4661
|
+
*
|
|
4662
|
+
* Constants:
|
|
4663
|
+
* - ALL_ECOSYSTEMS: Complete list of supported ecosystems
|
|
4664
|
+
* - ECOSYSTEM_MAP: Map ecosystem strings to PURL types
|
|
4665
|
+
*
|
|
4666
|
+
* Type Definitions:
|
|
4667
|
+
* - PURL_Type: Package URL type from Socket SDK
|
|
4668
|
+
*
|
|
4669
|
+
* Supported Ecosystems:
|
|
4670
|
+
* - apk, bitbucket, cargo, chrome, cocoapods, composer
|
|
4671
|
+
* - conan, conda, cran, deb, docker, gem, generic
|
|
4672
|
+
* - github, gitlab, go, hackage, hex, huggingface
|
|
4673
|
+
* - maven, mlflow, npm, nuget, oci, pub, pypi, rpm, swift
|
|
4674
|
+
*
|
|
4675
|
+
* Usage:
|
|
4676
|
+
* - Validates ecosystem types
|
|
4677
|
+
* - Maps between different ecosystem representations
|
|
4678
|
+
* - Ensures type safety for ecosystem operations
|
|
4679
|
+
*/
|
|
4680
|
+
|
|
4068
4681
|
const ALL_ECOSYSTEMS = ['apk', 'bitbucket', 'cargo', 'chrome', 'cocoapods', 'composer', 'conan', 'conda', 'cran', 'deb', 'docker', 'gem', 'generic', 'github', 'golang', 'hackage', 'hex', 'huggingface', 'maven', 'mlflow', constants.NPM, 'nuget', 'oci', 'pub', 'pypi', 'qpkg', 'rpm', 'swift', 'swid', 'unknown'];
|
|
4069
4682
|
new Set(ALL_ECOSYSTEMS);
|
|
4070
4683
|
function getEcosystemChoicesForMeow() {
|
|
4071
4684
|
return [...ALL_ECOSYSTEMS];
|
|
4072
4685
|
}
|
|
4073
4686
|
|
|
4074
|
-
|
|
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
|
-
}
|
|
4687
|
+
/**
|
|
4688
|
+
* Filter configuration utilities for Socket CLI.
|
|
4689
|
+
* Manages filter configuration normalization for security scanning.
|
|
4690
|
+
*
|
|
4691
|
+
* Key Functions:
|
|
4692
|
+
* - toFilterConfig: Normalize filter configuration objects
|
|
4693
|
+
*
|
|
4694
|
+
* Usage:
|
|
4695
|
+
* - Normalizes user-provided filter objects
|
|
4696
|
+
* - Ensures proper structure for filter configuration
|
|
4697
|
+
* - Validates boolean and array values
|
|
4698
|
+
*/
|
|
4101
4699
|
|
|
4102
4700
|
function toFilterConfig(obj) {
|
|
4103
4701
|
const normalized = {
|
|
@@ -4197,6 +4795,30 @@ const ALERT_SEVERITY = createEnum({
|
|
|
4197
4795
|
low: 'low'
|
|
4198
4796
|
});
|
|
4199
4797
|
|
|
4798
|
+
/**
|
|
4799
|
+
* Color and markdown formatting utilities for Socket CLI.
|
|
4800
|
+
* Provides dual-mode formatting for terminal colors or markdown output.
|
|
4801
|
+
*
|
|
4802
|
+
* Key Class:
|
|
4803
|
+
* - ColorOrMarkdown: Dual-mode formatter for terminal/markdown output
|
|
4804
|
+
*
|
|
4805
|
+
* Formatting Methods:
|
|
4806
|
+
* - bold: Bold text formatting
|
|
4807
|
+
* - codeBlock: Code block formatting
|
|
4808
|
+
* - codeInline: Inline code formatting
|
|
4809
|
+
* - header: Section headers
|
|
4810
|
+
* - hyperlink: Clickable links
|
|
4811
|
+
* - indent: Text indentation
|
|
4812
|
+
* - italic: Italic text formatting
|
|
4813
|
+
* - list: Bullet list formatting
|
|
4814
|
+
* - table: Table formatting
|
|
4815
|
+
*
|
|
4816
|
+
* Usage:
|
|
4817
|
+
* - Switches between terminal colors and markdown based on output format
|
|
4818
|
+
* - Supports both interactive terminal and report generation
|
|
4819
|
+
* - Handles hyperlink fallbacks for terminals without link support
|
|
4820
|
+
*/
|
|
4821
|
+
|
|
4200
4822
|
class ColorOrMarkdown {
|
|
4201
4823
|
constructor(useMarkdown) {
|
|
4202
4824
|
this.useMarkdown = !!useMarkdown;
|
|
@@ -4242,6 +4864,28 @@ function getTranslations() {
|
|
|
4242
4864
|
return _translations;
|
|
4243
4865
|
}
|
|
4244
4866
|
|
|
4867
|
+
/**
|
|
4868
|
+
* Socket package alert utilities for Socket CLI.
|
|
4869
|
+
* Handles security alerts, vulnerabilities, and package risk assessment.
|
|
4870
|
+
*
|
|
4871
|
+
* Key Functions:
|
|
4872
|
+
* - addArtifactToAlertsMap: Add security alert to package map
|
|
4873
|
+
* - logAlertsMap: Display alerts in formatted output
|
|
4874
|
+
* - shouldSkipPackageAlert: Filter alerts based on criteria
|
|
4875
|
+
*
|
|
4876
|
+
* Alert Types:
|
|
4877
|
+
* - CVE: Common Vulnerabilities and Exposures
|
|
4878
|
+
* - GHSA: GitHub Security Advisories
|
|
4879
|
+
* - Package quality issues
|
|
4880
|
+
* - Supply chain risks
|
|
4881
|
+
*
|
|
4882
|
+
* Features:
|
|
4883
|
+
* - Alert severity classification (critical/high/medium/low)
|
|
4884
|
+
* - Fix type detection (major/minor/patch/none)
|
|
4885
|
+
* - Alert filtering and suppression
|
|
4886
|
+
* - Colorized terminal output
|
|
4887
|
+
*/
|
|
4888
|
+
|
|
4245
4889
|
const ALERT_SEVERITY_COLOR = createEnum({
|
|
4246
4890
|
critical: 'magenta',
|
|
4247
4891
|
high: 'red',
|
|
@@ -4586,6 +5230,26 @@ function logAlertsMap(alertsMap, options) {
|
|
|
4586
5230
|
output.write('\n');
|
|
4587
5231
|
}
|
|
4588
5232
|
|
|
5233
|
+
/**
|
|
5234
|
+
* Alerts map utilities for Socket CLI.
|
|
5235
|
+
* Manages security alerts and vulnerability mappings for packages.
|
|
5236
|
+
*
|
|
5237
|
+
* Key Functions:
|
|
5238
|
+
* - getAlertsMapFromPnpmLockfile: Extract alerts from pnpm lockfile
|
|
5239
|
+
* - getAlertsMapFromPurls: Get alerts for specific package URLs
|
|
5240
|
+
* - processAlertsApiResponse: Process API response into alerts map
|
|
5241
|
+
*
|
|
5242
|
+
* Alert Processing:
|
|
5243
|
+
* - Filters alerts based on socket.yml configuration
|
|
5244
|
+
* - Maps package URLs to security vulnerabilities
|
|
5245
|
+
* - Supports batch processing for performance
|
|
5246
|
+
*
|
|
5247
|
+
* Integration:
|
|
5248
|
+
* - Works with pnpm lockfiles for dependency scanning
|
|
5249
|
+
* - Uses Socket API for vulnerability data
|
|
5250
|
+
* - Respects filter configurations from socket.yml
|
|
5251
|
+
*/
|
|
5252
|
+
|
|
4589
5253
|
async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
4590
5254
|
const purls = await extractPurlsFromPnpmLockfile(lockfile);
|
|
4591
5255
|
return await getAlertsMapFromPurls(purls, {
|
|
@@ -4686,6 +5350,183 @@ async function getAlertsMapFromPurls(purls, options) {
|
|
|
4686
5350
|
return alertsByPurl;
|
|
4687
5351
|
}
|
|
4688
5352
|
|
|
5353
|
+
/**
|
|
5354
|
+
* npm package specification utilities for Socket CLI.
|
|
5355
|
+
* Parses and handles various npm package specification formats.
|
|
5356
|
+
*
|
|
5357
|
+
* Supported Formats:
|
|
5358
|
+
* - Regular packages: lodash, lodash@4.17.21
|
|
5359
|
+
* - Scoped packages: @types/node, @types/node@20.0.0
|
|
5360
|
+
* - Version ranges: lodash@^4.0.0, lodash@~4.17.0
|
|
5361
|
+
* - Git URLs: git+https://github.com/user/repo.git
|
|
5362
|
+
* - File paths: file:../local-package
|
|
5363
|
+
* - Aliases: my-alias@npm:real-package@1.0.0
|
|
5364
|
+
*
|
|
5365
|
+
* Key Functions:
|
|
5366
|
+
* - safeNpa: Safe wrapper for npm-package-arg
|
|
5367
|
+
* - safeNpmSpecToPurl: Convert npm spec to PURL
|
|
5368
|
+
* - safeParseNpmSpec: Parse npm spec to name/version
|
|
5369
|
+
*
|
|
5370
|
+
* Error Handling:
|
|
5371
|
+
* - Returns undefined for invalid specs
|
|
5372
|
+
* - Fallback parsing for edge cases
|
|
5373
|
+
* - Safe against malformed input
|
|
5374
|
+
*/
|
|
5375
|
+
|
|
5376
|
+
|
|
5377
|
+
// @ts-expect-error - Result is re-exported below.
|
|
5378
|
+
|
|
5379
|
+
/**
|
|
5380
|
+
* Safe wrapper for npm-package-arg that doesn't throw.
|
|
5381
|
+
* Returns undefined if parsing fails.
|
|
5382
|
+
*/
|
|
5383
|
+
function safeNpa(...args) {
|
|
5384
|
+
try {
|
|
5385
|
+
return Reflect.apply(vendor.npaExports, undefined, args);
|
|
5386
|
+
} catch {}
|
|
5387
|
+
return undefined;
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5390
|
+
/**
|
|
5391
|
+
* Parse npm package specification into name and version.
|
|
5392
|
+
* Uses npm-package-arg for proper handling of various spec formats:
|
|
5393
|
+
* - Regular packages: lodash, lodash@4.17.21
|
|
5394
|
+
* - Scoped packages: @types/node, @types/node@20.0.0
|
|
5395
|
+
* - Version ranges: lodash@^4.0.0
|
|
5396
|
+
* - Git URLs, file paths, etc.
|
|
5397
|
+
*
|
|
5398
|
+
* Returns undefined if parsing fails.
|
|
5399
|
+
*/
|
|
5400
|
+
function safeParseNpmSpec(pkgSpec) {
|
|
5401
|
+
// Use npm-package-arg for proper spec parsing.
|
|
5402
|
+
const parsed = safeNpa(pkgSpec);
|
|
5403
|
+
if (!parsed) {
|
|
5404
|
+
// Fallback to simple parsing if npm-package-arg fails.
|
|
5405
|
+
// Handle scoped packages first to avoid confusion with version delimiter.
|
|
5406
|
+
if (pkgSpec.startsWith('@')) {
|
|
5407
|
+
const scopedMatch = pkgSpec.match(/^(@[^/@]+\/[^/@]+)(?:@(.+))?$/);
|
|
5408
|
+
if (scopedMatch) {
|
|
5409
|
+
return {
|
|
5410
|
+
name: scopedMatch[1],
|
|
5411
|
+
version: scopedMatch[2]
|
|
5412
|
+
};
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5415
|
+
|
|
5416
|
+
// Handle regular packages.
|
|
5417
|
+
const atIndex = pkgSpec.indexOf('@');
|
|
5418
|
+
if (atIndex === -1) {
|
|
5419
|
+
return {
|
|
5420
|
+
name: pkgSpec,
|
|
5421
|
+
version: undefined
|
|
5422
|
+
};
|
|
5423
|
+
}
|
|
5424
|
+
return {
|
|
5425
|
+
name: pkgSpec.slice(0, atIndex),
|
|
5426
|
+
version: pkgSpec.slice(atIndex + 1)
|
|
5427
|
+
};
|
|
5428
|
+
}
|
|
5429
|
+
|
|
5430
|
+
// Extract name and version from parsed spec.
|
|
5431
|
+
const name = parsed.name || pkgSpec;
|
|
5432
|
+
let version;
|
|
5433
|
+
|
|
5434
|
+
// Handle different spec types from npm-package-arg.
|
|
5435
|
+
if (parsed.type === 'tag' || parsed.type === 'version' || parsed.type === 'range') {
|
|
5436
|
+
// For npm registry packages:
|
|
5437
|
+
// - type 'tag': latest, beta, etc.
|
|
5438
|
+
// - type 'version': exact version like 1.0.0
|
|
5439
|
+
// - type 'range': version range like ^1.0.0, ~1.0.0, or * for bare names
|
|
5440
|
+
// Don't include '*' as a version - it means "any version".
|
|
5441
|
+
if (parsed.fetchSpec && parsed.fetchSpec !== '*') {
|
|
5442
|
+
version = parsed.fetchSpec;
|
|
5443
|
+
} else if (parsed.rawSpec && parsed.rawSpec !== '*' && parsed.rawSpec !== parsed.name) {
|
|
5444
|
+
version = parsed.rawSpec;
|
|
5445
|
+
}
|
|
5446
|
+
} else if (parsed.type === 'git' || parsed.type === 'remote' || parsed.type === 'file') {
|
|
5447
|
+
// For non-registry specs, use rawSpec if different from name.
|
|
5448
|
+
if (parsed.rawSpec && parsed.rawSpec !== parsed.name) {
|
|
5449
|
+
version = parsed.rawSpec;
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
return {
|
|
5453
|
+
name,
|
|
5454
|
+
version
|
|
5455
|
+
};
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
/**
|
|
5459
|
+
* Convert npm package spec to PURL string.
|
|
5460
|
+
* Handles various npm spec formats and converts them to standardized PURLs.
|
|
5461
|
+
* Returns undefined if conversion fails.
|
|
5462
|
+
*/
|
|
5463
|
+
function safeNpmSpecToPurl(pkgSpec) {
|
|
5464
|
+
const parsed = safeParseNpmSpec(pkgSpec);
|
|
5465
|
+
if (!parsed) {
|
|
5466
|
+
return undefined;
|
|
5467
|
+
}
|
|
5468
|
+
const {
|
|
5469
|
+
name,
|
|
5470
|
+
version
|
|
5471
|
+
} = parsed;
|
|
5472
|
+
|
|
5473
|
+
// Create PURL object to ensure proper formatting.
|
|
5474
|
+
const purlObj = createPurlObject({
|
|
5475
|
+
type: constants.NPM,
|
|
5476
|
+
name,
|
|
5477
|
+
version,
|
|
5478
|
+
throws: false
|
|
5479
|
+
});
|
|
5480
|
+
return purlObj?.toString() ?? `pkg:${constants.NPM}/${name}${version ? `@${version}` : ''}`;
|
|
5481
|
+
}
|
|
5482
|
+
|
|
5483
|
+
/**
|
|
5484
|
+
* PNPM path resolution utilities for Socket CLI.
|
|
5485
|
+
* Locates and caches PNPM binary paths.
|
|
5486
|
+
*
|
|
5487
|
+
* Key Functions:
|
|
5488
|
+
* - getPnpmBinPath: Get cached PNPM binary path
|
|
5489
|
+
* - getPnpmBinPathDetails: Get detailed PNPM path information
|
|
5490
|
+
*
|
|
5491
|
+
* Error Handling:
|
|
5492
|
+
* - Exits with code 127 if PNPM not found
|
|
5493
|
+
* - Provides clear error messages for missing binaries
|
|
5494
|
+
*
|
|
5495
|
+
* Caching:
|
|
5496
|
+
* - Caches binary path lookups for performance
|
|
5497
|
+
* - Prevents repeated PATH searches
|
|
5498
|
+
*/
|
|
5499
|
+
|
|
5500
|
+
function exitWithBinPathError(binName) {
|
|
5501
|
+
logger.logger.fail(`Socket unable to locate ${binName}; ensure it is available in the PATH environment variable`);
|
|
5502
|
+
// The exit code 127 indicates that the command or binary being executed
|
|
5503
|
+
// could not be found.
|
|
5504
|
+
// eslint-disable-next-line n/no-process-exit
|
|
5505
|
+
process.exit(127);
|
|
5506
|
+
// This line is never reached in production, but helps tests.
|
|
5507
|
+
throw new Error('process.exit called');
|
|
5508
|
+
}
|
|
5509
|
+
let _pnpmBinPath;
|
|
5510
|
+
function getPnpmBinPath() {
|
|
5511
|
+
if (_pnpmBinPath === undefined) {
|
|
5512
|
+
_pnpmBinPath = getPnpmBinPathDetails().path;
|
|
5513
|
+
if (!_pnpmBinPath) {
|
|
5514
|
+
exitWithBinPathError('pnpm');
|
|
5515
|
+
}
|
|
5516
|
+
}
|
|
5517
|
+
return _pnpmBinPath;
|
|
5518
|
+
}
|
|
5519
|
+
let _pnpmBinPathDetails;
|
|
5520
|
+
function getPnpmBinPathDetails() {
|
|
5521
|
+
if (_pnpmBinPathDetails === undefined) {
|
|
5522
|
+
_pnpmBinPathDetails = findBinPathDetailsSync('pnpm');
|
|
5523
|
+
}
|
|
5524
|
+
return _pnpmBinPathDetails;
|
|
5525
|
+
}
|
|
5526
|
+
function isPnpmBinPathShadowed() {
|
|
5527
|
+
return getPnpmBinPathDetails().shadowed;
|
|
5528
|
+
}
|
|
5529
|
+
|
|
4689
5530
|
exports.AuthError = AuthError;
|
|
4690
5531
|
exports.COMPLETION_CMD_PREFIX = COMPLETION_CMD_PREFIX;
|
|
4691
5532
|
exports.InputError = InputError;
|
|
@@ -4699,6 +5540,8 @@ exports.cmdPrefixMessage = cmdPrefixMessage;
|
|
|
4699
5540
|
exports.convertCveToGhsa = convertCveToGhsa;
|
|
4700
5541
|
exports.convertPurlToGhsas = convertPurlToGhsas;
|
|
4701
5542
|
exports.createEnum = createEnum;
|
|
5543
|
+
exports.debugFileOp = debugFileOp;
|
|
5544
|
+
exports.debugScan = debugScan;
|
|
4702
5545
|
exports.detectAndValidatePackageEnvironment = detectAndValidatePackageEnvironment;
|
|
4703
5546
|
exports.detectDefaultBranch = detectDefaultBranch;
|
|
4704
5547
|
exports.determineOrgSlug = determineOrgSlug;
|
|
@@ -4709,6 +5552,7 @@ exports.fetchGhsaDetails = fetchGhsaDetails;
|
|
|
4709
5552
|
exports.fetchOrganization = fetchOrganization;
|
|
4710
5553
|
exports.filterFlags = filterFlags;
|
|
4711
5554
|
exports.findUp = findUp;
|
|
5555
|
+
exports.formatErrorWithDetail = formatErrorWithDetail;
|
|
4712
5556
|
exports.getAlertsMapFromPnpmLockfile = getAlertsMapFromPnpmLockfile;
|
|
4713
5557
|
exports.getAlertsMapFromPurls = getAlertsMapFromPurls;
|
|
4714
5558
|
exports.getBaseBranch = getBaseBranch;
|
|
@@ -4718,6 +5562,7 @@ exports.getConfigValueOrUndef = getConfigValueOrUndef;
|
|
|
4718
5562
|
exports.getDefaultOrgSlug = getDefaultOrgSlug;
|
|
4719
5563
|
exports.getEcosystemChoicesForMeow = getEcosystemChoicesForMeow;
|
|
4720
5564
|
exports.getEnterpriseOrgs = getEnterpriseOrgs;
|
|
5565
|
+
exports.getErrorCause = getErrorCause;
|
|
4721
5566
|
exports.getFlagApiRequirementsOutput = getFlagApiRequirementsOutput;
|
|
4722
5567
|
exports.getFlagListOutput = getFlagListOutput;
|
|
4723
5568
|
exports.getMajor = getMajor;
|
|
@@ -4773,7 +5618,6 @@ exports.meowOrExit = meowOrExit;
|
|
|
4773
5618
|
exports.meowWithSubcommands = meowWithSubcommands;
|
|
4774
5619
|
exports.msAtHome = msAtHome;
|
|
4775
5620
|
exports.normalizePurl = normalizePurl;
|
|
4776
|
-
exports.npa = npa;
|
|
4777
5621
|
exports.parsePnpmLockfile = parsePnpmLockfile;
|
|
4778
5622
|
exports.queryApiSafeJson = queryApiSafeJson;
|
|
4779
5623
|
exports.queryApiSafeText = queryApiSafeText;
|
|
@@ -4782,6 +5626,8 @@ exports.readOrDefaultSocketJsonUp = readOrDefaultSocketJsonUp;
|
|
|
4782
5626
|
exports.readPnpmLockfile = readPnpmLockfile;
|
|
4783
5627
|
exports.readSocketJsonSync = readSocketJsonSync;
|
|
4784
5628
|
exports.runAgentInstall = runAgentInstall;
|
|
5629
|
+
exports.safeNpa = safeNpa$1;
|
|
5630
|
+
exports.safeNpmSpecToPurl = safeNpmSpecToPurl;
|
|
4785
5631
|
exports.sendApiRequest = sendApiRequest;
|
|
4786
5632
|
exports.serializeResultJson = serializeResultJson;
|
|
4787
5633
|
exports.setGitRemoteGithubRepoUrl = setGitRemoteGithubRepoUrl;
|
|
@@ -4795,5 +5641,5 @@ exports.toFilterConfig = toFilterConfig;
|
|
|
4795
5641
|
exports.updateConfigValue = updateConfigValue;
|
|
4796
5642
|
exports.walkNestedMap = walkNestedMap;
|
|
4797
5643
|
exports.writeSocketJson = writeSocketJson;
|
|
4798
|
-
//# debugId=
|
|
5644
|
+
//# debugId=cf6fa269-bd5d-472d-ba3c-ad112752f863
|
|
4799
5645
|
//# sourceMappingURL=utils.js.map
|