@socketsecurity/cli 0.13.0 → 0.14.1
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/README.md +61 -28
- package/package.json +108 -110
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -4133
- package/dist/errors.d.ts +0 -7
- package/dist/link.d.ts +0 -2
- package/dist/link.js +0 -45
- package/dist/npm-cli.d.ts +0 -2
- package/dist/npm-cli.js +0 -84
- package/dist/npm-injection.d.ts +0 -1
- package/dist/npm-injection.js +0 -913
- package/dist/npm-injection2.d.ts +0 -25
- package/dist/npm-injection2.js +0 -899
- package/dist/npx-cli.d.ts +0 -2
- package/dist/npx-cli.js +0 -60
- package/dist/path-resolve.d.ts +0 -12
- package/dist/path-resolve.js +0 -139
- package/dist/sdk.d.ts +0 -27
- package/dist/sdk.js +0 -224
- package/dist/settings.d.ts +0 -9
- package/dist/type-helpers.d.ts +0 -3
- package/dist/vendor.js +0 -25395
package/dist/npm-injection2.js
DELETED
|
@@ -1,899 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var vendor = require('./vendor.js');
|
|
4
|
-
var require$$0$3 = require('node:events');
|
|
5
|
-
var require$$0$1 = require('node:fs');
|
|
6
|
-
var require$$4 = require('node:https');
|
|
7
|
-
var require$$1 = require('node:path');
|
|
8
|
-
var require$$3 = require('node:readline');
|
|
9
|
-
var require$$0$2 = require('node:stream');
|
|
10
|
-
var require$$0$4 = require('node:timers/promises');
|
|
11
|
-
var require$$3$1 = require('@socketsecurity/config');
|
|
12
|
-
var link = require('./link.js');
|
|
13
|
-
var require$$1$1 = require('node:net');
|
|
14
|
-
var require$$0 = require('node:os');
|
|
15
|
-
var require$$6 = require('../package.json');
|
|
16
|
-
var sdk = require('./sdk.js');
|
|
17
|
-
var require$$20 = require('pacote');
|
|
18
|
-
|
|
19
|
-
var npmInjection = {};
|
|
20
|
-
|
|
21
|
-
var ttyServer$1 = {};
|
|
22
|
-
|
|
23
|
-
var typeHelpers = {};
|
|
24
|
-
|
|
25
|
-
Object.defineProperty(typeHelpers, "__esModule", {
|
|
26
|
-
value: true
|
|
27
|
-
});
|
|
28
|
-
typeHelpers.isErrnoException = isErrnoException;
|
|
29
|
-
function isErrnoException(value) {
|
|
30
|
-
if (!(value instanceof Error)) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return value.code !== undefined;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
Object.defineProperty(ttyServer$1, "__esModule", {
|
|
37
|
-
value: true
|
|
38
|
-
});
|
|
39
|
-
ttyServer$1.createTTYServer = createTTYServer;
|
|
40
|
-
var _nodeFs$1 = require$$0$1;
|
|
41
|
-
var _nodeNet = require$$1$1;
|
|
42
|
-
var _nodeOs = require$$0;
|
|
43
|
-
var _nodePath$1 = require$$1;
|
|
44
|
-
var _nodeReadline$1 = require$$3;
|
|
45
|
-
var _nodeStream$1 = require$$0$2;
|
|
46
|
-
var _package = require$$6;
|
|
47
|
-
var _typeHelpers$1 = typeHelpers;
|
|
48
|
-
const NEWLINE_CHAR_CODE = 10; /*'\n'*/
|
|
49
|
-
|
|
50
|
-
const TTY_IPC = process.env['SOCKET_SECURITY_TTY_IPC'];
|
|
51
|
-
const sock = _nodePath$1.join(_nodeOs.tmpdir(), `socket-security-tty-${process.pid}.sock`);
|
|
52
|
-
process.env['SOCKET_SECURITY_TTY_IPC'] = sock;
|
|
53
|
-
function createNonStandardTTYServer() {
|
|
54
|
-
return {
|
|
55
|
-
async captureTTY(mutexFn) {
|
|
56
|
-
return await new Promise((resolve, reject) => {
|
|
57
|
-
const conn = _nodeNet.createConnection({
|
|
58
|
-
path: TTY_IPC
|
|
59
|
-
}).on('error', reject);
|
|
60
|
-
let captured = false;
|
|
61
|
-
const buffs = [];
|
|
62
|
-
conn.on('data', function awaitCapture(chunk) {
|
|
63
|
-
buffs.push(chunk);
|
|
64
|
-
let lineBuff = Buffer.concat(buffs);
|
|
65
|
-
if (captured) return;
|
|
66
|
-
try {
|
|
67
|
-
const eolIndex = lineBuff.indexOf(NEWLINE_CHAR_CODE);
|
|
68
|
-
if (eolIndex !== -1) {
|
|
69
|
-
conn.removeListener('data', awaitCapture);
|
|
70
|
-
conn.push(lineBuff.slice(eolIndex + 1));
|
|
71
|
-
const {
|
|
72
|
-
ipc_version: remote_ipc_version,
|
|
73
|
-
capabilities: {
|
|
74
|
-
input: hasInput,
|
|
75
|
-
output: hasOutput,
|
|
76
|
-
colorLevel: ipcColorLevel
|
|
77
|
-
}
|
|
78
|
-
} = JSON.parse(lineBuff.slice(0, eolIndex).toString('utf-8'));
|
|
79
|
-
lineBuff = null;
|
|
80
|
-
captured = true;
|
|
81
|
-
if (remote_ipc_version !== _package.version) {
|
|
82
|
-
throw new Error('Mismatched STDIO tunnel IPC version, ensure you only have 1 version of socket CLI being called.');
|
|
83
|
-
}
|
|
84
|
-
const input = hasInput ? new _nodeStream$1.PassThrough() : null;
|
|
85
|
-
input?.pause();
|
|
86
|
-
if (input) conn.pipe(input);
|
|
87
|
-
const output = hasOutput ? new _nodeStream$1.PassThrough() : null;
|
|
88
|
-
if (output) {
|
|
89
|
-
output.pipe(conn)
|
|
90
|
-
// Make ora happy
|
|
91
|
-
;
|
|
92
|
-
output.isTTY = true;
|
|
93
|
-
output.cursorTo = function cursorTo(x, y, callback) {
|
|
94
|
-
_nodeReadline$1.cursorTo(this, x, y, callback);
|
|
95
|
-
};
|
|
96
|
-
output.clearLine = function clearLine(dir, callback) {
|
|
97
|
-
_nodeReadline$1.clearLine(this, dir, callback);
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
mutexFn(ipcColorLevel, hasInput ? input : undefined, hasOutput ? output : undefined).then(resolve, reject).finally(() => {
|
|
101
|
-
conn.unref();
|
|
102
|
-
conn.end();
|
|
103
|
-
input?.end();
|
|
104
|
-
output?.end();
|
|
105
|
-
// process.exit(13)
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
} catch (e) {
|
|
109
|
-
reject(e);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
function createIPCServer(colorLevel, captureState,
|
|
117
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
118
|
-
npmlog) {
|
|
119
|
-
const input = process.stdin;
|
|
120
|
-
const output = process.stderr;
|
|
121
|
-
return new Promise((resolve, reject) => {
|
|
122
|
-
const server = _nodeNet
|
|
123
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
124
|
-
.createServer(async conn => {
|
|
125
|
-
if (captureState.captured) {
|
|
126
|
-
await new Promise(resolve => {
|
|
127
|
-
captureState.pendingCaptures.push({
|
|
128
|
-
resolve() {
|
|
129
|
-
resolve();
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
} else {
|
|
134
|
-
captureState.captured = true;
|
|
135
|
-
}
|
|
136
|
-
const wasProgressEnabled = npmlog.progressEnabled;
|
|
137
|
-
npmlog.pause();
|
|
138
|
-
if (wasProgressEnabled) {
|
|
139
|
-
npmlog.disableProgress();
|
|
140
|
-
}
|
|
141
|
-
conn.write(`${JSON.stringify({
|
|
142
|
-
ipc_version: _package.version,
|
|
143
|
-
capabilities: {
|
|
144
|
-
input: Boolean(input),
|
|
145
|
-
output: true,
|
|
146
|
-
colorLevel
|
|
147
|
-
}
|
|
148
|
-
})}\n`);
|
|
149
|
-
conn.on('data', data => {
|
|
150
|
-
output.write(data);
|
|
151
|
-
}).on('error', e => {
|
|
152
|
-
output.write(`there was an error prompting from a sub shell (${e?.message}), socket npm closing`);
|
|
153
|
-
process.exit(1);
|
|
154
|
-
});
|
|
155
|
-
input.on('data', data => {
|
|
156
|
-
conn.write(data);
|
|
157
|
-
}).on('end', () => {
|
|
158
|
-
conn.unref();
|
|
159
|
-
conn.end();
|
|
160
|
-
if (wasProgressEnabled) {
|
|
161
|
-
npmlog.enableProgress();
|
|
162
|
-
}
|
|
163
|
-
npmlog.resume();
|
|
164
|
-
captureState.nextCapture();
|
|
165
|
-
});
|
|
166
|
-
}).listen(sock, () => resolve(server)).on('error', reject).unref();
|
|
167
|
-
process.on('exit', () => {
|
|
168
|
-
server.close();
|
|
169
|
-
tryUnlinkSync(sock);
|
|
170
|
-
});
|
|
171
|
-
resolve(server);
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
function createStandardTTYServer(colorLevel, isInteractive,
|
|
175
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
176
|
-
npmlog) {
|
|
177
|
-
const captureState = {
|
|
178
|
-
captured: false,
|
|
179
|
-
nextCapture: () => {
|
|
180
|
-
if (captureState.pendingCaptures.length > 0) {
|
|
181
|
-
const pendingCapture = captureState.pendingCaptures.shift();
|
|
182
|
-
pendingCapture?.resolve();
|
|
183
|
-
} else {
|
|
184
|
-
captureState.captured = false;
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
pendingCaptures: []
|
|
188
|
-
};
|
|
189
|
-
tryUnlinkSync(sock);
|
|
190
|
-
const input = isInteractive ? process.stdin : undefined;
|
|
191
|
-
const output = process.stderr;
|
|
192
|
-
let ipcServerPromise;
|
|
193
|
-
if (input) {
|
|
194
|
-
ipcServerPromise = createIPCServer(colorLevel, captureState, npmlog);
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
async captureTTY(mutexFn) {
|
|
198
|
-
await ipcServerPromise;
|
|
199
|
-
if (captureState.captured) {
|
|
200
|
-
const captured = new Promise(resolve => {
|
|
201
|
-
captureState.pendingCaptures.push({
|
|
202
|
-
resolve() {
|
|
203
|
-
resolve();
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
await captured;
|
|
208
|
-
} else {
|
|
209
|
-
captureState.captured = true;
|
|
210
|
-
}
|
|
211
|
-
const wasProgressEnabled = npmlog.progressEnabled;
|
|
212
|
-
try {
|
|
213
|
-
npmlog.pause();
|
|
214
|
-
if (wasProgressEnabled) {
|
|
215
|
-
npmlog.disableProgress();
|
|
216
|
-
}
|
|
217
|
-
return await mutexFn(colorLevel, input, output);
|
|
218
|
-
} finally {
|
|
219
|
-
if (wasProgressEnabled) {
|
|
220
|
-
npmlog.enableProgress();
|
|
221
|
-
}
|
|
222
|
-
npmlog.resume();
|
|
223
|
-
captureState.nextCapture();
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
function tryUnlinkSync(filepath) {
|
|
229
|
-
try {
|
|
230
|
-
(0, _nodeFs$1.unlinkSync)(filepath);
|
|
231
|
-
} catch (e) {
|
|
232
|
-
if ((0, _typeHelpers$1.isErrnoException)(e) && e.code !== 'ENOENT') {
|
|
233
|
-
throw e;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
function createTTYServer(colorLevel, isInteractive, npmlog) {
|
|
238
|
-
return !isInteractive && TTY_IPC ? createNonStandardTTYServer() : createStandardTTYServer(colorLevel, isInteractive, npmlog);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
var issueRules = {};
|
|
242
|
-
|
|
243
|
-
Object.defineProperty(issueRules, "__esModule", {
|
|
244
|
-
value: true
|
|
245
|
-
});
|
|
246
|
-
issueRules.createIssueUXLookup = createIssueUXLookup;
|
|
247
|
-
//#region UX Constants
|
|
248
|
-
|
|
249
|
-
const IGNORE_UX = {
|
|
250
|
-
block: false,
|
|
251
|
-
display: false
|
|
252
|
-
};
|
|
253
|
-
const WARN_UX = {
|
|
254
|
-
block: false,
|
|
255
|
-
display: true
|
|
256
|
-
};
|
|
257
|
-
const ERROR_UX = {
|
|
258
|
-
block: true,
|
|
259
|
-
display: true
|
|
260
|
-
};
|
|
261
|
-
//#endregion
|
|
262
|
-
//#region utils
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Iterates over all entries with ordered issue rule for deferral
|
|
266
|
-
* Iterates over all issue rules and finds the first defined value that does not defer otherwise uses the defaultValue
|
|
267
|
-
* Takes the value and converts into a UX workflow
|
|
268
|
-
*
|
|
269
|
-
* @param {Iterable<Iterable<NonNormalizedIssueRule>>} entriesOrderedIssueRules
|
|
270
|
-
* @param {NonNormalizedResolvedIssueRule} defaultValue
|
|
271
|
-
* @returns {RuleActionUX}
|
|
272
|
-
*/
|
|
273
|
-
function resolveIssueRuleUX(entriesOrderedIssueRules, defaultValue) {
|
|
274
|
-
if (defaultValue === true || defaultValue == null) {
|
|
275
|
-
defaultValue = {
|
|
276
|
-
action: 'error'
|
|
277
|
-
};
|
|
278
|
-
} else if (defaultValue === false) {
|
|
279
|
-
defaultValue = {
|
|
280
|
-
action: 'ignore'
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
let block = false;
|
|
284
|
-
let display = false;
|
|
285
|
-
let needDefault = true;
|
|
286
|
-
iterate_entries: for (const issueRuleArr of entriesOrderedIssueRules) {
|
|
287
|
-
for (const rule of issueRuleArr) {
|
|
288
|
-
if (issueRuleValueDoesNotDefer(rule)) {
|
|
289
|
-
needDefault = false;
|
|
290
|
-
const narrowingFilter = uxForDefinedNonDeferValue(rule);
|
|
291
|
-
block = block || narrowingFilter.block;
|
|
292
|
-
display = display || narrowingFilter.display;
|
|
293
|
-
continue iterate_entries;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
297
|
-
block = block || narrowingFilter.block;
|
|
298
|
-
display = display || narrowingFilter.display;
|
|
299
|
-
}
|
|
300
|
-
if (needDefault) {
|
|
301
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
302
|
-
block = block || narrowingFilter.block;
|
|
303
|
-
display = display || narrowingFilter.display;
|
|
304
|
-
}
|
|
305
|
-
return {
|
|
306
|
-
block,
|
|
307
|
-
display
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Negative form because it is narrowing the type
|
|
313
|
-
*/
|
|
314
|
-
function issueRuleValueDoesNotDefer(issueRule) {
|
|
315
|
-
if (issueRule === undefined) {
|
|
316
|
-
return false;
|
|
317
|
-
} else if (typeof issueRule === 'object' && issueRule) {
|
|
318
|
-
const {
|
|
319
|
-
action
|
|
320
|
-
} = issueRule;
|
|
321
|
-
if (action === undefined || action === 'defer') {
|
|
322
|
-
return false;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Handles booleans for backwards compatibility
|
|
330
|
-
|
|
331
|
-
*/
|
|
332
|
-
function uxForDefinedNonDeferValue(issueRuleValue) {
|
|
333
|
-
if (typeof issueRuleValue === 'boolean') {
|
|
334
|
-
return issueRuleValue ? ERROR_UX : IGNORE_UX;
|
|
335
|
-
}
|
|
336
|
-
const {
|
|
337
|
-
action
|
|
338
|
-
} = issueRuleValue;
|
|
339
|
-
if (action === 'warn') {
|
|
340
|
-
return WARN_UX;
|
|
341
|
-
} else if (action === 'ignore') {
|
|
342
|
-
return IGNORE_UX;
|
|
343
|
-
}
|
|
344
|
-
return ERROR_UX;
|
|
345
|
-
}
|
|
346
|
-
//#endregion
|
|
347
|
-
|
|
348
|
-
//#region exports
|
|
349
|
-
|
|
350
|
-
function createIssueUXLookup(settings) {
|
|
351
|
-
const cachedUX = new Map();
|
|
352
|
-
return context => {
|
|
353
|
-
const key = context.issue.type;
|
|
354
|
-
let ux = cachedUX.get(key);
|
|
355
|
-
if (ux) {
|
|
356
|
-
return ux;
|
|
357
|
-
}
|
|
358
|
-
const entriesOrderedIssueRules = [];
|
|
359
|
-
for (const settingsEntry of settings.entries) {
|
|
360
|
-
const orderedIssueRules = [];
|
|
361
|
-
let target = settingsEntry.start;
|
|
362
|
-
while (target !== null) {
|
|
363
|
-
const resolvedTarget = settingsEntry.settings[target];
|
|
364
|
-
if (!resolvedTarget) {
|
|
365
|
-
break;
|
|
366
|
-
}
|
|
367
|
-
const issueRuleValue = resolvedTarget.issueRules?.[key];
|
|
368
|
-
if (typeof issueRuleValue !== 'undefined') {
|
|
369
|
-
orderedIssueRules.push(issueRuleValue);
|
|
370
|
-
}
|
|
371
|
-
target = resolvedTarget.deferTo ?? null;
|
|
372
|
-
}
|
|
373
|
-
entriesOrderedIssueRules.push(orderedIssueRules);
|
|
374
|
-
}
|
|
375
|
-
const defaultValue = settings.defaults.issueRules[key];
|
|
376
|
-
let resolvedDefaultValue = {
|
|
377
|
-
action: 'error'
|
|
378
|
-
};
|
|
379
|
-
if (defaultValue === false) {
|
|
380
|
-
resolvedDefaultValue = {
|
|
381
|
-
action: 'ignore'
|
|
382
|
-
};
|
|
383
|
-
} else if (defaultValue && defaultValue !== true) {
|
|
384
|
-
resolvedDefaultValue = {
|
|
385
|
-
action: defaultValue.action ?? 'error'
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
ux = resolveIssueRuleUX(entriesOrderedIssueRules, resolvedDefaultValue);
|
|
389
|
-
cachedUX.set(key, ux);
|
|
390
|
-
return ux;
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
var _interopRequireWildcard = vendor.interopRequireWildcard.default;
|
|
395
|
-
var _interopRequireDefault = vendor.interopRequireDefault.default;
|
|
396
|
-
Object.defineProperty(npmInjection, "__esModule", {
|
|
397
|
-
value: true
|
|
398
|
-
});
|
|
399
|
-
npmInjection.findRoot = findRoot;
|
|
400
|
-
var _nodeEvents = require$$0$3;
|
|
401
|
-
var _nodeFs = require$$0$1;
|
|
402
|
-
var _nodeHttps = require$$4;
|
|
403
|
-
var _nodePath = require$$1;
|
|
404
|
-
var _nodeReadline = require$$3;
|
|
405
|
-
var _nodeStream = require$$0$2;
|
|
406
|
-
var _promises = require$$0$4;
|
|
407
|
-
var _config = require$$3$1;
|
|
408
|
-
var _chalk = _interopRequireDefault(vendor.source);
|
|
409
|
-
var _isInteractive = _interopRequireDefault(vendor.isInteractive);
|
|
410
|
-
var _ora = _interopRequireWildcard(vendor.ora);
|
|
411
|
-
var _link = link.link;
|
|
412
|
-
var _ttyServer = ttyServer$1;
|
|
413
|
-
var _chalkMarkdown = sdk.chalkMarkdown;
|
|
414
|
-
var _issueRules = issueRules;
|
|
415
|
-
var _sdk = sdk.sdk;
|
|
416
|
-
var _settings = sdk.settings;
|
|
417
|
-
var _typeHelpers = typeHelpers;
|
|
418
|
-
const LOOP_SENTINEL = 1_000_000;
|
|
419
|
-
const distPath = __dirname;
|
|
420
|
-
const rootPath = _nodePath.resolve(distPath, '..');
|
|
421
|
-
const binPath = _nodePath.join(rootPath, 'bin');
|
|
422
|
-
const npmEntrypoint = (0, _nodeFs.realpathSync)(`${process.argv[1]}`);
|
|
423
|
-
const npmRootPath = findRoot(_nodePath.dirname(npmEntrypoint));
|
|
424
|
-
const POTENTIALLY_BUG_ERROR_SNIPPET = 'this is potentially a bug with socket-npm caused by changes to the npm cli';
|
|
425
|
-
const abortController = new AbortController();
|
|
426
|
-
const {
|
|
427
|
-
signal: abortSignal
|
|
428
|
-
} = abortController;
|
|
429
|
-
const translations = require(_nodePath.join(rootPath, 'translations.json'));
|
|
430
|
-
if (npmRootPath === undefined) {
|
|
431
|
-
console.error(`Unable to find npm cli install directory, ${POTENTIALLY_BUG_ERROR_SNIPPET}.`);
|
|
432
|
-
console.error(`Searched parent directories of ${npmEntrypoint}`);
|
|
433
|
-
process.exit(127);
|
|
434
|
-
}
|
|
435
|
-
const npmDepPath = _nodePath.join(npmRootPath, 'node_modules');
|
|
436
|
-
const arboristClassPath = _nodePath.join(npmDepPath, '@npmcli/arborist/lib/arborist/index.js');
|
|
437
|
-
const Arborist = require(arboristClassPath);
|
|
438
|
-
|
|
439
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
440
|
-
let tarball;
|
|
441
|
-
try {
|
|
442
|
-
tarball = require(_nodePath.join(npmDepPath, 'pacote')).tarball;
|
|
443
|
-
} catch {
|
|
444
|
-
tarball = require$$20.tarball;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
448
|
-
let npmlog;
|
|
449
|
-
try {
|
|
450
|
-
npmlog = require(_nodePath.join(npmDepPath, 'proc-log/lib/index.js')).log;
|
|
451
|
-
} catch {}
|
|
452
|
-
if (npmlog === undefined) {
|
|
453
|
-
try {
|
|
454
|
-
npmlog = require(_nodePath.join(npmDepPath, 'npmlog/lib/log.js'));
|
|
455
|
-
} catch {}
|
|
456
|
-
}
|
|
457
|
-
if (npmlog === undefined) {
|
|
458
|
-
console.error(`Unable to integrate with npm cli logging infrastructure, ${POTENTIALLY_BUG_ERROR_SNIPPET}.`);
|
|
459
|
-
process.exit(127);
|
|
460
|
-
}
|
|
461
|
-
const kCtorArgs = Symbol('ctorArgs');
|
|
462
|
-
const kRiskyReify = Symbol('riskyReify');
|
|
463
|
-
const formatter = new _chalkMarkdown.ChalkOrMarkdown(false);
|
|
464
|
-
const pubToken = (0, _sdk.getDefaultKey)() ?? _sdk.FREE_API_KEY;
|
|
465
|
-
const ttyServer = (0, _ttyServer.createTTYServer)(_chalk.default.level, (0, _isInteractive.default)({
|
|
466
|
-
stream: process.stdin
|
|
467
|
-
}), npmlog);
|
|
468
|
-
let _uxLookup;
|
|
469
|
-
async function uxLookup(settings) {
|
|
470
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
471
|
-
while (_uxLookup === undefined) {
|
|
472
|
-
await (0, _promises.setTimeout)(1, {
|
|
473
|
-
signal: abortSignal
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
return _uxLookup(settings);
|
|
477
|
-
}
|
|
478
|
-
async function* batchScan(pkgIds) {
|
|
479
|
-
const query = {
|
|
480
|
-
packages: pkgIds.map(pkgid => {
|
|
481
|
-
const {
|
|
482
|
-
name,
|
|
483
|
-
version
|
|
484
|
-
} = pkgidParts(pkgid);
|
|
485
|
-
return {
|
|
486
|
-
eco: 'npm',
|
|
487
|
-
pkg: name,
|
|
488
|
-
ver: version,
|
|
489
|
-
top: true
|
|
490
|
-
};
|
|
491
|
-
})
|
|
492
|
-
};
|
|
493
|
-
// TODO: migrate to SDK
|
|
494
|
-
const pkgDataReq = _nodeHttps.request('https://api.socket.dev/v0/scan/batch', {
|
|
495
|
-
method: 'POST',
|
|
496
|
-
headers: {
|
|
497
|
-
Authorization: `Basic ${Buffer.from(`${pubToken}:`).toString('base64url')}`
|
|
498
|
-
},
|
|
499
|
-
signal: abortSignal
|
|
500
|
-
}).end(JSON.stringify(query));
|
|
501
|
-
const {
|
|
502
|
-
0: res
|
|
503
|
-
} = await _nodeEvents.once(pkgDataReq, 'response');
|
|
504
|
-
const ok = res.statusCode >= 200 && res.statusCode <= 299;
|
|
505
|
-
if (!ok) {
|
|
506
|
-
throw new Error(`Socket API Error: ${res.statusCode}`);
|
|
507
|
-
}
|
|
508
|
-
const rli = _nodeReadline.createInterface(res);
|
|
509
|
-
for await (const line of rli) {
|
|
510
|
-
yield JSON.parse(line);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
function findRoot(filepath) {
|
|
514
|
-
let curPath = filepath;
|
|
515
|
-
while (true) {
|
|
516
|
-
if (_nodePath.basename(curPath) === 'npm') {
|
|
517
|
-
return curPath;
|
|
518
|
-
}
|
|
519
|
-
const parent = _nodePath.dirname(curPath);
|
|
520
|
-
if (parent === curPath) {
|
|
521
|
-
return undefined;
|
|
522
|
-
}
|
|
523
|
-
curPath = parent;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
function findSocketYML() {
|
|
527
|
-
let prevDir = null;
|
|
528
|
-
let dir = process.cwd();
|
|
529
|
-
while (dir !== prevDir) {
|
|
530
|
-
let ymlPath = _nodePath.join(dir, 'socket.yml');
|
|
531
|
-
let yml = maybeReadfileSync(ymlPath);
|
|
532
|
-
if (yml === undefined) {
|
|
533
|
-
ymlPath = _nodePath.join(dir, 'socket.yaml');
|
|
534
|
-
yml = maybeReadfileSync(ymlPath);
|
|
535
|
-
}
|
|
536
|
-
if (typeof yml === 'string') {
|
|
537
|
-
try {
|
|
538
|
-
return {
|
|
539
|
-
path: ymlPath,
|
|
540
|
-
parsed: _config.parseSocketConfig(yml)
|
|
541
|
-
};
|
|
542
|
-
} catch {
|
|
543
|
-
throw new Error(`Found file but was unable to parse ${ymlPath}`);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
prevDir = dir;
|
|
547
|
-
dir = _nodePath.join(dir, '..');
|
|
548
|
-
}
|
|
549
|
-
return null;
|
|
550
|
-
}
|
|
551
|
-
function maybeReadfileSync(filepath) {
|
|
552
|
-
try {
|
|
553
|
-
return (0, _nodeFs.existsSync)(filepath) ? (0, _nodeFs.readFileSync)(filepath, 'utf8') : undefined;
|
|
554
|
-
} catch {}
|
|
555
|
-
return undefined;
|
|
556
|
-
}
|
|
557
|
-
async function packagesHaveRiskyIssues(safeArb, _registry, pkgs, output) {
|
|
558
|
-
let result = false;
|
|
559
|
-
let remaining = pkgs.length;
|
|
560
|
-
if (!remaining) {
|
|
561
|
-
(0, _ora.default)('').succeed('No changes detected');
|
|
562
|
-
return result;
|
|
563
|
-
}
|
|
564
|
-
const getText = () => `Looking up data for ${remaining} packages`;
|
|
565
|
-
const spinner = (0, _ora.default)({
|
|
566
|
-
color: 'cyan',
|
|
567
|
-
stream: output,
|
|
568
|
-
isEnabled: true,
|
|
569
|
-
isSilent: false,
|
|
570
|
-
hideCursor: true,
|
|
571
|
-
discardStdin: true,
|
|
572
|
-
spinner: _ora.spinners.dots
|
|
573
|
-
}).start(getText());
|
|
574
|
-
try {
|
|
575
|
-
for await (const pkgData of batchScan(pkgs.map(pkg => pkg.pkgid))) {
|
|
576
|
-
let failures = [];
|
|
577
|
-
let displayWarning = false;
|
|
578
|
-
const name = pkgData.pkg;
|
|
579
|
-
const version = pkgData.ver;
|
|
580
|
-
const id = `${name}@${version}`;
|
|
581
|
-
if (pkgData.type === 'missing') {
|
|
582
|
-
result = true;
|
|
583
|
-
failures.push({
|
|
584
|
-
type: 'missingDependency'
|
|
585
|
-
});
|
|
586
|
-
} else {
|
|
587
|
-
let blocked = false;
|
|
588
|
-
for (const failure of pkgData.value.issues) {
|
|
589
|
-
const ux = await uxLookup({
|
|
590
|
-
package: {
|
|
591
|
-
name,
|
|
592
|
-
version
|
|
593
|
-
},
|
|
594
|
-
issue: {
|
|
595
|
-
type: failure.type
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
if (ux.display || ux.block) {
|
|
599
|
-
failures.push({
|
|
600
|
-
raw: failure,
|
|
601
|
-
block: ux.block
|
|
602
|
-
});
|
|
603
|
-
// before we ask about problematic issues, check to see if they
|
|
604
|
-
// already existed in the old version if they did, be quiet
|
|
605
|
-
const pkg = pkgs.find(pkg => pkg.pkgid === id && pkg.existing?.startsWith(`${name}@`));
|
|
606
|
-
if (pkg?.existing) {
|
|
607
|
-
for await (const oldPkgData of batchScan([pkg.existing])) {
|
|
608
|
-
if (oldPkgData.type === 'success') {
|
|
609
|
-
failures = failures.filter(issue => oldPkgData.value.issues.find(oldIssue => oldIssue.type === issue.raw.type) == null);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
if (ux.block) {
|
|
615
|
-
result = true;
|
|
616
|
-
blocked = true;
|
|
617
|
-
}
|
|
618
|
-
if (ux.display) {
|
|
619
|
-
displayWarning = true;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
if (!blocked) {
|
|
623
|
-
const pkg = pkgs.find(pkg => pkg.pkgid === id);
|
|
624
|
-
if (pkg) {
|
|
625
|
-
await tarball.stream(id, stream => {
|
|
626
|
-
stream.resume();
|
|
627
|
-
return stream.promise();
|
|
628
|
-
}, {
|
|
629
|
-
...safeArb[kCtorArgs][0]
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
if (displayWarning) {
|
|
635
|
-
spinner.stop();
|
|
636
|
-
output?.write(`(socket) ${formatter.hyperlink(id, `https://socket.dev/npm/package/${name}/overview/${version}`)} contains risks:\n`);
|
|
637
|
-
failures.sort((a, b) => a.raw.type < b.raw.type ? -1 : 1);
|
|
638
|
-
const lines = new Set();
|
|
639
|
-
for (const failure of failures) {
|
|
640
|
-
const type = failure.raw.type;
|
|
641
|
-
if (type) {
|
|
642
|
-
const issueTypeTranslation = translations.issues[type];
|
|
643
|
-
// TODO: emoji seems to mis-align terminals sometimes
|
|
644
|
-
lines.add(` ${issueTypeTranslation?.title ?? type}${failure.block ? '' : ' (non-blocking)'} - ${issueTypeTranslation?.description ?? ''}\n`);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
for (const line of lines) {
|
|
648
|
-
output?.write(line);
|
|
649
|
-
}
|
|
650
|
-
spinner.start();
|
|
651
|
-
}
|
|
652
|
-
remaining--;
|
|
653
|
-
spinner.text = remaining > 0 ? getText() : '';
|
|
654
|
-
}
|
|
655
|
-
return result;
|
|
656
|
-
} finally {
|
|
657
|
-
if (spinner.isSpinning) {
|
|
658
|
-
spinner.stop();
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
function pkgidParts(pkgid) {
|
|
663
|
-
const delimiter = pkgid.lastIndexOf('@');
|
|
664
|
-
const name = pkgid.slice(0, delimiter);
|
|
665
|
-
const version = pkgid.slice(delimiter + 1);
|
|
666
|
-
return {
|
|
667
|
-
name,
|
|
668
|
-
version
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
function toPURL(pkgid, resolved) {
|
|
672
|
-
const repo = resolved.replace(/#[\s\S]*$/u, '').replace(/\?[\s\S]*$/u, '').replace(/\/[^/]*\/-\/[\s\S]*$/u, '');
|
|
673
|
-
const {
|
|
674
|
-
name,
|
|
675
|
-
version
|
|
676
|
-
} = pkgidParts(pkgid);
|
|
677
|
-
return {
|
|
678
|
-
type: 'npm',
|
|
679
|
-
namespace_and_name: name,
|
|
680
|
-
version,
|
|
681
|
-
repository_url: repo
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
function walk(diff_, needInfoOn = []) {
|
|
685
|
-
const queue = [diff_];
|
|
686
|
-
let pos = 0;
|
|
687
|
-
let {
|
|
688
|
-
length: queueLength
|
|
689
|
-
} = queue;
|
|
690
|
-
while (pos < queueLength) {
|
|
691
|
-
if (pos === LOOP_SENTINEL) {
|
|
692
|
-
throw new Error('Detected infinite loop while walking Arborist diff');
|
|
693
|
-
}
|
|
694
|
-
const diff = queue[pos++];
|
|
695
|
-
if (!diff) {
|
|
696
|
-
continue;
|
|
697
|
-
}
|
|
698
|
-
if (diff.action) {
|
|
699
|
-
const sameVersion = diff.actual?.package.version === diff.ideal?.package.version;
|
|
700
|
-
let keep = false;
|
|
701
|
-
let existing = null;
|
|
702
|
-
if (diff.action === 'CHANGE') {
|
|
703
|
-
if (!sameVersion) {
|
|
704
|
-
existing = diff.actual.pkgid;
|
|
705
|
-
keep = true;
|
|
706
|
-
}
|
|
707
|
-
} else {
|
|
708
|
-
keep = diff.action !== 'REMOVE';
|
|
709
|
-
}
|
|
710
|
-
if (keep && diff.ideal?.pkgid && diff.ideal.resolved && (!diff.actual || diff.actual.resolved)) {
|
|
711
|
-
needInfoOn.push({
|
|
712
|
-
existing,
|
|
713
|
-
action: diff.action,
|
|
714
|
-
location: diff.ideal.location,
|
|
715
|
-
pkgid: diff.ideal.pkgid,
|
|
716
|
-
newPackage: toPURL(diff.ideal.pkgid, diff.ideal.resolved),
|
|
717
|
-
oldPackage: diff.actual && diff.actual.resolved ? toPURL(diff.actual.pkgid, diff.actual.resolved) : null,
|
|
718
|
-
resolved: diff.ideal.resolved
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
if (diff.children) {
|
|
723
|
-
for (const child of diff.children) {
|
|
724
|
-
queue[queueLength++] = child;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
return needInfoOn;
|
|
729
|
-
}
|
|
730
|
-
class SafeArborist extends Arborist {
|
|
731
|
-
constructor(...ctorArgs) {
|
|
732
|
-
const mutedArguments = [{
|
|
733
|
-
...(ctorArgs[0] ?? {}),
|
|
734
|
-
audit: true,
|
|
735
|
-
dryRun: true,
|
|
736
|
-
ignoreScripts: true,
|
|
737
|
-
save: false,
|
|
738
|
-
saveBundle: false,
|
|
739
|
-
// progress: false,
|
|
740
|
-
fund: false
|
|
741
|
-
}, ctorArgs.slice(1)];
|
|
742
|
-
super(...mutedArguments);
|
|
743
|
-
this[kCtorArgs] = ctorArgs;
|
|
744
|
-
}
|
|
745
|
-
async [kRiskyReify](...args) {
|
|
746
|
-
// safe arborist has suffered side effects and must be rebuilt from scratch
|
|
747
|
-
const arb = new Arborist(...this[kCtorArgs]);
|
|
748
|
-
const ret = await arb.reify(...args);
|
|
749
|
-
Object.assign(this, arb);
|
|
750
|
-
return ret;
|
|
751
|
-
}
|
|
752
|
-
async reify(...args) {
|
|
753
|
-
const options = args[0] ? {
|
|
754
|
-
...args[0]
|
|
755
|
-
} : {};
|
|
756
|
-
if (options.dryRun) {
|
|
757
|
-
return await this[kRiskyReify](...args);
|
|
758
|
-
}
|
|
759
|
-
const old = {
|
|
760
|
-
...options,
|
|
761
|
-
dryRun: false,
|
|
762
|
-
save: Boolean(options['save'] ?? true),
|
|
763
|
-
saveBundle: Boolean(options['saveBundle'] ?? false)
|
|
764
|
-
};
|
|
765
|
-
args[0] = options;
|
|
766
|
-
options.dryRun = true;
|
|
767
|
-
options['save'] = false;
|
|
768
|
-
options['saveBundle'] = false;
|
|
769
|
-
// TODO: make this deal w/ any refactor to private fields by punching the class itself
|
|
770
|
-
await super.reify(...args);
|
|
771
|
-
const diff = walk(this['diff']);
|
|
772
|
-
options.dryRun = old.dryRun;
|
|
773
|
-
options['save'] = old.save;
|
|
774
|
-
options['saveBundle'] = old.saveBundle;
|
|
775
|
-
// Nothing to check, mmm already installed or all private?
|
|
776
|
-
if (diff.findIndex(c => c.newPackage.repository_url === 'https://registry.npmjs.org') === -1) {
|
|
777
|
-
return await this[kRiskyReify](...args);
|
|
778
|
-
}
|
|
779
|
-
const proceed = await ttyServer.captureTTY(async (colorLevel, input, output) => {
|
|
780
|
-
_chalk.default.level = colorLevel;
|
|
781
|
-
if (input && output) {
|
|
782
|
-
const risky = await packagesHaveRiskyIssues(this, this['registry'], diff, output);
|
|
783
|
-
if (!risky) {
|
|
784
|
-
return true;
|
|
785
|
-
}
|
|
786
|
-
const rlin = new _nodeStream.PassThrough();
|
|
787
|
-
input.pipe(rlin);
|
|
788
|
-
const rlout = new _nodeStream.PassThrough();
|
|
789
|
-
rlout.pipe(output, {
|
|
790
|
-
end: false
|
|
791
|
-
});
|
|
792
|
-
const rli = _nodeReadline.createInterface(rlin, rlout);
|
|
793
|
-
try {
|
|
794
|
-
while (true) {
|
|
795
|
-
const answer = await new Promise(resolve => {
|
|
796
|
-
rli.question('Accept risks of installing these packages (y/N)?\n', {
|
|
797
|
-
signal: abortSignal
|
|
798
|
-
}, resolve);
|
|
799
|
-
});
|
|
800
|
-
if (/^\s*y(?:es)?\s*$/i.test(answer)) {
|
|
801
|
-
return true;
|
|
802
|
-
}
|
|
803
|
-
if (/^(?:\s*no?\s*|)$/i.test(answer)) {
|
|
804
|
-
return false;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
} finally {
|
|
808
|
-
rli.close();
|
|
809
|
-
}
|
|
810
|
-
} else if (await packagesHaveRiskyIssues(this, this['registry'], diff, output)) {
|
|
811
|
-
throw new Error('Socket npm Unable to prompt to accept risk, need TTY to do so');
|
|
812
|
-
}
|
|
813
|
-
return true;
|
|
814
|
-
});
|
|
815
|
-
if (proceed) {
|
|
816
|
-
return await this[kRiskyReify](...args);
|
|
817
|
-
} else {
|
|
818
|
-
throw new Error('Socket npm exiting due to risks');
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
require.cache[arboristClassPath].exports = SafeArborist;
|
|
823
|
-
async function main() {
|
|
824
|
-
// shadow `npm` and `npx` to mitigate subshells
|
|
825
|
-
(0, _link.installLinks)((0, _nodeFs.realpathSync)(binPath), 'npm');
|
|
826
|
-
const remoteSettings = await (async () => {
|
|
827
|
-
try {
|
|
828
|
-
const sdk = await (0, _sdk.setupSdk)(pubToken);
|
|
829
|
-
const orgResult = await sdk.getOrganizations();
|
|
830
|
-
if (!orgResult.success) {
|
|
831
|
-
throw new Error('Failed to fetch Socket organization info: ' + orgResult.error.message);
|
|
832
|
-
}
|
|
833
|
-
const orgs = [];
|
|
834
|
-
for (const org of Object.values(orgResult.data.organizations)) {
|
|
835
|
-
if (org) {
|
|
836
|
-
orgs.push(org);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
const result = await sdk.postSettings(orgs.map(org => {
|
|
840
|
-
return {
|
|
841
|
-
organization: org.id
|
|
842
|
-
};
|
|
843
|
-
}));
|
|
844
|
-
if (!result.success) {
|
|
845
|
-
throw new Error('Failed to fetch API key settings: ' + result.error.message);
|
|
846
|
-
}
|
|
847
|
-
return {
|
|
848
|
-
orgs,
|
|
849
|
-
settings: result.data
|
|
850
|
-
};
|
|
851
|
-
} catch (e) {
|
|
852
|
-
if (typeof e === 'object' && e !== null && 'cause' in e) {
|
|
853
|
-
const {
|
|
854
|
-
cause
|
|
855
|
-
} = e;
|
|
856
|
-
if ((0, _typeHelpers.isErrnoException)(cause)) {
|
|
857
|
-
if (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED') {
|
|
858
|
-
throw new Error('Unable to connect to socket.dev, ensure internet connectivity before retrying', {
|
|
859
|
-
cause: e
|
|
860
|
-
});
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
throw e;
|
|
865
|
-
}
|
|
866
|
-
})();
|
|
867
|
-
const {
|
|
868
|
-
orgs,
|
|
869
|
-
settings
|
|
870
|
-
} = remoteSettings;
|
|
871
|
-
const enforcedOrgs = (0, _settings.getSetting)('enforcedOrgs') ?? [];
|
|
872
|
-
|
|
873
|
-
// remove any organizations not being enforced
|
|
874
|
-
for (const {
|
|
875
|
-
0: i,
|
|
876
|
-
1: org
|
|
877
|
-
} of orgs.entries()) {
|
|
878
|
-
if (!enforcedOrgs.includes(org.id)) {
|
|
879
|
-
settings.entries.splice(i, 1);
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
const socketYml = findSocketYML();
|
|
883
|
-
if (socketYml) {
|
|
884
|
-
settings.entries.push({
|
|
885
|
-
start: socketYml.path,
|
|
886
|
-
// @ts-ignore
|
|
887
|
-
settings: {
|
|
888
|
-
[socketYml.path]: {
|
|
889
|
-
deferTo: null,
|
|
890
|
-
issueRules: socketYml.parsed.issueRules
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
_uxLookup = (0, _issueRules.createIssueUXLookup)(settings);
|
|
896
|
-
}
|
|
897
|
-
void main();
|
|
898
|
-
|
|
899
|
-
exports.npmInjection = npmInjection;
|