@socketsecurity/cli-with-sentry 0.14.57 → 0.14.59
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/bin/cli.js +2 -0
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +11 -6
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.js +2 -2
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/module-sync/artifact.d.ts +75 -0
- package/dist/module-sync/cli.js +1063 -802
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/index.d.ts +4 -3
- package/dist/module-sync/shadow-bin.js +3 -1
- package/dist/module-sync/shadow-bin.js.map +1 -1
- package/dist/module-sync/shadow-npm-inject.js +1414 -1287
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/module-sync/socket-package-alert.d.ts +46 -0
- package/dist/module-sync/types.d.ts +11 -3
- package/dist/require/cli.js +1063 -802
- package/dist/require/cli.js.map +1 -1
- package/package.json +12 -10
- package/dist/module-sync/color-or-markdown.d.ts +0 -16
- package/dist/module-sync/socket-url.d.ts +0 -3
package/dist/require/cli.js
CHANGED
|
@@ -26,6 +26,7 @@ var ndjson = _socketInterop(require('ndjson'));
|
|
|
26
26
|
var shadowNpmInject = require('./shadow-npm-inject.js');
|
|
27
27
|
var constants = require('./constants.js');
|
|
28
28
|
var objects = require('@socketsecurity/registry/lib/objects');
|
|
29
|
+
var path$1 = require('@socketsecurity/registry/lib/path');
|
|
29
30
|
var regexps = require('@socketsecurity/registry/lib/regexps');
|
|
30
31
|
var commonTags = _socketInterop(require('common-tags'));
|
|
31
32
|
var fs$1 = require('node:fs/promises');
|
|
@@ -40,26 +41,29 @@ var require$$0$1 = require('node:util');
|
|
|
40
41
|
var registry = require('@socketsecurity/registry');
|
|
41
42
|
var npm = require('@socketsecurity/registry/lib/npm');
|
|
42
43
|
var packages = require('@socketsecurity/registry/lib/packages');
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var
|
|
44
|
+
var lockfileFile = _socketInterop(require('@pnpm/lockfile-file'));
|
|
45
|
+
var lockfile_detectDepTypes = _socketInterop(require('@pnpm/lockfile.detect-dep-types'));
|
|
46
|
+
var debug = require('@socketsecurity/registry/lib/debug');
|
|
46
47
|
var spawn = require('@socketsecurity/registry/lib/spawn');
|
|
47
|
-
var
|
|
48
|
-
var semver = _socketInterop(require('semver'));
|
|
49
|
-
var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
50
|
-
var promises = require('@socketsecurity/registry/lib/promises');
|
|
48
|
+
var shadowNpmPaths = require('./shadow-npm-paths.js');
|
|
51
49
|
var browserslist = _socketInterop(require('browserslist'));
|
|
50
|
+
var semver = _socketInterop(require('semver'));
|
|
52
51
|
var which = _socketInterop(require('which'));
|
|
53
52
|
var index_cjs = require('@socketregistry/hyrious__bun.lockb/index.cjs');
|
|
54
53
|
var sorts = require('@socketsecurity/registry/lib/sorts');
|
|
55
54
|
var strings = require('@socketsecurity/registry/lib/strings');
|
|
55
|
+
var registryConstants = require('@socketsecurity/registry/lib/constants');
|
|
56
|
+
var isInteractive = require('@socketregistry/is-interactive/index.cjs');
|
|
57
|
+
var terminalLink = _socketInterop(require('terminal-link'));
|
|
58
|
+
var npa = _socketInterop(require('npm-package-arg'));
|
|
59
|
+
var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
60
|
+
var promises = require('@socketsecurity/registry/lib/promises');
|
|
56
61
|
var yaml = _socketInterop(require('yaml'));
|
|
57
|
-
var debug = require('@socketsecurity/registry/lib/debug');
|
|
58
|
-
var shadowNpmPaths = require('./shadow-npm-paths.js');
|
|
59
62
|
var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
|
|
60
63
|
var config$A = require('@socketsecurity/config');
|
|
61
64
|
var assert = require('node:assert');
|
|
62
65
|
var readline = require('node:readline/promises');
|
|
66
|
+
var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
|
|
63
67
|
var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
|
|
64
68
|
var readline$1 = require('node:readline');
|
|
65
69
|
|
|
@@ -321,7 +325,7 @@ class Core {
|
|
|
321
325
|
}) {
|
|
322
326
|
const introducedBy = [];
|
|
323
327
|
if (pkg.direct) {
|
|
324
|
-
|
|
328
|
+
const manifests = pkg.manifestFiles.map(({
|
|
325
329
|
file
|
|
326
330
|
}) => file).join(';');
|
|
327
331
|
introducedBy.push(['direct', manifests]);
|
|
@@ -332,7 +336,7 @@ class Core {
|
|
|
332
336
|
continue;
|
|
333
337
|
}
|
|
334
338
|
const topPurl = `${topPackage.type}/${topPackage.name}@${topPackage.version}`;
|
|
335
|
-
|
|
339
|
+
const manifests = topPackage.manifestFiles.map(({
|
|
336
340
|
file
|
|
337
341
|
}) => file).join(';');
|
|
338
342
|
introducedBy.push([topPurl, manifests]);
|
|
@@ -764,7 +768,7 @@ function processSecurityComment({
|
|
|
764
768
|
const result = [];
|
|
765
769
|
let start = false;
|
|
766
770
|
let ignoreAll = false;
|
|
767
|
-
|
|
771
|
+
const ignoredPackages = [];
|
|
768
772
|
for (const ignoreComment of ignoreComments) {
|
|
769
773
|
const parsed = parseIgnoreCommand(ignoreComment.body?.split('\n').at(0) ?? '');
|
|
770
774
|
if (parsed.ignoreAll) {
|
|
@@ -788,7 +792,7 @@ function processSecurityComment({
|
|
|
788
792
|
const [_, _title, packageLink, _introducedBy, _manifest, _ci] = line.split('|');
|
|
789
793
|
|
|
790
794
|
// Parsing package link [npm/pkg](url)
|
|
791
|
-
|
|
795
|
+
const [_ecosystem, pkg] = packageLink.slice(1, packageLink.indexOf(']')).split('/', 2);
|
|
792
796
|
const [pkgName, pkgVersion] = pkg.split('@');
|
|
793
797
|
|
|
794
798
|
// Checking if this package should be ignored
|
|
@@ -1111,8 +1115,8 @@ function createSources(alert) {
|
|
|
1111
1115
|
manifests.push(addStr);
|
|
1112
1116
|
}
|
|
1113
1117
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1118
|
+
const manifestList = manifests.join('');
|
|
1119
|
+
const sourceList = sources.join('');
|
|
1116
1120
|
const manifestStr = `<ul>${manifestList}</ul>`;
|
|
1117
1121
|
const sourcesStr = `<ul>${sourceList}</ul>`;
|
|
1118
1122
|
return [manifestStr, sourcesStr];
|
|
@@ -1257,8 +1261,8 @@ async function runAction(githubEventBefore, githubEventAfter) {
|
|
|
1257
1261
|
const securityComment = securityCommentTemplate(diff);
|
|
1258
1262
|
let newSecurityComment = true;
|
|
1259
1263
|
let newOverviewComment = true;
|
|
1260
|
-
|
|
1261
|
-
|
|
1264
|
+
const updateOldSecurityComment = comments.security !== undefined;
|
|
1265
|
+
const updateOldOverviewComment = comments.overview !== undefined;
|
|
1262
1266
|
if (diff.newAlerts.length === 0) {
|
|
1263
1267
|
if (!updateOldSecurityComment) {
|
|
1264
1268
|
newSecurityComment = false;
|
|
@@ -1400,8 +1404,7 @@ const validationFlags = {
|
|
|
1400
1404
|
|
|
1401
1405
|
const {
|
|
1402
1406
|
DRY_RUN_LABEL: DRY_RUN_LABEL$1,
|
|
1403
|
-
REDACTED
|
|
1404
|
-
SOCKET_CLI_SHOW_BANNER
|
|
1407
|
+
REDACTED
|
|
1405
1408
|
} = constants;
|
|
1406
1409
|
async function meowWithSubcommands(subcommands, options) {
|
|
1407
1410
|
const {
|
|
@@ -1435,11 +1438,7 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1435
1438
|
};
|
|
1436
1439
|
// ...else we provide basic instructions and help.
|
|
1437
1440
|
|
|
1438
|
-
|
|
1439
|
-
// Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
|
|
1440
|
-
if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
|
|
1441
|
-
logger.logger.log(getAsciiHeader(name));
|
|
1442
|
-
}
|
|
1441
|
+
emitBanner(name);
|
|
1443
1442
|
const cli = vendor.meow(`
|
|
1444
1443
|
Usage
|
|
1445
1444
|
$ ${name} <command>
|
|
@@ -1493,11 +1492,7 @@ function meowOrExit({
|
|
|
1493
1492
|
parentName
|
|
1494
1493
|
}) {
|
|
1495
1494
|
const command = `${parentName} ${config.commandName}`;
|
|
1496
|
-
|
|
1497
|
-
// Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
|
|
1498
|
-
if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
|
|
1499
|
-
logger.logger.log(getAsciiHeader(command));
|
|
1500
|
-
}
|
|
1495
|
+
emitBanner(command);
|
|
1501
1496
|
|
|
1502
1497
|
// This exits if .printHelp() is called either by meow itself or by us.
|
|
1503
1498
|
const cli = vendor.meow({
|
|
@@ -1514,13 +1509,24 @@ function meowOrExit({
|
|
|
1514
1509
|
}
|
|
1515
1510
|
return cli;
|
|
1516
1511
|
}
|
|
1512
|
+
function emitBanner(name) {
|
|
1513
|
+
// Print a banner at the top of each command.
|
|
1514
|
+
// This helps with brand recognition and marketing.
|
|
1515
|
+
// It also helps with debugging since it contains version and command details.
|
|
1516
|
+
// Note: print over stderr to preserve stdout for flags like --json and
|
|
1517
|
+
// --markdown. If we don't do this, you can't use --json in particular
|
|
1518
|
+
// and pipe the result to other tools. By emiting the banner over stderr
|
|
1519
|
+
// you can do something like `socket scan view xyz | jq | process`.
|
|
1520
|
+
// The spinner also emits over stderr for example.
|
|
1521
|
+
logger.logger.error(getAsciiHeader(name));
|
|
1522
|
+
}
|
|
1517
1523
|
function getAsciiHeader(command) {
|
|
1518
1524
|
const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
|
|
1519
|
-
"0.14.
|
|
1525
|
+
"0.14.59:e40b009:5200cfd8:pub";
|
|
1520
1526
|
const nodeVersion = process.version;
|
|
1521
1527
|
const apiToken = shadowNpmInject.getSetting('apiToken');
|
|
1522
1528
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
|
|
1523
|
-
const relCwd = process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}`, 'i'), '~/');
|
|
1529
|
+
const relCwd = path$1.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path.sep}|$)`, 'i'), '~/'));
|
|
1524
1530
|
const body = `
|
|
1525
1531
|
_____ _ _ /---------------
|
|
1526
1532
|
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver ${cliVersion}
|
|
@@ -1719,7 +1725,7 @@ async function outputAnalyticsWithToken({
|
|
|
1719
1725
|
// A message should already have been printed if we have no data here
|
|
1720
1726
|
if (!data) return;
|
|
1721
1727
|
if (outputKind === 'json') {
|
|
1722
|
-
|
|
1728
|
+
const serialized = renderJson(data);
|
|
1723
1729
|
if (!serialized) return;
|
|
1724
1730
|
if (filePath && filePath !== '-') {
|
|
1725
1731
|
try {
|
|
@@ -2191,6 +2197,9 @@ const config$x = {
|
|
|
2191
2197
|
Usage
|
|
2192
2198
|
$ ${command} <org slug>
|
|
2193
2199
|
|
|
2200
|
+
This feature requires an Enterprise Plan. To learn more about getting access
|
|
2201
|
+
to this feature and many more, please visit https://socket.dev/pricing
|
|
2202
|
+
|
|
2194
2203
|
Options
|
|
2195
2204
|
${getFlagListOutput(config.flags, 6)}
|
|
2196
2205
|
|
|
@@ -2246,22 +2255,22 @@ async function run$x(argv, importMeta, {
|
|
|
2246
2255
|
}
|
|
2247
2256
|
|
|
2248
2257
|
const {
|
|
2249
|
-
NPM: NPM$
|
|
2258
|
+
NPM: NPM$f,
|
|
2250
2259
|
NPX: NPX$3,
|
|
2251
|
-
PNPM: PNPM$
|
|
2260
|
+
PNPM: PNPM$a
|
|
2252
2261
|
} = constants;
|
|
2253
|
-
const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$
|
|
2262
|
+
const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$f, PNPM$a, 'ts', 'tsx', 'typescript']);
|
|
2254
2263
|
async function runCycloneDX(yargv) {
|
|
2255
2264
|
let cleanupPackageLock = false;
|
|
2256
2265
|
if (yargv.type !== 'yarn' && nodejsPlatformTypes.has(yargv.type) && fs.existsSync('./yarn.lock')) {
|
|
2257
2266
|
if (fs.existsSync('./package-lock.json')) {
|
|
2258
|
-
yargv.type = NPM$
|
|
2267
|
+
yargv.type = NPM$f;
|
|
2259
2268
|
} else {
|
|
2260
2269
|
// Use synp to create a package-lock.json from the yarn.lock,
|
|
2261
2270
|
// based on the node_modules folder, for a more accurate SBOM.
|
|
2262
2271
|
try {
|
|
2263
2272
|
await shadowBin(NPX$3, ['synp@1.9.14', '--', '--source-file', './yarn.lock'], 2);
|
|
2264
|
-
yargv.type = NPM$
|
|
2273
|
+
yargv.type = NPM$f;
|
|
2265
2274
|
cleanupPackageLock = true;
|
|
2266
2275
|
} catch {}
|
|
2267
2276
|
}
|
|
@@ -2781,99 +2790,105 @@ const cmdDiffScan = {
|
|
|
2781
2790
|
}
|
|
2782
2791
|
};
|
|
2783
2792
|
|
|
2784
|
-
// import { detect } from '../../utils/package-environment-detector'
|
|
2785
|
-
|
|
2786
2793
|
const {
|
|
2787
|
-
NPM: NPM$
|
|
2794
|
+
NPM: NPM$e
|
|
2788
2795
|
} = constants;
|
|
2789
2796
|
function isTopLevel(tree, node) {
|
|
2790
2797
|
return tree.children.get(node.name) === node;
|
|
2791
2798
|
}
|
|
2792
|
-
async function
|
|
2793
|
-
// Lazily access constants.spinner.
|
|
2799
|
+
async function npmFix(_pkgEnvDetails, cwd, options) {
|
|
2794
2800
|
const {
|
|
2795
2801
|
spinner
|
|
2796
|
-
} =
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
});
|
|
2802
|
-
// const agentDetails = await detect()
|
|
2803
|
-
|
|
2802
|
+
} = {
|
|
2803
|
+
__proto__: null,
|
|
2804
|
+
...options
|
|
2805
|
+
};
|
|
2806
|
+
spinner?.start();
|
|
2804
2807
|
const arb = new shadowNpmInject.SafeArborist({
|
|
2805
2808
|
path: cwd,
|
|
2806
2809
|
...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2807
2810
|
});
|
|
2808
2811
|
await arb.reify();
|
|
2809
|
-
const
|
|
2812
|
+
const alertsMap = await shadowNpmInject.getAlertsMapFromArborist(arb, {
|
|
2810
2813
|
consolidate: true,
|
|
2811
|
-
|
|
2812
|
-
|
|
2814
|
+
include: {
|
|
2815
|
+
existing: true,
|
|
2816
|
+
unfixable: false,
|
|
2817
|
+
upgrade: false
|
|
2818
|
+
}
|
|
2813
2819
|
});
|
|
2814
|
-
const infoByPkg = shadowNpmInject.
|
|
2820
|
+
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
|
|
2821
|
+
if (!infoByPkg) {
|
|
2822
|
+
spinner?.stop();
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2815
2825
|
await arb.buildIdealTree();
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
}
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2826
|
+
const editablePkgJson = await packages.readPackageJson(cwd, {
|
|
2827
|
+
editable: true
|
|
2828
|
+
});
|
|
2829
|
+
for (const {
|
|
2830
|
+
0: name,
|
|
2831
|
+
1: infos
|
|
2832
|
+
} of infoByPkg) {
|
|
2833
|
+
const revertToIdealTree = arb.idealTree;
|
|
2834
|
+
arb.idealTree = null;
|
|
2835
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2836
|
+
await arb.buildIdealTree();
|
|
2837
|
+
const tree = arb.idealTree;
|
|
2838
|
+
const hasUpgrade = !!registry.getManifestData(NPM$e, name);
|
|
2839
|
+
if (hasUpgrade) {
|
|
2840
|
+
spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
|
|
2841
|
+
continue;
|
|
2842
|
+
}
|
|
2843
|
+
const nodes = shadowNpmInject.findPackageNodes(tree, name);
|
|
2844
|
+
const packument = nodes.length && infos.length ?
|
|
2845
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2846
|
+
await packages.fetchPackagePackument(name) : null;
|
|
2847
|
+
if (!packument) {
|
|
2848
|
+
continue;
|
|
2849
|
+
}
|
|
2850
|
+
for (let i = 0, {
|
|
2851
|
+
length: nodesLength
|
|
2852
|
+
} = nodes; i < nodesLength; i += 1) {
|
|
2853
|
+
const node = nodes[i];
|
|
2854
|
+
for (let j = 0, {
|
|
2855
|
+
length: infosLength
|
|
2856
|
+
} = infos; j < infosLength; j += 1) {
|
|
2857
|
+
const {
|
|
2858
|
+
firstPatchedVersionIdentifier,
|
|
2859
|
+
vulnerableVersionRange
|
|
2860
|
+
} = infos[j];
|
|
2861
|
+
const {
|
|
2862
|
+
version: oldVersion
|
|
2863
|
+
} = node;
|
|
2864
|
+
if (shadowNpmInject.updateNode(node, packument, vulnerableVersionRange)) {
|
|
2865
|
+
try {
|
|
2866
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2867
|
+
await npm.runScript('test', [], {
|
|
2868
|
+
spinner,
|
|
2869
|
+
stdio: 'ignore'
|
|
2870
|
+
});
|
|
2871
|
+
spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
|
|
2872
|
+
if (isTopLevel(tree, node)) {
|
|
2873
|
+
for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
|
|
2874
|
+
const {
|
|
2875
|
+
content: pkgJson
|
|
2876
|
+
} = editablePkgJson;
|
|
2877
|
+
const oldVersion = pkgJson[depField]?.[name];
|
|
2878
|
+
if (oldVersion) {
|
|
2879
|
+
const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? '';
|
|
2880
|
+
pkgJson[depField][name] = `${decorator}${node.version}`;
|
|
2866
2881
|
}
|
|
2867
|
-
// eslint-disable-next-line no-await-in-loop
|
|
2868
|
-
await editablePkgJson.save();
|
|
2869
|
-
} catch {
|
|
2870
|
-
spinner.error(`Reverting ${name} to ${oldVersion}`);
|
|
2871
|
-
arb.idealTree = revertToIdealTree;
|
|
2872
2882
|
}
|
|
2873
|
-
} else {
|
|
2874
|
-
spinner.error(`Could not patch ${name} ${oldVersion}`);
|
|
2875
2883
|
}
|
|
2884
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2885
|
+
await editablePkgJson.save();
|
|
2886
|
+
} catch {
|
|
2887
|
+
spinner?.error(`Reverting ${name} to ${oldVersion}`);
|
|
2888
|
+
arb.idealTree = revertToIdealTree;
|
|
2876
2889
|
}
|
|
2890
|
+
} else {
|
|
2891
|
+
spinner?.error(`Could not patch ${name} ${oldVersion}`);
|
|
2877
2892
|
}
|
|
2878
2893
|
}
|
|
2879
2894
|
}
|
|
@@ -2883,161 +2898,687 @@ async function runFix() {
|
|
|
2883
2898
|
});
|
|
2884
2899
|
arb2.idealTree = arb.idealTree;
|
|
2885
2900
|
await arb2.reify();
|
|
2886
|
-
spinner
|
|
2901
|
+
spinner?.stop();
|
|
2887
2902
|
}
|
|
2888
2903
|
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
`
|
|
2906
|
-
|
|
2907
|
-
const
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
importMeta,
|
|
2919
|
-
parentName
|
|
2920
|
-
});
|
|
2921
|
-
if (cli.flags['dryRun']) {
|
|
2922
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$s);
|
|
2923
|
-
return;
|
|
2904
|
+
async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
2905
|
+
const {
|
|
2906
|
+
spinner
|
|
2907
|
+
} = {
|
|
2908
|
+
__proto__: null,
|
|
2909
|
+
...options
|
|
2910
|
+
};
|
|
2911
|
+
const depTypes = lockfile_detectDepTypes.detectDepTypes(lockfile);
|
|
2912
|
+
const pkgIds = Object.keys(depTypes);
|
|
2913
|
+
let {
|
|
2914
|
+
length: remaining
|
|
2915
|
+
} = pkgIds;
|
|
2916
|
+
const alertsByPkgId = new Map();
|
|
2917
|
+
if (!remaining) {
|
|
2918
|
+
return alertsByPkgId;
|
|
2919
|
+
}
|
|
2920
|
+
const getText = () => `Looking up data for ${remaining} packages`;
|
|
2921
|
+
spinner?.start(getText());
|
|
2922
|
+
const toAlertsMapOptions = {
|
|
2923
|
+
overrides: lockfile.overrides,
|
|
2924
|
+
...options
|
|
2925
|
+
};
|
|
2926
|
+
for await (const artifact of shadowNpmInject.batchScan(pkgIds)) {
|
|
2927
|
+
await shadowNpmInject.addArtifactToAlertsMap(artifact, alertsByPkgId, toAlertsMapOptions);
|
|
2928
|
+
remaining -= 1;
|
|
2929
|
+
if (spinner && remaining > 0) {
|
|
2930
|
+
spinner.start();
|
|
2931
|
+
spinner.setText(getText());
|
|
2932
|
+
}
|
|
2924
2933
|
}
|
|
2925
|
-
|
|
2934
|
+
spinner?.stop();
|
|
2935
|
+
return alertsByPkgId;
|
|
2926
2936
|
}
|
|
2927
2937
|
|
|
2928
|
-
function
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2938
|
+
function cmdFlagsToString(args) {
|
|
2939
|
+
const result = [];
|
|
2940
|
+
for (let i = 0, {
|
|
2941
|
+
length
|
|
2942
|
+
} = args; i < length; i += 1) {
|
|
2943
|
+
if (args[i].startsWith('--')) {
|
|
2944
|
+
// Check if the next item exists and is NOT another flag.
|
|
2945
|
+
if (i + 1 < length && !args[i + 1].startsWith('--')) {
|
|
2946
|
+
result.push(`${args[i]}=${args[i + 1]}`);
|
|
2947
|
+
i += 1;
|
|
2948
|
+
} else {
|
|
2949
|
+
result.push(args[i]);
|
|
2950
|
+
}
|
|
2932
2951
|
}
|
|
2933
2952
|
}
|
|
2934
|
-
return
|
|
2953
|
+
return result.join(' ');
|
|
2935
2954
|
}
|
|
2936
|
-
function
|
|
2937
|
-
const
|
|
2938
|
-
|
|
2939
|
-
result[key] = input[key];
|
|
2940
|
-
}
|
|
2941
|
-
return result;
|
|
2955
|
+
function cmdPrefixMessage(cmdName, text) {
|
|
2956
|
+
const cmdPrefix = cmdName ? `${cmdName}: ` : '';
|
|
2957
|
+
return `${cmdPrefix}${text}`;
|
|
2942
2958
|
}
|
|
2943
2959
|
|
|
2944
|
-
|
|
2945
|
-
|
|
2960
|
+
const {
|
|
2961
|
+
SOCKET_CLI_SENTRY_BUILD,
|
|
2962
|
+
SOCKET_IPC_HANDSHAKE
|
|
2963
|
+
} = constants;
|
|
2964
|
+
function safeNpmInstall(options) {
|
|
2946
2965
|
const {
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2966
|
+
agentExecPath = shadowNpmPaths.getNpmBinPath(),
|
|
2967
|
+
args = [],
|
|
2968
|
+
ipc,
|
|
2969
|
+
spinner,
|
|
2970
|
+
...spawnOptions
|
|
2971
|
+
} = {
|
|
2972
|
+
__proto__: null,
|
|
2973
|
+
...options
|
|
2974
|
+
};
|
|
2975
|
+
const useIpc = objects.isObject(ipc);
|
|
2976
|
+
const useDebug = debug.isDebug();
|
|
2977
|
+
const terminatorPos = args.indexOf('--');
|
|
2978
|
+
const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
|
|
2979
|
+
const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
|
|
2980
|
+
const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
|
|
2981
|
+
const logLevelArgs = isSilent ? ['--loglevel', 'error'] : [];
|
|
2982
|
+
const spawnPromise = spawn.spawn(
|
|
2983
|
+
// Lazily access constants.execPath.
|
|
2984
|
+
constants.execPath, [
|
|
2985
|
+
// Lazily access constants.nodeHardenFlags.
|
|
2986
|
+
...constants.nodeHardenFlags,
|
|
2987
|
+
// Lazily access constants.nodeNoWarningsFlags.
|
|
2988
|
+
...constants.nodeNoWarningsFlags,
|
|
2989
|
+
// Lazily access constants.ENV[SOCKET_CLI_SENTRY_BUILD].
|
|
2990
|
+
...(constants.ENV[SOCKET_CLI_SENTRY_BUILD] ? ['--require',
|
|
2991
|
+
// Lazily access constants.distInstrumentWithSentryPath.
|
|
2992
|
+
constants.distInstrumentWithSentryPath] : []), '--require',
|
|
2993
|
+
// Lazily access constants.distShadowNpmInjectPath.
|
|
2994
|
+
constants.distShadowNpmInjectPath, agentExecPath, 'install',
|
|
2995
|
+
// Avoid code paths for 'audit' and 'fund'.
|
|
2996
|
+
'--no-audit', '--no-fund',
|
|
2997
|
+
// Add `--no-progress` flag to fix input being swallowed by the spinner
|
|
2998
|
+
// when running the command with recent versions of npm.
|
|
2999
|
+
'--no-progress',
|
|
3000
|
+
// Add '--loglevel=error' if a loglevel flag is not provided and the
|
|
3001
|
+
// SOCKET_CLI_DEBUG environment variable is not truthy.
|
|
3002
|
+
...logLevelArgs, ...npmArgs, ...otherArgs], {
|
|
3003
|
+
spinner,
|
|
3004
|
+
// Set stdio to include 'ipc'.
|
|
3005
|
+
// See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
|
|
3006
|
+
// and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
|
|
3007
|
+
stdio: useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
|
|
3008
|
+
...spawnOptions,
|
|
3009
|
+
env: {
|
|
3010
|
+
...process$1.env,
|
|
3011
|
+
...spawnOptions.env
|
|
3012
|
+
}
|
|
3013
|
+
});
|
|
3014
|
+
if (useIpc) {
|
|
3015
|
+
spawnPromise.process.send({
|
|
3016
|
+
[SOCKET_IPC_HANDSHAKE]: ipc
|
|
3017
|
+
});
|
|
2954
3018
|
}
|
|
2955
|
-
|
|
2956
|
-
return `${values.join(', ')}${separator}${finalValue}`;
|
|
3019
|
+
return spawnPromise;
|
|
2957
3020
|
}
|
|
2958
3021
|
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
3022
|
+
const {
|
|
3023
|
+
NPM: NPM$d
|
|
3024
|
+
} = constants;
|
|
3025
|
+
function runAgentInstall(pkgEnvDetails, options) {
|
|
3026
|
+
const {
|
|
3027
|
+
agent,
|
|
3028
|
+
agentExecPath
|
|
3029
|
+
} = pkgEnvDetails;
|
|
3030
|
+
// All package managers support the "install" command.
|
|
3031
|
+
if (agent === NPM$d) {
|
|
3032
|
+
return safeNpmInstall({
|
|
3033
|
+
agentExecPath,
|
|
3034
|
+
...options
|
|
3035
|
+
});
|
|
2968
3036
|
}
|
|
2969
|
-
|
|
3037
|
+
const {
|
|
3038
|
+
args = [],
|
|
3039
|
+
spinner,
|
|
3040
|
+
...spawnOptions
|
|
3041
|
+
} = {
|
|
3042
|
+
__proto__: null,
|
|
3043
|
+
...options
|
|
3044
|
+
};
|
|
3045
|
+
return spawn.spawn(agentExecPath, ['install', ...args], {
|
|
3046
|
+
spinner,
|
|
3047
|
+
stdio: debug.isDebug() ? 'inherit' : 'ignore',
|
|
3048
|
+
...spawnOptions,
|
|
3049
|
+
env: {
|
|
3050
|
+
...process.env,
|
|
3051
|
+
NODE_OPTIONS: cmdFlagsToString([
|
|
3052
|
+
// Lazily access constants.nodeHardenFlags.
|
|
3053
|
+
...constants.nodeHardenFlags,
|
|
3054
|
+
// Lazily access constants.nodeNoWarningsFlags.
|
|
3055
|
+
...constants.nodeNoWarningsFlags]),
|
|
3056
|
+
...spawnOptions.env
|
|
3057
|
+
}
|
|
3058
|
+
});
|
|
2970
3059
|
}
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3060
|
+
|
|
3061
|
+
const {
|
|
3062
|
+
NPM: NPM$c,
|
|
3063
|
+
OVERRIDES: OVERRIDES$2,
|
|
3064
|
+
PNPM: PNPM$9
|
|
3065
|
+
} = constants;
|
|
3066
|
+
async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
3067
|
+
const {
|
|
3068
|
+
spinner
|
|
3069
|
+
} = {
|
|
3070
|
+
__proto__: null,
|
|
3071
|
+
...options
|
|
3072
|
+
};
|
|
3073
|
+
spinner?.start();
|
|
3074
|
+
const lockfile = await lockfileFile.readWantedLockfile(cwd, {
|
|
3075
|
+
ignoreIncompatible: false
|
|
3076
|
+
});
|
|
3077
|
+
if (!lockfile) {
|
|
3078
|
+
spinner?.stop();
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
3081
|
+
const alertsMap = await getAlertsMapFromPnpmLockfile(lockfile, {
|
|
3082
|
+
consolidate: true,
|
|
3083
|
+
include: {
|
|
3084
|
+
existing: true,
|
|
3085
|
+
unfixable: false,
|
|
3086
|
+
upgrade: false
|
|
2976
3087
|
}
|
|
3088
|
+
});
|
|
3089
|
+
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
|
|
3090
|
+
if (!infoByPkg) {
|
|
3091
|
+
spinner?.stop();
|
|
3092
|
+
return;
|
|
2977
3093
|
}
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3094
|
+
const arb = new shadowNpmInject.SafeArborist({
|
|
3095
|
+
path: cwd,
|
|
3096
|
+
...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
3097
|
+
});
|
|
3098
|
+
await arb.loadActual();
|
|
3099
|
+
const editablePkgJson = await packages.readPackageJson(cwd, {
|
|
3100
|
+
editable: true
|
|
3101
|
+
});
|
|
3102
|
+
const {
|
|
3103
|
+
content: pkgJson
|
|
3104
|
+
} = editablePkgJson;
|
|
3105
|
+
for (const {
|
|
3106
|
+
0: name,
|
|
3107
|
+
1: infos
|
|
3108
|
+
} of infoByPkg) {
|
|
3109
|
+
const tree = arb.actualTree;
|
|
3110
|
+
const hasUpgrade = !!registry.getManifestData(NPM$c, name);
|
|
3111
|
+
if (hasUpgrade) {
|
|
3112
|
+
spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
|
|
2992
3113
|
continue;
|
|
2993
3114
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
3115
|
+
const nodes = shadowNpmInject.findPackageNodes(tree, name);
|
|
3116
|
+
const packument = nodes.length && infos.length ?
|
|
3117
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3118
|
+
await packages.fetchPackagePackument(name) : null;
|
|
3119
|
+
if (!packument) {
|
|
3120
|
+
continue;
|
|
2996
3121
|
}
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
}
|
|
3122
|
+
for (let i = 0, {
|
|
3123
|
+
length: nodesLength
|
|
3124
|
+
} = nodes; i < nodesLength; i += 1) {
|
|
3125
|
+
const node = nodes[i];
|
|
3126
|
+
for (let j = 0, {
|
|
3127
|
+
length: infosLength
|
|
3128
|
+
} = infos; j < infosLength; j += 1) {
|
|
3129
|
+
const {
|
|
3130
|
+
firstPatchedVersionIdentifier,
|
|
3131
|
+
vulnerableVersionRange
|
|
3132
|
+
} = infos[j];
|
|
3133
|
+
const {
|
|
3134
|
+
version: oldVersion
|
|
3135
|
+
} = node;
|
|
3136
|
+
const availableVersions = Object.keys(packument.versions);
|
|
3137
|
+
// Find the highest non-vulnerable version within the same major range
|
|
3138
|
+
const targetVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
|
|
3139
|
+
const targetPackument = targetVersion ? packument.versions[targetVersion] : undefined;
|
|
3140
|
+
if (targetPackument) {
|
|
3141
|
+
const oldPnpm = pkgJson[PNPM$9];
|
|
3142
|
+
const oldOverrides = oldPnpm?.[OVERRIDES$2];
|
|
3143
|
+
try {
|
|
3144
|
+
editablePkgJson.update({
|
|
3145
|
+
[PNPM$9]: {
|
|
3146
|
+
...oldPnpm,
|
|
3147
|
+
[OVERRIDES$2]: {
|
|
3148
|
+
[`${node.name}@${vulnerableVersionRange}`]: `^${targetVersion}`,
|
|
3149
|
+
...oldOverrides
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
});
|
|
3153
|
+
spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
|
|
3000
3154
|
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3155
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3156
|
+
await editablePkgJson.save();
|
|
3157
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3158
|
+
await runAgentInstall(pkgEnvDetails, {
|
|
3159
|
+
spinner
|
|
3160
|
+
});
|
|
3161
|
+
} catch {
|
|
3162
|
+
spinner?.error(`Reverting ${name} to ${oldVersion}`);
|
|
3163
|
+
}
|
|
3164
|
+
} else {
|
|
3165
|
+
spinner?.error(`Could not patch ${name} ${oldVersion}`);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3010
3169
|
}
|
|
3011
|
-
|
|
3012
|
-
return {
|
|
3013
|
-
data: result.data,
|
|
3014
|
-
severityCount,
|
|
3015
|
-
score: scoreResult.data
|
|
3016
|
-
};
|
|
3170
|
+
spinner?.stop();
|
|
3017
3171
|
}
|
|
3018
3172
|
|
|
3019
3173
|
const {
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3174
|
+
BINARY_LOCK_EXT,
|
|
3175
|
+
BUN: BUN$5,
|
|
3176
|
+
LOCK_EXT: LOCK_EXT$1,
|
|
3177
|
+
NPM: NPM$b,
|
|
3178
|
+
NPM_BUGGY_OVERRIDES_PATCHED_VERSION: NPM_BUGGY_OVERRIDES_PATCHED_VERSION$1,
|
|
3179
|
+
PNPM: PNPM$8,
|
|
3180
|
+
VLT: VLT$5,
|
|
3181
|
+
YARN,
|
|
3182
|
+
YARN_BERRY: YARN_BERRY$5,
|
|
3183
|
+
YARN_CLASSIC: YARN_CLASSIC$6
|
|
3184
|
+
} = constants;
|
|
3185
|
+
const AGENTS = [BUN$5, NPM$b, PNPM$8, YARN_BERRY$5, YARN_CLASSIC$6, VLT$5];
|
|
3186
|
+
const binByAgent = {
|
|
3187
|
+
__proto__: null,
|
|
3188
|
+
[BUN$5]: BUN$5,
|
|
3189
|
+
[NPM$b]: NPM$b,
|
|
3190
|
+
[PNPM$8]: PNPM$8,
|
|
3191
|
+
[YARN_BERRY$5]: YARN,
|
|
3192
|
+
[YARN_CLASSIC$6]: YARN,
|
|
3193
|
+
[VLT$5]: VLT$5
|
|
3194
|
+
};
|
|
3195
|
+
async function getAgentExecPath(agent) {
|
|
3196
|
+
const binName = binByAgent[agent];
|
|
3197
|
+
return (await which(binName, {
|
|
3198
|
+
nothrow: true
|
|
3199
|
+
})) ?? binName;
|
|
3200
|
+
}
|
|
3201
|
+
async function getAgentVersion(agentExecPath, cwd) {
|
|
3202
|
+
let result;
|
|
3203
|
+
try {
|
|
3204
|
+
result = semver.coerce(
|
|
3205
|
+
// All package managers support the "--version" flag.
|
|
3206
|
+
(await spawn.spawn(agentExecPath, ['--version'], {
|
|
3207
|
+
cwd
|
|
3208
|
+
})).stdout) ?? undefined;
|
|
3209
|
+
} catch {}
|
|
3210
|
+
return result;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
// The order of LOCKS properties IS significant as it affects iteration order.
|
|
3214
|
+
const LOCKS = {
|
|
3215
|
+
[`bun${LOCK_EXT$1}`]: BUN$5,
|
|
3216
|
+
[`bun${BINARY_LOCK_EXT}`]: BUN$5,
|
|
3217
|
+
// If both package-lock.json and npm-shrinkwrap.json are present in the root
|
|
3218
|
+
// of a project, npm-shrinkwrap.json will take precedence and package-lock.json
|
|
3219
|
+
// will be ignored.
|
|
3220
|
+
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
|
|
3221
|
+
'npm-shrinkwrap.json': NPM$b,
|
|
3222
|
+
'package-lock.json': NPM$b,
|
|
3223
|
+
'pnpm-lock.yaml': PNPM$8,
|
|
3224
|
+
'pnpm-lock.yml': PNPM$8,
|
|
3225
|
+
[`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$6,
|
|
3226
|
+
'vlt-lock.json': VLT$5,
|
|
3227
|
+
// Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
|
|
3228
|
+
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
|
|
3229
|
+
//
|
|
3230
|
+
// Unlike the other LOCKS keys this key contains a directory AND filename so
|
|
3231
|
+
// it has to be handled differently.
|
|
3232
|
+
'node_modules/.package-lock.json': NPM$b
|
|
3233
|
+
};
|
|
3234
|
+
const readLockFileByAgent = (() => {
|
|
3235
|
+
function wrapReader(reader) {
|
|
3236
|
+
return async (...args) => {
|
|
3237
|
+
try {
|
|
3238
|
+
return await reader(...args);
|
|
3239
|
+
} catch {}
|
|
3240
|
+
return undefined;
|
|
3241
|
+
};
|
|
3242
|
+
}
|
|
3243
|
+
const binaryReader = wrapReader(shadowNpmInject.readFileBinary);
|
|
3244
|
+
const defaultReader = wrapReader(async lockPath => await shadowNpmInject.readFileUtf8(lockPath));
|
|
3245
|
+
return {
|
|
3246
|
+
[BUN$5]: wrapReader(async (lockPath, agentExecPath) => {
|
|
3247
|
+
const ext = path.extname(lockPath);
|
|
3248
|
+
if (ext === LOCK_EXT$1) {
|
|
3249
|
+
return await defaultReader(lockPath);
|
|
3250
|
+
}
|
|
3251
|
+
if (ext === BINARY_LOCK_EXT) {
|
|
3252
|
+
const lockBuffer = await binaryReader(lockPath);
|
|
3253
|
+
if (lockBuffer) {
|
|
3254
|
+
try {
|
|
3255
|
+
return index_cjs.parse(lockBuffer);
|
|
3256
|
+
} catch {}
|
|
3257
|
+
}
|
|
3258
|
+
// To print a Yarn lockfile to your console without writing it to disk
|
|
3259
|
+
// use `bun bun.lockb`.
|
|
3260
|
+
// https://bun.sh/guides/install/yarnlock
|
|
3261
|
+
return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
|
|
3262
|
+
}
|
|
3263
|
+
return undefined;
|
|
3264
|
+
}),
|
|
3265
|
+
[NPM$b]: defaultReader,
|
|
3266
|
+
[PNPM$8]: defaultReader,
|
|
3267
|
+
[VLT$5]: defaultReader,
|
|
3268
|
+
[YARN_BERRY$5]: defaultReader,
|
|
3269
|
+
[YARN_CLASSIC$6]: defaultReader
|
|
3270
|
+
};
|
|
3271
|
+
})();
|
|
3272
|
+
async function detectPackageEnvironment({
|
|
3273
|
+
cwd = process$1.cwd(),
|
|
3274
|
+
onUnknown
|
|
3275
|
+
} = {}) {
|
|
3276
|
+
let lockPath = await shadowNpmInject.findUp(Object.keys(LOCKS), {
|
|
3277
|
+
cwd
|
|
3278
|
+
});
|
|
3279
|
+
let lockName = lockPath ? path.basename(lockPath) : undefined;
|
|
3280
|
+
const isHiddenLockFile = lockName === '.package-lock.json';
|
|
3281
|
+
const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await shadowNpmInject.findUp('package.json', {
|
|
3282
|
+
cwd
|
|
3283
|
+
});
|
|
3284
|
+
const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
|
|
3285
|
+
const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
|
|
3286
|
+
editable: true
|
|
3287
|
+
}) : undefined;
|
|
3288
|
+
const pkgJson = editablePkgJson?.content;
|
|
3289
|
+
// Read Corepack `packageManager` field in package.json:
|
|
3290
|
+
// https://nodejs.org/api/packages.html#packagemanager
|
|
3291
|
+
const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
|
|
3292
|
+
let agent;
|
|
3293
|
+
let agentVersion;
|
|
3294
|
+
if (pkgManager) {
|
|
3295
|
+
const atSignIndex = pkgManager.lastIndexOf('@');
|
|
3296
|
+
if (atSignIndex !== -1) {
|
|
3297
|
+
const name = pkgManager.slice(0, atSignIndex);
|
|
3298
|
+
const version = pkgManager.slice(atSignIndex + 1);
|
|
3299
|
+
if (version && AGENTS.includes(name)) {
|
|
3300
|
+
agent = name;
|
|
3301
|
+
agentVersion = semver.coerce(version) ?? undefined;
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
|
|
3306
|
+
agent = LOCKS[lockName];
|
|
3307
|
+
}
|
|
3308
|
+
if (agent === undefined) {
|
|
3309
|
+
agent = NPM$b;
|
|
3310
|
+
onUnknown?.(pkgManager);
|
|
3311
|
+
}
|
|
3312
|
+
const agentExecPath = await getAgentExecPath(agent);
|
|
3313
|
+
const npmExecPath = agent === NPM$b ? agentExecPath : await getAgentExecPath(NPM$b);
|
|
3314
|
+
if (agentVersion === undefined) {
|
|
3315
|
+
agentVersion = await getAgentVersion(agentExecPath, cwd);
|
|
3316
|
+
}
|
|
3317
|
+
if (agent === YARN_CLASSIC$6 && (agentVersion?.major ?? 0) > 1) {
|
|
3318
|
+
agent = YARN_BERRY$5;
|
|
3319
|
+
}
|
|
3320
|
+
const targets = {
|
|
3321
|
+
browser: false,
|
|
3322
|
+
node: true
|
|
3323
|
+
};
|
|
3324
|
+
let lockSrc;
|
|
3325
|
+
// Lazily access constants.maintainedNodeVersions.
|
|
3326
|
+
let minimumNodeVersion = constants.maintainedNodeVersions.last;
|
|
3327
|
+
if (pkgJson) {
|
|
3328
|
+
const browserField = pkgJson.browser;
|
|
3329
|
+
if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
|
|
3330
|
+
targets.browser = true;
|
|
3331
|
+
}
|
|
3332
|
+
const nodeRange = pkgJson.engines?.['node'];
|
|
3333
|
+
if (strings.isNonEmptyString(nodeRange)) {
|
|
3334
|
+
const coerced = semver.coerce(nodeRange);
|
|
3335
|
+
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
3336
|
+
minimumNodeVersion = coerced.version;
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
const browserslistQuery = pkgJson['browserslist'];
|
|
3340
|
+
if (Array.isArray(browserslistQuery)) {
|
|
3341
|
+
const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
|
|
3342
|
+
const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
|
|
3343
|
+
if (!targets.browser && browserslistTargets.length) {
|
|
3344
|
+
targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
|
|
3345
|
+
}
|
|
3346
|
+
if (browserslistNodeTargets.length) {
|
|
3347
|
+
const coerced = semver.coerce(browserslistNodeTargets[0]);
|
|
3348
|
+
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
3349
|
+
minimumNodeVersion = coerced.version;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
// Lazily access constants.maintainedNodeVersions.
|
|
3354
|
+
targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
|
|
3355
|
+
lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
|
|
3356
|
+
} else {
|
|
3357
|
+
lockName = undefined;
|
|
3358
|
+
lockPath = undefined;
|
|
3359
|
+
}
|
|
3360
|
+
const pkgSupported = targets.browser || targets.node;
|
|
3361
|
+
const npmBuggyOverrides = agent === NPM$b && !!agentVersion && semver.lt(agentVersion, NPM_BUGGY_OVERRIDES_PATCHED_VERSION$1);
|
|
3362
|
+
return {
|
|
3363
|
+
agent,
|
|
3364
|
+
agentExecPath,
|
|
3365
|
+
agentVersion,
|
|
3366
|
+
lockName,
|
|
3367
|
+
lockPath,
|
|
3368
|
+
lockSrc,
|
|
3369
|
+
minimumNodeVersion,
|
|
3370
|
+
npmExecPath,
|
|
3371
|
+
pkgJson: editablePkgJson,
|
|
3372
|
+
pkgPath,
|
|
3373
|
+
pkgSupported,
|
|
3374
|
+
features: {
|
|
3375
|
+
npmBuggyOverrides
|
|
3376
|
+
},
|
|
3377
|
+
targets
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
3381
|
+
const {
|
|
3382
|
+
cmdName = '',
|
|
3383
|
+
logger,
|
|
3384
|
+
prod
|
|
3385
|
+
} = {
|
|
3386
|
+
__proto__: null,
|
|
3387
|
+
...options
|
|
3388
|
+
};
|
|
3389
|
+
const details = await detectPackageEnvironment({
|
|
3390
|
+
cwd,
|
|
3391
|
+
onUnknown(pkgManager) {
|
|
3392
|
+
logger?.warn(cmdPrefixMessage(cmdName, `Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`));
|
|
3393
|
+
}
|
|
3394
|
+
});
|
|
3395
|
+
if (!details.pkgSupported) {
|
|
3396
|
+
logger?.fail(cmdPrefixMessage(cmdName, 'No supported Node or browser range detected'));
|
|
3397
|
+
return;
|
|
3398
|
+
}
|
|
3399
|
+
if (details.agent === VLT$5) {
|
|
3400
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${details.agent} does not support overrides. Soon, though ⚡`));
|
|
3401
|
+
return;
|
|
3402
|
+
}
|
|
3403
|
+
const lockName = details.lockName ?? 'lock file';
|
|
3404
|
+
if (details.lockName === undefined || details.lockSrc === undefined) {
|
|
3405
|
+
logger?.fail(cmdPrefixMessage(cmdName, `No ${lockName} found`));
|
|
3406
|
+
return;
|
|
3407
|
+
}
|
|
3408
|
+
if (details.lockSrc.trim() === '') {
|
|
3409
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${lockName} is empty`));
|
|
3410
|
+
return;
|
|
3411
|
+
}
|
|
3412
|
+
if (details.pkgPath === undefined) {
|
|
3413
|
+
logger?.fail(cmdPrefixMessage(cmdName, 'No package.json found'));
|
|
3414
|
+
return;
|
|
3415
|
+
}
|
|
3416
|
+
if (prod && (details.agent === BUN$5 || details.agent === YARN_BERRY$5)) {
|
|
3417
|
+
logger?.fail(cmdPrefixMessage(cmdName, `--prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.version}` : ''}`));
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
|
|
3421
|
+
logger?.warn(cmdPrefixMessage(cmdName, `Package ${lockName} found at ${details.lockPath}`));
|
|
3422
|
+
}
|
|
3423
|
+
return details;
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
const {
|
|
3427
|
+
NPM: NPM$a,
|
|
3428
|
+
PNPM: PNPM$7
|
|
3429
|
+
} = constants;
|
|
3430
|
+
const CMD_NAME$1 = 'socket fix';
|
|
3431
|
+
async function runFix() {
|
|
3432
|
+
// Lazily access constants.spinner.
|
|
3433
|
+
const {
|
|
3434
|
+
spinner
|
|
3435
|
+
} = constants;
|
|
3436
|
+
spinner.start();
|
|
3437
|
+
const cwd = process.cwd();
|
|
3438
|
+
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
3439
|
+
cmdName: CMD_NAME$1,
|
|
3440
|
+
logger: logger.logger
|
|
3441
|
+
});
|
|
3442
|
+
if (!pkgEnvDetails) {
|
|
3443
|
+
spinner.stop();
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3446
|
+
switch (pkgEnvDetails.agent) {
|
|
3447
|
+
case NPM$a:
|
|
3448
|
+
{
|
|
3449
|
+
await npmFix(pkgEnvDetails, cwd);
|
|
3450
|
+
break;
|
|
3451
|
+
}
|
|
3452
|
+
case PNPM$7:
|
|
3453
|
+
{
|
|
3454
|
+
await pnpmFix(pkgEnvDetails, cwd);
|
|
3455
|
+
break;
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
spinner.successAndStop('Socket.dev fix successful');
|
|
3459
|
+
}
|
|
3460
|
+
|
|
3461
|
+
const {
|
|
3462
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$s
|
|
3463
|
+
} = constants;
|
|
3464
|
+
const config$t = {
|
|
3465
|
+
commandName: 'fix',
|
|
3466
|
+
description: 'Fix "fixable" Socket alerts',
|
|
3467
|
+
hidden: true,
|
|
3468
|
+
flags: {
|
|
3469
|
+
...commonFlags
|
|
3470
|
+
},
|
|
3471
|
+
help: (command, config) => `
|
|
3472
|
+
Usage
|
|
3473
|
+
$ ${command}
|
|
3474
|
+
|
|
3475
|
+
Options
|
|
3476
|
+
${getFlagListOutput(config.flags, 6)}
|
|
3477
|
+
`
|
|
3478
|
+
};
|
|
3479
|
+
const cmdFix = {
|
|
3480
|
+
description: config$t.description,
|
|
3481
|
+
hidden: config$t.hidden,
|
|
3482
|
+
run: run$t
|
|
3483
|
+
};
|
|
3484
|
+
async function run$t(argv, importMeta, {
|
|
3485
|
+
parentName
|
|
3486
|
+
}) {
|
|
3487
|
+
const cli = meowOrExit({
|
|
3488
|
+
argv,
|
|
3489
|
+
config: config$t,
|
|
3490
|
+
importMeta,
|
|
3491
|
+
parentName
|
|
3492
|
+
});
|
|
3493
|
+
if (cli.flags['dryRun']) {
|
|
3494
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$s);
|
|
3495
|
+
return;
|
|
3496
|
+
}
|
|
3497
|
+
await runFix();
|
|
3498
|
+
}
|
|
3499
|
+
|
|
3500
|
+
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
3501
|
+
const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
3502
|
+
const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
|
|
3503
|
+
const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
|
|
3504
|
+
if (result.success === false) {
|
|
3505
|
+
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
3506
|
+
}
|
|
3507
|
+
if (scoreResult.success === false) {
|
|
3508
|
+
return handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult);
|
|
3509
|
+
}
|
|
3510
|
+
const severityCount = shadowNpmInject.getSeverityCount(result.data, includeAllIssues ? undefined : 'high');
|
|
3511
|
+
return {
|
|
3512
|
+
data: result.data,
|
|
3513
|
+
severityCount,
|
|
3514
|
+
score: scoreResult.data
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
const {
|
|
3519
|
+
NPM: NPM$9
|
|
3520
|
+
} = registryConstants;
|
|
3521
|
+
function formatScore(score) {
|
|
3522
|
+
if (score > 80) {
|
|
3523
|
+
return colors.green(`${score}`);
|
|
3524
|
+
} else if (score < 80 && score > 60) {
|
|
3525
|
+
return colors.yellow(`${score}`);
|
|
3526
|
+
}
|
|
3527
|
+
return colors.red(`${score}`);
|
|
3528
|
+
}
|
|
3529
|
+
function logPackageIssuesDetails(packageData, outputMarkdown) {
|
|
3530
|
+
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.SEVERITY.critical || d.value?.severity === shadowNpmInject.SEVERITY.high);
|
|
3531
|
+
const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
|
|
3532
|
+
const {
|
|
3533
|
+
type
|
|
3534
|
+
} = issue;
|
|
3535
|
+
if (type) {
|
|
3536
|
+
const details = acc.get(type);
|
|
3537
|
+
if (details) {
|
|
3538
|
+
details.count += 1;
|
|
3539
|
+
} else {
|
|
3540
|
+
acc.set(type, {
|
|
3541
|
+
label: issue.value?.label ?? '',
|
|
3542
|
+
count: 1
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
return acc;
|
|
3547
|
+
}, new Map());
|
|
3548
|
+
const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
|
|
3549
|
+
for (const [type, details] of uniqueIssueDetails.entries()) {
|
|
3550
|
+
const issueWithLink = format.hyperlink(details.label, shadowNpmInject.getSocketDevAlertUrl(type), {
|
|
3551
|
+
fallbackToUrl: true
|
|
3552
|
+
});
|
|
3553
|
+
if (details.count === 1) {
|
|
3554
|
+
logger.logger.log(`- ${issueWithLink}`);
|
|
3555
|
+
} else {
|
|
3556
|
+
logger.logger.log(`- ${issueWithLink}: ${details.count}`);
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
function logPackageInfo({
|
|
3561
|
+
data,
|
|
3562
|
+
score,
|
|
3563
|
+
severityCount
|
|
3564
|
+
}, {
|
|
3565
|
+
name,
|
|
3566
|
+
outputKind,
|
|
3567
|
+
pkgName,
|
|
3568
|
+
pkgVersion
|
|
3569
|
+
}) {
|
|
3570
|
+
if (outputKind === 'json') {
|
|
3033
3571
|
logger.logger.log(JSON.stringify(data, undefined, 2));
|
|
3034
3572
|
return;
|
|
3035
3573
|
}
|
|
3036
3574
|
if (outputKind === 'markdown') {
|
|
3037
|
-
logger.logger.log(
|
|
3038
|
-
|
|
3575
|
+
logger.logger.log(commonTags.stripIndents`
|
|
3576
|
+
# Package report for ${pkgName}
|
|
3577
|
+
|
|
3578
|
+
Package report card:
|
|
3579
|
+
`);
|
|
3039
3580
|
} else {
|
|
3040
|
-
logger.logger.log(
|
|
3581
|
+
logger.logger.log(`Package report card for ${pkgName}:`);
|
|
3041
3582
|
}
|
|
3042
3583
|
const scoreResult = {
|
|
3043
3584
|
'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),
|
|
@@ -3046,72 +3587,35 @@ function formatPackageInfo({
|
|
|
3046
3587
|
Vulnerabilities: Math.floor(score.vulnerability.score * 100),
|
|
3047
3588
|
License: Math.floor(score.license.score * 100)
|
|
3048
3589
|
};
|
|
3590
|
+
logger.logger.log('\n');
|
|
3049
3591
|
Object.entries(scoreResult).map(score => logger.logger.log(`- ${score[0]}: ${formatScore(score[1])}`));
|
|
3050
3592
|
logger.logger.log('\n');
|
|
3051
|
-
if (
|
|
3593
|
+
if (objects.hasKeys(severityCount)) {
|
|
3052
3594
|
if (outputKind === 'markdown') {
|
|
3053
3595
|
logger.logger.log('# Issues\n');
|
|
3054
3596
|
}
|
|
3055
|
-
logger.logger.log(`Package has these issues: ${formatSeverityCount(severityCount)}\n`);
|
|
3056
|
-
|
|
3597
|
+
logger.logger.log(`Package has these issues: ${shadowNpmInject.formatSeverityCount(severityCount)}\n`);
|
|
3598
|
+
logPackageIssuesDetails(data, outputKind === 'markdown');
|
|
3057
3599
|
} else {
|
|
3058
3600
|
logger.logger.log('Package has no issues');
|
|
3059
3601
|
}
|
|
3060
3602
|
const format = new shadowNpmInject.ColorOrMarkdown(outputKind === 'markdown');
|
|
3061
|
-
const url = shadowNpmInject.getSocketDevPackageOverviewUrl(NPM$
|
|
3062
|
-
logger.logger.log('\n');
|
|
3063
|
-
if (pkgVersion === 'latest') {
|
|
3064
|
-
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, {
|
|
3065
|
-
fallbackToUrl: true
|
|
3066
|
-
})}`);
|
|
3067
|
-
} else {
|
|
3068
|
-
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, {
|
|
3069
|
-
fallbackToUrl: true
|
|
3070
|
-
})}`);
|
|
3071
|
-
}
|
|
3072
|
-
if (outputKind !== 'markdown') {
|
|
3073
|
-
logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`));
|
|
3074
|
-
} else {
|
|
3075
|
-
logger.logger.log('');
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
function formatPackageIssuesDetails(packageData, outputMarkdown) {
|
|
3079
|
-
const issueDetails = packageData.filter(d => d.value?.severity === 'high' || d.value?.severity === 'critical');
|
|
3080
|
-
const uniqueIssues = issueDetails.reduce((acc, issue) => {
|
|
3081
|
-
const {
|
|
3082
|
-
type
|
|
3083
|
-
} = issue;
|
|
3084
|
-
if (type) {
|
|
3085
|
-
if (acc[type] === undefined) {
|
|
3086
|
-
acc[type] = {
|
|
3087
|
-
label: issue.value?.label,
|
|
3088
|
-
count: 1
|
|
3089
|
-
};
|
|
3090
|
-
} else {
|
|
3091
|
-
acc[type].count += 1;
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
return acc;
|
|
3095
|
-
}, {});
|
|
3096
|
-
const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
|
|
3097
|
-
for (const issue of Object.keys(uniqueIssues)) {
|
|
3098
|
-
const issueWithLink = format.hyperlink(`${uniqueIssues[issue]?.label}`, shadowNpmInject.getSocketDevAlertUrl(issue), {
|
|
3603
|
+
const url = shadowNpmInject.getSocketDevPackageOverviewUrl(NPM$9, pkgName, pkgVersion);
|
|
3604
|
+
logger.logger.log('\n');
|
|
3605
|
+
if (pkgVersion === 'latest') {
|
|
3606
|
+
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, {
|
|
3099
3607
|
fallbackToUrl: true
|
|
3100
|
-
});
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
}
|
|
3608
|
+
})}`);
|
|
3609
|
+
} else {
|
|
3610
|
+
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, {
|
|
3611
|
+
fallbackToUrl: true
|
|
3612
|
+
})}`);
|
|
3106
3613
|
}
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
} else if (score < 80 && score > 60) {
|
|
3112
|
-
return colors.yellow(`${score}`);
|
|
3614
|
+
if (outputKind !== 'markdown') {
|
|
3615
|
+
logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`));
|
|
3616
|
+
} else {
|
|
3617
|
+
logger.logger.log('');
|
|
3113
3618
|
}
|
|
3114
|
-
return colors.red(`${score}`);
|
|
3115
3619
|
}
|
|
3116
3620
|
|
|
3117
3621
|
async function getPackageInfo({
|
|
@@ -3130,13 +3634,13 @@ async function getPackageInfo({
|
|
|
3130
3634
|
const packageData = await fetchPackageInfo(pkgName, pkgVersion, includeAllIssues);
|
|
3131
3635
|
spinner.successAndStop('Data fetched');
|
|
3132
3636
|
if (packageData) {
|
|
3133
|
-
|
|
3637
|
+
logPackageInfo(packageData, {
|
|
3134
3638
|
name: commandName,
|
|
3135
3639
|
outputKind,
|
|
3136
3640
|
pkgName,
|
|
3137
3641
|
pkgVersion
|
|
3138
3642
|
});
|
|
3139
|
-
if (strict &&
|
|
3643
|
+
if (strict && objects.hasKeys(packageData.severityCount)) {
|
|
3140
3644
|
// Let NodeJS exit gracefully but with exit(1)
|
|
3141
3645
|
process$1.exitCode = 1;
|
|
3142
3646
|
}
|
|
@@ -3338,8 +3842,8 @@ async function run$r(argv, importMeta, {
|
|
|
3338
3842
|
importMeta,
|
|
3339
3843
|
parentName
|
|
3340
3844
|
});
|
|
3341
|
-
|
|
3342
|
-
|
|
3845
|
+
const apiBaseUrl = cli.flags['apiBaseUrl'];
|
|
3846
|
+
const apiProxy = cli.flags['apiProxy'];
|
|
3343
3847
|
if (cli.flags['dryRun']) {
|
|
3344
3848
|
logger.logger.log(DRY_RUN_BAIL_TEXT$q);
|
|
3345
3849
|
return;
|
|
@@ -3808,6 +4312,9 @@ const config$o = {
|
|
|
3808
4312
|
|
|
3809
4313
|
Support is beta. Please report issues or give us feedback on what's missing.
|
|
3810
4314
|
|
|
4315
|
+
This is only for SBT. If your Scala setup uses gradle, please see the help
|
|
4316
|
+
sections for \`socket manifest gradle\` or \`socket cdxgen\`.
|
|
4317
|
+
|
|
3811
4318
|
Examples
|
|
3812
4319
|
|
|
3813
4320
|
$ ${command} ./build.sbt
|
|
@@ -4181,21 +4688,21 @@ async function run$l(argv, importMeta, {
|
|
|
4181
4688
|
}
|
|
4182
4689
|
|
|
4183
4690
|
const {
|
|
4184
|
-
NPM: NPM$
|
|
4691
|
+
NPM: NPM$8
|
|
4185
4692
|
} = constants;
|
|
4186
4693
|
async function wrapNpm(argv) {
|
|
4187
4694
|
// Lazily access constants.distShadowNpmBinPath.
|
|
4188
4695
|
const shadowBin = require(constants.distShadowNpmBinPath);
|
|
4189
|
-
await shadowBin(NPM$
|
|
4696
|
+
await shadowBin(NPM$8, argv);
|
|
4190
4697
|
}
|
|
4191
4698
|
|
|
4192
4699
|
const {
|
|
4193
4700
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$k,
|
|
4194
|
-
NPM: NPM$
|
|
4701
|
+
NPM: NPM$7
|
|
4195
4702
|
} = constants;
|
|
4196
4703
|
const config$k = {
|
|
4197
4704
|
commandName: 'npm',
|
|
4198
|
-
description: `${NPM$
|
|
4705
|
+
description: `${NPM$7} wrapper functionality`,
|
|
4199
4706
|
hidden: false,
|
|
4200
4707
|
flags: {},
|
|
4201
4708
|
help: (command, _config) => `
|
|
@@ -4309,273 +4816,20 @@ async function run$i(argv, importMeta, {
|
|
|
4309
4816
|
}
|
|
4310
4817
|
|
|
4311
4818
|
const {
|
|
4312
|
-
BUN: BUN$
|
|
4313
|
-
NPM: NPM$
|
|
4314
|
-
PNPM: PNPM$7,
|
|
4315
|
-
VLT: VLT$6,
|
|
4316
|
-
YARN_BERRY: YARN_BERRY$6,
|
|
4317
|
-
YARN_CLASSIC: YARN_CLASSIC$6
|
|
4318
|
-
} = constants;
|
|
4319
|
-
function matchHumanStdout(stdout, name) {
|
|
4320
|
-
return stdout.includes(` ${name}@`);
|
|
4321
|
-
}
|
|
4322
|
-
function matchQueryStdout(stdout, name) {
|
|
4323
|
-
return stdout.includes(`"${name}"`);
|
|
4324
|
-
}
|
|
4325
|
-
const depsIncludesByAgent = new Map([[BUN$6, matchHumanStdout], [NPM$9, matchQueryStdout], [PNPM$7, matchQueryStdout], [VLT$6, matchQueryStdout], [YARN_BERRY$6, matchHumanStdout], [YARN_CLASSIC$6, matchHumanStdout]]);
|
|
4326
|
-
|
|
4327
|
-
const {
|
|
4328
|
-
BINARY_LOCK_EXT,
|
|
4329
|
-
BUN: BUN$5,
|
|
4330
|
-
LOCK_EXT: LOCK_EXT$1,
|
|
4331
|
-
NPM: NPM$8,
|
|
4819
|
+
BUN: BUN$4,
|
|
4820
|
+
NPM: NPM$6,
|
|
4332
4821
|
PNPM: PNPM$6,
|
|
4333
|
-
VLT: VLT$
|
|
4334
|
-
|
|
4335
|
-
YARN_BERRY: YARN_BERRY$5,
|
|
4822
|
+
VLT: VLT$4,
|
|
4823
|
+
YARN_BERRY: YARN_BERRY$4,
|
|
4336
4824
|
YARN_CLASSIC: YARN_CLASSIC$5
|
|
4337
4825
|
} = constants;
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
__proto__: null,
|
|
4341
|
-
[BUN$5]: BUN$5,
|
|
4342
|
-
[NPM$8]: NPM$8,
|
|
4343
|
-
[PNPM$6]: PNPM$6,
|
|
4344
|
-
[YARN_BERRY$5]: YARN,
|
|
4345
|
-
[YARN_CLASSIC$5]: YARN,
|
|
4346
|
-
[VLT$5]: VLT$5
|
|
4347
|
-
};
|
|
4348
|
-
async function getAgentExecPath(agent) {
|
|
4349
|
-
const binName = binByAgent[agent];
|
|
4350
|
-
return (await which(binName, {
|
|
4351
|
-
nothrow: true
|
|
4352
|
-
})) ?? binName;
|
|
4353
|
-
}
|
|
4354
|
-
async function getAgentVersion(agentExecPath, cwd) {
|
|
4355
|
-
let result;
|
|
4356
|
-
try {
|
|
4357
|
-
result = semver.coerce(
|
|
4358
|
-
// All package managers support the "--version" flag.
|
|
4359
|
-
(await spawn.spawn(agentExecPath, ['--version'], {
|
|
4360
|
-
cwd
|
|
4361
|
-
})).stdout) ?? undefined;
|
|
4362
|
-
} catch {}
|
|
4363
|
-
return result;
|
|
4364
|
-
}
|
|
4365
|
-
|
|
4366
|
-
// The order of LOCKS properties IS significant as it affects iteration order.
|
|
4367
|
-
const LOCKS = {
|
|
4368
|
-
[`bun${LOCK_EXT$1}`]: BUN$5,
|
|
4369
|
-
[`bun${BINARY_LOCK_EXT}`]: BUN$5,
|
|
4370
|
-
// If both package-lock.json and npm-shrinkwrap.json are present in the root
|
|
4371
|
-
// of a project, npm-shrinkwrap.json will take precedence and package-lock.json
|
|
4372
|
-
// will be ignored.
|
|
4373
|
-
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
|
|
4374
|
-
'npm-shrinkwrap.json': NPM$8,
|
|
4375
|
-
'package-lock.json': NPM$8,
|
|
4376
|
-
'pnpm-lock.yaml': PNPM$6,
|
|
4377
|
-
'pnpm-lock.yml': PNPM$6,
|
|
4378
|
-
[`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$5,
|
|
4379
|
-
'vlt-lock.json': VLT$5,
|
|
4380
|
-
// Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
|
|
4381
|
-
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
|
|
4382
|
-
//
|
|
4383
|
-
// Unlike the other LOCKS keys this key contains a directory AND filename so
|
|
4384
|
-
// it has to be handled differently.
|
|
4385
|
-
'node_modules/.package-lock.json': NPM$8
|
|
4386
|
-
};
|
|
4387
|
-
const readLockFileByAgent = (() => {
|
|
4388
|
-
function wrapReader(reader) {
|
|
4389
|
-
return async (...args) => {
|
|
4390
|
-
try {
|
|
4391
|
-
return await reader(...args);
|
|
4392
|
-
} catch {}
|
|
4393
|
-
return undefined;
|
|
4394
|
-
};
|
|
4395
|
-
}
|
|
4396
|
-
const binaryReader = wrapReader(shadowNpmInject.readFileBinary);
|
|
4397
|
-
const defaultReader = wrapReader(async lockPath => await shadowNpmInject.readFileUtf8(lockPath));
|
|
4398
|
-
return {
|
|
4399
|
-
[BUN$5]: wrapReader(async (lockPath, agentExecPath) => {
|
|
4400
|
-
const ext = path.extname(lockPath);
|
|
4401
|
-
if (ext === LOCK_EXT$1) {
|
|
4402
|
-
return await defaultReader(lockPath);
|
|
4403
|
-
}
|
|
4404
|
-
if (ext === BINARY_LOCK_EXT) {
|
|
4405
|
-
const lockBuffer = await binaryReader(lockPath);
|
|
4406
|
-
if (lockBuffer) {
|
|
4407
|
-
try {
|
|
4408
|
-
return index_cjs.parse(lockBuffer);
|
|
4409
|
-
} catch {}
|
|
4410
|
-
}
|
|
4411
|
-
// To print a Yarn lockfile to your console without writing it to disk
|
|
4412
|
-
// use `bun bun.lockb`.
|
|
4413
|
-
// https://bun.sh/guides/install/yarnlock
|
|
4414
|
-
return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
|
|
4415
|
-
}
|
|
4416
|
-
return undefined;
|
|
4417
|
-
}),
|
|
4418
|
-
[NPM$8]: defaultReader,
|
|
4419
|
-
[PNPM$6]: defaultReader,
|
|
4420
|
-
[VLT$5]: defaultReader,
|
|
4421
|
-
[YARN_BERRY$5]: defaultReader,
|
|
4422
|
-
[YARN_CLASSIC$5]: defaultReader
|
|
4423
|
-
};
|
|
4424
|
-
})();
|
|
4425
|
-
async function detectPackageEnvironment({
|
|
4426
|
-
cwd = process$1.cwd(),
|
|
4427
|
-
onUnknown
|
|
4428
|
-
} = {}) {
|
|
4429
|
-
let lockPath = await shadowNpmInject.findUp(Object.keys(LOCKS), {
|
|
4430
|
-
cwd
|
|
4431
|
-
});
|
|
4432
|
-
let lockName = lockPath ? path.basename(lockPath) : undefined;
|
|
4433
|
-
const isHiddenLockFile = lockName === '.package-lock.json';
|
|
4434
|
-
const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await shadowNpmInject.findUp('package.json', {
|
|
4435
|
-
cwd
|
|
4436
|
-
});
|
|
4437
|
-
const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
|
|
4438
|
-
const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
|
|
4439
|
-
editable: true
|
|
4440
|
-
}) : undefined;
|
|
4441
|
-
const pkgJson = editablePkgJson?.content;
|
|
4442
|
-
// Read Corepack `packageManager` field in package.json:
|
|
4443
|
-
// https://nodejs.org/api/packages.html#packagemanager
|
|
4444
|
-
const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
|
|
4445
|
-
let agent;
|
|
4446
|
-
let agentVersion;
|
|
4447
|
-
if (pkgManager) {
|
|
4448
|
-
const atSignIndex = pkgManager.lastIndexOf('@');
|
|
4449
|
-
if (atSignIndex !== -1) {
|
|
4450
|
-
const name = pkgManager.slice(0, atSignIndex);
|
|
4451
|
-
const version = pkgManager.slice(atSignIndex + 1);
|
|
4452
|
-
if (version && AGENTS.includes(name)) {
|
|
4453
|
-
agent = name;
|
|
4454
|
-
agentVersion = semver.coerce(version) ?? undefined;
|
|
4455
|
-
}
|
|
4456
|
-
}
|
|
4457
|
-
}
|
|
4458
|
-
if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
|
|
4459
|
-
agent = LOCKS[lockName];
|
|
4460
|
-
}
|
|
4461
|
-
if (agent === undefined) {
|
|
4462
|
-
agent = NPM$8;
|
|
4463
|
-
onUnknown?.(pkgManager);
|
|
4464
|
-
}
|
|
4465
|
-
const agentExecPath = await getAgentExecPath(agent);
|
|
4466
|
-
const npmExecPath = agent === NPM$8 ? agentExecPath : await getAgentExecPath(NPM$8);
|
|
4467
|
-
if (agentVersion === undefined) {
|
|
4468
|
-
agentVersion = await getAgentVersion(agentExecPath, cwd);
|
|
4469
|
-
}
|
|
4470
|
-
if (agent === YARN_CLASSIC$5 && (agentVersion?.major ?? 0) > 1) {
|
|
4471
|
-
agent = YARN_BERRY$5;
|
|
4472
|
-
}
|
|
4473
|
-
const targets = {
|
|
4474
|
-
browser: false,
|
|
4475
|
-
node: true
|
|
4476
|
-
};
|
|
4477
|
-
let lockSrc;
|
|
4478
|
-
// Lazily access constants.maintainedNodeVersions.
|
|
4479
|
-
let minimumNodeVersion = constants.maintainedNodeVersions.previous;
|
|
4480
|
-
if (pkgJson) {
|
|
4481
|
-
const browserField = pkgJson.browser;
|
|
4482
|
-
if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
|
|
4483
|
-
targets.browser = true;
|
|
4484
|
-
}
|
|
4485
|
-
const nodeRange = pkgJson.engines?.['node'];
|
|
4486
|
-
if (strings.isNonEmptyString(nodeRange)) {
|
|
4487
|
-
const coerced = semver.coerce(nodeRange);
|
|
4488
|
-
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
4489
|
-
minimumNodeVersion = coerced.version;
|
|
4490
|
-
}
|
|
4491
|
-
}
|
|
4492
|
-
const browserslistQuery = pkgJson['browserslist'];
|
|
4493
|
-
if (Array.isArray(browserslistQuery)) {
|
|
4494
|
-
const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
|
|
4495
|
-
const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
|
|
4496
|
-
if (!targets.browser && browserslistTargets.length) {
|
|
4497
|
-
targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
|
|
4498
|
-
}
|
|
4499
|
-
if (browserslistNodeTargets.length) {
|
|
4500
|
-
const coerced = semver.coerce(browserslistNodeTargets[0]);
|
|
4501
|
-
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
4502
|
-
minimumNodeVersion = coerced.version;
|
|
4503
|
-
}
|
|
4504
|
-
}
|
|
4505
|
-
}
|
|
4506
|
-
// Lazily access constants.maintainedNodeVersions.
|
|
4507
|
-
targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
|
|
4508
|
-
lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
|
|
4509
|
-
} else {
|
|
4510
|
-
lockName = undefined;
|
|
4511
|
-
lockPath = undefined;
|
|
4512
|
-
}
|
|
4513
|
-
return {
|
|
4514
|
-
agent,
|
|
4515
|
-
agentExecPath,
|
|
4516
|
-
agentVersion,
|
|
4517
|
-
lockName,
|
|
4518
|
-
lockPath,
|
|
4519
|
-
lockSrc,
|
|
4520
|
-
minimumNodeVersion,
|
|
4521
|
-
npmExecPath,
|
|
4522
|
-
pkgJson: editablePkgJson,
|
|
4523
|
-
pkgPath,
|
|
4524
|
-
supported: targets.browser || targets.node,
|
|
4525
|
-
targets
|
|
4526
|
-
};
|
|
4826
|
+
function matchLsCmdViewHumanStdout(stdout, name) {
|
|
4827
|
+
return stdout.includes(` ${name}@`);
|
|
4527
4828
|
}
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
BUN: BUN$4,
|
|
4531
|
-
VLT: VLT$4,
|
|
4532
|
-
YARN_BERRY: YARN_BERRY$4
|
|
4533
|
-
} = constants;
|
|
4534
|
-
const COMMAND_TITLE$2 = 'Socket Optimize';
|
|
4535
|
-
async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
4536
|
-
const {
|
|
4537
|
-
logger,
|
|
4538
|
-
prod
|
|
4539
|
-
} = {
|
|
4540
|
-
__proto__: null,
|
|
4541
|
-
...options
|
|
4542
|
-
};
|
|
4543
|
-
const details = await detectPackageEnvironment({
|
|
4544
|
-
cwd,
|
|
4545
|
-
onUnknown(pkgManager) {
|
|
4546
|
-
logger?.warn(`${COMMAND_TITLE$2}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`);
|
|
4547
|
-
}
|
|
4548
|
-
});
|
|
4549
|
-
if (!details.supported) {
|
|
4550
|
-
logger?.fail(`${COMMAND_TITLE$2}: No supported Node or browser range detected`);
|
|
4551
|
-
return;
|
|
4552
|
-
}
|
|
4553
|
-
if (details.agent === VLT$4) {
|
|
4554
|
-
logger?.fail(`${COMMAND_TITLE$2}: ${details.agent} does not support overrides. Soon, though ⚡`);
|
|
4555
|
-
return;
|
|
4556
|
-
}
|
|
4557
|
-
const lockName = details.lockName ?? 'lock file';
|
|
4558
|
-
if (details.lockName === undefined || details.lockSrc === undefined) {
|
|
4559
|
-
logger?.fail(`${COMMAND_TITLE$2}: No ${lockName} found`);
|
|
4560
|
-
return;
|
|
4561
|
-
}
|
|
4562
|
-
if (details.lockSrc.trim() === '') {
|
|
4563
|
-
logger?.fail(`${COMMAND_TITLE$2}: ${lockName} is empty`);
|
|
4564
|
-
return;
|
|
4565
|
-
}
|
|
4566
|
-
if (details.pkgPath === undefined) {
|
|
4567
|
-
logger?.fail(`${COMMAND_TITLE$2}: No package.json found`);
|
|
4568
|
-
return;
|
|
4569
|
-
}
|
|
4570
|
-
if (prod && (details.agent === BUN$4 || details.agent === YARN_BERRY$4)) {
|
|
4571
|
-
logger?.fail(`${COMMAND_TITLE$2}: --prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.toString()}` : ''}`);
|
|
4572
|
-
return;
|
|
4573
|
-
}
|
|
4574
|
-
if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
|
|
4575
|
-
logger?.warn(`${COMMAND_TITLE$2}: Package ${lockName} found at ${details.lockPath}`);
|
|
4576
|
-
}
|
|
4577
|
-
return details;
|
|
4829
|
+
function matchQueryCmdStdout(stdout, name) {
|
|
4830
|
+
return stdout.includes(`"${name}"`);
|
|
4578
4831
|
}
|
|
4832
|
+
const depsIncludesByAgent = new Map([[BUN$4, matchLsCmdViewHumanStdout], [NPM$6, matchQueryCmdStdout], [PNPM$6, matchQueryCmdStdout], [VLT$4, matchQueryCmdStdout], [YARN_BERRY$4, matchLsCmdViewHumanStdout], [YARN_CLASSIC$5, matchLsCmdViewHumanStdout]]);
|
|
4579
4833
|
|
|
4580
4834
|
function getDependencyEntries(pkgJson) {
|
|
4581
4835
|
const {
|
|
@@ -4603,7 +4857,7 @@ function getDependencyEntries(pkgJson) {
|
|
|
4603
4857
|
|
|
4604
4858
|
const {
|
|
4605
4859
|
BUN: BUN$3,
|
|
4606
|
-
NPM: NPM$
|
|
4860
|
+
NPM: NPM$5,
|
|
4607
4861
|
OVERRIDES: OVERRIDES$1,
|
|
4608
4862
|
PNPM: PNPM$5,
|
|
4609
4863
|
RESOLUTIONS: RESOLUTIONS$1,
|
|
@@ -4624,7 +4878,7 @@ function getOverridesDataBun(pkgJson) {
|
|
|
4624
4878
|
function getOverridesDataNpm(pkgJson) {
|
|
4625
4879
|
const overrides = pkgJson?.[OVERRIDES$1] ?? {};
|
|
4626
4880
|
return {
|
|
4627
|
-
type: NPM$
|
|
4881
|
+
type: NPM$5,
|
|
4628
4882
|
overrides
|
|
4629
4883
|
};
|
|
4630
4884
|
}
|
|
@@ -4665,7 +4919,7 @@ function getOverridesDataClassic(pkgJson) {
|
|
|
4665
4919
|
overrides
|
|
4666
4920
|
};
|
|
4667
4921
|
}
|
|
4668
|
-
const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$
|
|
4922
|
+
const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$5, getOverridesDataNpm], [PNPM$5, getOverridesDataPnpm], [VLT$3, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataClassic]]);
|
|
4669
4923
|
|
|
4670
4924
|
const {
|
|
4671
4925
|
PNPM: PNPM$4
|
|
@@ -4713,26 +4967,26 @@ function workspacePatternToGlobPattern(workspace) {
|
|
|
4713
4967
|
const {
|
|
4714
4968
|
BUN: BUN$2,
|
|
4715
4969
|
LOCK_EXT,
|
|
4716
|
-
NPM: NPM$
|
|
4970
|
+
NPM: NPM$4,
|
|
4717
4971
|
PNPM: PNPM$3,
|
|
4718
4972
|
VLT: VLT$2,
|
|
4719
4973
|
YARN_BERRY: YARN_BERRY$2,
|
|
4720
4974
|
YARN_CLASSIC: YARN_CLASSIC$3
|
|
4721
4975
|
} = constants;
|
|
4722
|
-
function
|
|
4976
|
+
function includesNpm(lockSrc, name) {
|
|
4723
4977
|
// Detects the package name in the following cases:
|
|
4724
4978
|
// "name":
|
|
4725
4979
|
return lockSrc.includes(`"${name}":`);
|
|
4726
4980
|
}
|
|
4727
|
-
function
|
|
4981
|
+
function includesBun(lockSrc, name, lockName) {
|
|
4728
4982
|
// This is a bit counterintuitive. When lockName ends with a .lockb
|
|
4729
4983
|
// we treat it as a yarn.lock. When lockName ends with a .lock we
|
|
4730
4984
|
// treat it as a package-lock.json. The bun.lock format is not identical
|
|
4731
4985
|
// package-lock.json, however it close enough for npmLockIncludes to work.
|
|
4732
|
-
const
|
|
4733
|
-
return
|
|
4986
|
+
const lockfileScanner = lockName?.endsWith(LOCK_EXT) ? includesNpm : includesYarn;
|
|
4987
|
+
return lockfileScanner(lockSrc, name);
|
|
4734
4988
|
}
|
|
4735
|
-
function
|
|
4989
|
+
function includesPnpm(lockSrc, name) {
|
|
4736
4990
|
const escapedName = regexps.escapeRegExp(name);
|
|
4737
4991
|
return new RegExp(
|
|
4738
4992
|
// Detects the package name in the following cases:
|
|
@@ -4742,12 +4996,12 @@ function lockIncludesPnpm(lockSrc, name) {
|
|
|
4742
4996
|
// name@
|
|
4743
4997
|
`(?<=^\\s*)(?:(['/])${escapedName}\\1|${escapedName}(?=[:@]))`, 'm').test(lockSrc);
|
|
4744
4998
|
}
|
|
4745
|
-
function
|
|
4999
|
+
function includesVlt(lockSrc, name) {
|
|
4746
5000
|
// Detects the package name in the following cases:
|
|
4747
5001
|
// "name"
|
|
4748
5002
|
return lockSrc.includes(`"${name}"`);
|
|
4749
5003
|
}
|
|
4750
|
-
function
|
|
5004
|
+
function includesYarn(lockSrc, name) {
|
|
4751
5005
|
const escapedName = regexps.escapeRegExp(name);
|
|
4752
5006
|
return new RegExp(
|
|
4753
5007
|
// Detects the package name in the following cases:
|
|
@@ -4757,11 +5011,11 @@ function lockIncludesYarn(lockSrc, name) {
|
|
|
4757
5011
|
// , name@
|
|
4758
5012
|
`(?<=(?:^\\s*|,\\s*)"?)${escapedName}(?=@)`, 'm').test(lockSrc);
|
|
4759
5013
|
}
|
|
4760
|
-
const
|
|
5014
|
+
const lockfileIncludesByAgent = new Map([[BUN$2, includesBun], [NPM$4, includesNpm], [PNPM$3, includesPnpm], [VLT$2, includesVlt], [YARN_BERRY$2, includesYarn], [YARN_CLASSIC$3, includesYarn]]);
|
|
4761
5015
|
|
|
4762
5016
|
const {
|
|
4763
5017
|
BUN: BUN$1,
|
|
4764
|
-
NPM: NPM$
|
|
5018
|
+
NPM: NPM$3,
|
|
4765
5019
|
PNPM: PNPM$2,
|
|
4766
5020
|
VLT: VLT$1,
|
|
4767
5021
|
YARN_BERRY: YARN_BERRY$1,
|
|
@@ -4797,11 +5051,11 @@ function cleanupQueryStdout(stdout) {
|
|
|
4797
5051
|
}
|
|
4798
5052
|
return JSON.stringify([...names], null, 2);
|
|
4799
5053
|
}
|
|
4800
|
-
function
|
|
5054
|
+
function parsableToQueryStdout(stdout) {
|
|
4801
5055
|
if (stdout === '') {
|
|
4802
5056
|
return '';
|
|
4803
5057
|
}
|
|
4804
|
-
// Convert the
|
|
5058
|
+
// Convert the parsable stdout into a json array of unique names.
|
|
4805
5059
|
// The matchAll regexp looks for a forward (posix) or backward (win32) slash
|
|
4806
5060
|
// and matches one or more non-slashes until the newline.
|
|
4807
5061
|
const names = new Set(stdout.matchAll(/(?<=[/\\])[^/\\]+(?=\n)/g));
|
|
@@ -4831,7 +5085,7 @@ async function lsNpm(agentExecPath, cwd) {
|
|
|
4831
5085
|
}
|
|
4832
5086
|
async function lsPnpm(agentExecPath, cwd, options) {
|
|
4833
5087
|
const npmExecPath = options?.npmExecPath;
|
|
4834
|
-
if (npmExecPath && npmExecPath !== NPM$
|
|
5088
|
+
if (npmExecPath && npmExecPath !== NPM$3) {
|
|
4835
5089
|
const result = await npmQuery(npmExecPath, cwd);
|
|
4836
5090
|
if (result) {
|
|
4837
5091
|
return result;
|
|
@@ -4839,15 +5093,19 @@ async function lsPnpm(agentExecPath, cwd, options) {
|
|
|
4839
5093
|
}
|
|
4840
5094
|
let stdout = '';
|
|
4841
5095
|
try {
|
|
4842
|
-
stdout = (await spawn.spawn(agentExecPath,
|
|
5096
|
+
stdout = (await spawn.spawn(agentExecPath,
|
|
5097
|
+
// Pnpm uses the alternative spelling of parsable.
|
|
5098
|
+
// https://en.wiktionary.org/wiki/parsable
|
|
5099
|
+
['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
|
|
4843
5100
|
cwd
|
|
4844
5101
|
})).stdout;
|
|
4845
5102
|
} catch {}
|
|
4846
|
-
return
|
|
5103
|
+
return parsableToQueryStdout(stdout);
|
|
4847
5104
|
}
|
|
4848
5105
|
async function lsVlt(agentExecPath, cwd) {
|
|
4849
5106
|
let stdout = '';
|
|
4850
5107
|
try {
|
|
5108
|
+
// See https://docs.vlt.sh/cli/commands/list#options.
|
|
4851
5109
|
stdout = (await spawn.spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
|
|
4852
5110
|
cwd
|
|
4853
5111
|
})).stdout;
|
|
@@ -4878,20 +5136,39 @@ async function lsYarnClassic(agentExecPath, cwd) {
|
|
|
4878
5136
|
} catch {}
|
|
4879
5137
|
return '';
|
|
4880
5138
|
}
|
|
4881
|
-
const lsByAgent =
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
5139
|
+
const lsByAgent = new Map([[BUN$1, lsBun], [NPM$3, lsNpm], [PNPM$2, lsPnpm], [VLT$1, lsVlt], [YARN_BERRY$1, lsYarnBerry], [YARN_CLASSIC$2, lsYarnClassic]]);
|
|
5140
|
+
|
|
5141
|
+
const {
|
|
5142
|
+
NPM_BUGGY_OVERRIDES_PATCHED_VERSION
|
|
5143
|
+
} = constants;
|
|
5144
|
+
async function updateLockfile(pkgEnvDetails, options) {
|
|
5145
|
+
const {
|
|
5146
|
+
cmdName = '',
|
|
5147
|
+
logger,
|
|
5148
|
+
spinner
|
|
5149
|
+
} = {
|
|
5150
|
+
__proto__: null,
|
|
5151
|
+
...options
|
|
5152
|
+
};
|
|
5153
|
+
spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
|
|
5154
|
+
try {
|
|
5155
|
+
await runAgentInstall(pkgEnvDetails, {
|
|
5156
|
+
spinner
|
|
5157
|
+
});
|
|
5158
|
+
spinner?.stop();
|
|
5159
|
+
if (pkgEnvDetails.features.npmBuggyOverrides) {
|
|
5160
|
+
logger?.log(`💡 Re-run ${cmdName ? `${cmdName} ` : ''}whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped for ${pkgEnvDetails.agent} >=${NPM_BUGGY_OVERRIDES_PATCHED_VERSION}.`);
|
|
5161
|
+
}
|
|
5162
|
+
} catch (e) {
|
|
5163
|
+
spinner?.stop();
|
|
5164
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`));
|
|
5165
|
+
logger?.error(e);
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
4891
5168
|
|
|
4892
5169
|
const {
|
|
4893
5170
|
BUN,
|
|
4894
|
-
NPM: NPM$
|
|
5171
|
+
NPM: NPM$2,
|
|
4895
5172
|
OVERRIDES,
|
|
4896
5173
|
PNPM: PNPM$1,
|
|
4897
5174
|
RESOLUTIONS,
|
|
@@ -4911,7 +5188,9 @@ function getHighestEntryIndex(entries, keys) {
|
|
|
4911
5188
|
return getEntryIndexes(entries, keys).at(-1) ?? -1;
|
|
4912
5189
|
}
|
|
4913
5190
|
function updatePkgJson(editablePkgJson, field, value) {
|
|
4914
|
-
const
|
|
5191
|
+
const {
|
|
5192
|
+
content: pkgJson
|
|
5193
|
+
} = editablePkgJson;
|
|
4915
5194
|
const oldValue = pkgJson[field];
|
|
4916
5195
|
if (oldValue) {
|
|
4917
5196
|
// The field already exists so we simply update the field value.
|
|
@@ -4995,177 +5274,15 @@ function updateResolutions(editablePkgJson, overrides) {
|
|
|
4995
5274
|
function pnpmUpdatePkgJson(editablePkgJson, overrides) {
|
|
4996
5275
|
updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides);
|
|
4997
5276
|
}
|
|
4998
|
-
const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$
|
|
4999
|
-
|
|
5000
|
-
const {
|
|
5001
|
-
SOCKET_IPC_HANDSHAKE
|
|
5002
|
-
} = constants;
|
|
5003
|
-
function safeNpmInstall(options) {
|
|
5004
|
-
const {
|
|
5005
|
-
args = [],
|
|
5006
|
-
ipc,
|
|
5007
|
-
spinner,
|
|
5008
|
-
...spawnOptions
|
|
5009
|
-
} = {
|
|
5010
|
-
__proto__: null,
|
|
5011
|
-
...options
|
|
5012
|
-
};
|
|
5013
|
-
const terminatorPos = args.indexOf('--');
|
|
5014
|
-
const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
|
|
5015
|
-
const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
|
|
5016
|
-
const useIpc = objects.isObject(ipc);
|
|
5017
|
-
const useDebug = debug.isDebug();
|
|
5018
|
-
const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
|
|
5019
|
-
const spawnPromise = spawn.spawn(
|
|
5020
|
-
// Lazily access constants.execPath.
|
|
5021
|
-
constants.execPath, [
|
|
5022
|
-
// Lazily access constants.nodeNoWarningsFlags.
|
|
5023
|
-
...constants.nodeNoWarningsFlags, '--require',
|
|
5024
|
-
// Lazily access constants.distShadowNpmInjectPath.
|
|
5025
|
-
constants.distShadowNpmInjectPath, shadowNpmPaths.getNpmBinPath(), 'install',
|
|
5026
|
-
// Even though the '--silent' flag is passed npm will still run through
|
|
5027
|
-
// code paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund'
|
|
5028
|
-
// flags are passed.
|
|
5029
|
-
'--no-audit', '--no-fund',
|
|
5030
|
-
// Add `--no-progress` and `--silent` flags to fix input being swallowed
|
|
5031
|
-
// by the spinner when running the command with recent versions of npm.
|
|
5032
|
-
'--no-progress',
|
|
5033
|
-
// Add the '--silent' flag if a loglevel flag is not provided and the
|
|
5034
|
-
// SOCKET_CLI_DEBUG environment variable is not truthy.
|
|
5035
|
-
...(isSilent ? ['--silent'] : []), ...npmArgs, ...otherArgs], {
|
|
5036
|
-
spinner,
|
|
5037
|
-
// Set stdio to include 'ipc'.
|
|
5038
|
-
// See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
|
|
5039
|
-
// and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
|
|
5040
|
-
stdio: isSilent ?
|
|
5041
|
-
// 'ignore'
|
|
5042
|
-
useIpc ? ['ignore', 'ignore', 'ignore', 'ipc'] : 'ignore' :
|
|
5043
|
-
// 'inherit'
|
|
5044
|
-
useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
|
|
5045
|
-
...spawnOptions,
|
|
5046
|
-
env: {
|
|
5047
|
-
...process$1.env,
|
|
5048
|
-
...spawnOptions.env
|
|
5049
|
-
}
|
|
5050
|
-
});
|
|
5051
|
-
if (useIpc) {
|
|
5052
|
-
spawnPromise.process.send({
|
|
5053
|
-
[SOCKET_IPC_HANDSHAKE]: ipc
|
|
5054
|
-
});
|
|
5055
|
-
}
|
|
5056
|
-
return spawnPromise;
|
|
5057
|
-
}
|
|
5058
|
-
|
|
5059
|
-
const {
|
|
5060
|
-
NPM: NPM$3,
|
|
5061
|
-
abortSignal
|
|
5062
|
-
} = constants;
|
|
5063
|
-
function runAgentInstall(agent, agentExecPath, options) {
|
|
5064
|
-
// All package managers support the "install" command.
|
|
5065
|
-
if (agent === NPM$3) {
|
|
5066
|
-
return safeNpmInstall(options);
|
|
5067
|
-
}
|
|
5068
|
-
const {
|
|
5069
|
-
args = [],
|
|
5070
|
-
spinner,
|
|
5071
|
-
...spawnOptions
|
|
5072
|
-
} = {
|
|
5073
|
-
__proto__: null,
|
|
5074
|
-
...options
|
|
5075
|
-
};
|
|
5076
|
-
const isSilent = !debug.isDebug();
|
|
5077
|
-
return spawn.spawn(agentExecPath, ['install', ...args], {
|
|
5078
|
-
signal: abortSignal,
|
|
5079
|
-
spinner,
|
|
5080
|
-
stdio: isSilent ? 'ignore' : 'inherit',
|
|
5081
|
-
...spawnOptions,
|
|
5082
|
-
env: {
|
|
5083
|
-
...process.env,
|
|
5084
|
-
...spawnOptions.env
|
|
5085
|
-
}
|
|
5086
|
-
});
|
|
5087
|
-
}
|
|
5088
|
-
|
|
5089
|
-
const {
|
|
5090
|
-
NPM: NPM$2
|
|
5091
|
-
} = constants;
|
|
5092
|
-
const COMMAND_TITLE$1 = 'Socket Optimize';
|
|
5093
|
-
async function updatePackageLockJson(pkgEnvDetails, options) {
|
|
5094
|
-
const {
|
|
5095
|
-
logger,
|
|
5096
|
-
spinner
|
|
5097
|
-
} = {
|
|
5098
|
-
__proto__: null,
|
|
5099
|
-
...options
|
|
5100
|
-
};
|
|
5101
|
-
spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
|
|
5102
|
-
try {
|
|
5103
|
-
await runAgentInstall(pkgEnvDetails.agent, pkgEnvDetails.agentExecPath, {
|
|
5104
|
-
spinner
|
|
5105
|
-
});
|
|
5106
|
-
spinner?.stop();
|
|
5107
|
-
if (pkgEnvDetails.agent === NPM$2) {
|
|
5108
|
-
logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
|
|
5109
|
-
}
|
|
5110
|
-
} catch (e) {
|
|
5111
|
-
spinner?.stop();
|
|
5112
|
-
logger?.fail(`${COMMAND_TITLE$1}: ${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`);
|
|
5113
|
-
logger?.error(e);
|
|
5114
|
-
}
|
|
5115
|
-
}
|
|
5277
|
+
const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$2, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
|
|
5116
5278
|
|
|
5117
5279
|
const {
|
|
5118
5280
|
NPM: NPM$1,
|
|
5119
5281
|
PNPM,
|
|
5120
5282
|
YARN_CLASSIC
|
|
5121
5283
|
} = constants;
|
|
5122
|
-
const
|
|
5284
|
+
const CMD_NAME = 'socket optimize';
|
|
5123
5285
|
const manifestNpmOverrides = registry.getManifestData(NPM$1);
|
|
5124
|
-
async function applyOptimization(cwd, pin, prod) {
|
|
5125
|
-
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
5126
|
-
logger: logger.logger,
|
|
5127
|
-
prod
|
|
5128
|
-
});
|
|
5129
|
-
if (!pkgEnvDetails) {
|
|
5130
|
-
return;
|
|
5131
|
-
}
|
|
5132
|
-
// Lazily access constants.spinner.
|
|
5133
|
-
const {
|
|
5134
|
-
spinner
|
|
5135
|
-
} = constants;
|
|
5136
|
-
spinner.start('Socket optimizing...');
|
|
5137
|
-
const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
|
|
5138
|
-
logger: logger.logger,
|
|
5139
|
-
pin,
|
|
5140
|
-
prod,
|
|
5141
|
-
spinner
|
|
5142
|
-
});
|
|
5143
|
-
spinner.stop();
|
|
5144
|
-
const addedCount = state.added.size;
|
|
5145
|
-
const updatedCount = state.updated.size;
|
|
5146
|
-
const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
|
|
5147
|
-
if (pkgJsonChanged) {
|
|
5148
|
-
if (updatedCount > 0) {
|
|
5149
|
-
logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
|
|
5150
|
-
}
|
|
5151
|
-
if (addedCount > 0) {
|
|
5152
|
-
logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
|
|
5153
|
-
}
|
|
5154
|
-
} else {
|
|
5155
|
-
logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
|
|
5156
|
-
}
|
|
5157
|
-
if (pkgEnvDetails.agent === NPM$1 || pkgJsonChanged) {
|
|
5158
|
-
// Always update package-lock.json until the npm overrides PR lands:
|
|
5159
|
-
// https://github.com/npm/cli/pull/8089
|
|
5160
|
-
await updatePackageLockJson(pkgEnvDetails, {
|
|
5161
|
-
logger: logger.logger,
|
|
5162
|
-
spinner
|
|
5163
|
-
});
|
|
5164
|
-
}
|
|
5165
|
-
}
|
|
5166
|
-
function createActionMessage(verb, overrideCount, workspaceCount) {
|
|
5167
|
-
return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
|
|
5168
|
-
}
|
|
5169
5286
|
async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
5170
5287
|
const {
|
|
5171
5288
|
agent,
|
|
@@ -5209,16 +5326,16 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
|
5209
5326
|
const isWorkspace = !!workspaceGlobs;
|
|
5210
5327
|
if (isWorkspace && agent === PNPM && npmExecPath === NPM$1 && !state.warnedPnpmWorkspaceRequiresNpm) {
|
|
5211
5328
|
state.warnedPnpmWorkspaceRequiresNpm = true;
|
|
5212
|
-
logger?.warn(
|
|
5329
|
+
logger?.warn(cmdPrefixMessage(CMD_NAME, 'pnpm workspace support requires `npm ls`, falling back to `pnpm list`'));
|
|
5213
5330
|
}
|
|
5214
|
-
const thingToScan = isLockScanned ? lockSrc : await lsByAgent
|
|
5331
|
+
const thingToScan = isLockScanned ? lockSrc : await lsByAgent.get(agent)(agentExecPath, pkgPath, {
|
|
5215
5332
|
npmExecPath
|
|
5216
5333
|
});
|
|
5217
5334
|
// The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their
|
|
5218
5335
|
// first two parameters. AgentLockIncludesFn accepts an optional third
|
|
5219
5336
|
// parameter which AgentDepsIncludesFn will ignore so we cast thingScanner
|
|
5220
5337
|
// as an AgentLockIncludesFn type.
|
|
5221
|
-
const thingScanner = isLockScanned ?
|
|
5338
|
+
const thingScanner = isLockScanned ? lockfileIncludesByAgent.get(agent) : depsIncludesByAgent.get(agent);
|
|
5222
5339
|
const depEntries = getDependencyEntries(pkgJson);
|
|
5223
5340
|
const overridesDataObjects = [];
|
|
5224
5341
|
if (pkgJson['private'] || isWorkspace) {
|
|
@@ -5344,6 +5461,51 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
|
5344
5461
|
}
|
|
5345
5462
|
return state;
|
|
5346
5463
|
}
|
|
5464
|
+
function createActionMessage(verb, overrideCount, workspaceCount) {
|
|
5465
|
+
return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
|
|
5466
|
+
}
|
|
5467
|
+
async function applyOptimization(cwd, pin, prod) {
|
|
5468
|
+
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
5469
|
+
cmdName: CMD_NAME,
|
|
5470
|
+
logger: logger.logger,
|
|
5471
|
+
prod
|
|
5472
|
+
});
|
|
5473
|
+
if (!pkgEnvDetails) {
|
|
5474
|
+
return;
|
|
5475
|
+
}
|
|
5476
|
+
// Lazily access constants.spinner.
|
|
5477
|
+
const {
|
|
5478
|
+
spinner
|
|
5479
|
+
} = constants;
|
|
5480
|
+
spinner.start('Socket optimizing...');
|
|
5481
|
+
const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
|
|
5482
|
+
logger: logger.logger,
|
|
5483
|
+
pin,
|
|
5484
|
+
prod,
|
|
5485
|
+
spinner
|
|
5486
|
+
});
|
|
5487
|
+
spinner.stop();
|
|
5488
|
+
const addedCount = state.added.size;
|
|
5489
|
+
const updatedCount = state.updated.size;
|
|
5490
|
+
const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
|
|
5491
|
+
if (pkgJsonChanged) {
|
|
5492
|
+
if (updatedCount > 0) {
|
|
5493
|
+
logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
|
|
5494
|
+
}
|
|
5495
|
+
if (addedCount > 0) {
|
|
5496
|
+
logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
|
|
5497
|
+
}
|
|
5498
|
+
} else {
|
|
5499
|
+
logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
|
|
5500
|
+
}
|
|
5501
|
+
if (pkgJsonChanged || pkgEnvDetails.features.npmBuggyOverrides) {
|
|
5502
|
+
await updateLockfile(pkgEnvDetails, {
|
|
5503
|
+
cmdName: CMD_NAME,
|
|
5504
|
+
logger: logger.logger,
|
|
5505
|
+
spinner
|
|
5506
|
+
});
|
|
5507
|
+
}
|
|
5508
|
+
}
|
|
5347
5509
|
|
|
5348
5510
|
const {
|
|
5349
5511
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$h
|
|
@@ -5724,8 +5886,8 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
|
|
|
5724
5886
|
spinner.error('Report result deemed unhealthy for project');
|
|
5725
5887
|
}
|
|
5726
5888
|
} else if (!result.data.healthy) {
|
|
5727
|
-
const severityCount = getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
|
|
5728
|
-
const issueSummary = formatSeverityCount(severityCount);
|
|
5889
|
+
const severityCount = shadowNpmInject.getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
|
|
5890
|
+
const issueSummary = shadowNpmInject.formatSeverityCount(severityCount);
|
|
5729
5891
|
spinner.success(`Report has these issues: ${issueSummary}`);
|
|
5730
5892
|
} else {
|
|
5731
5893
|
spinner.success('Report has no issues');
|
|
@@ -7026,7 +7188,7 @@ async function run$6(argv, importMeta, {
|
|
|
7026
7188
|
});
|
|
7027
7189
|
const [orgSlug = '', ...targets] = cli.input;
|
|
7028
7190
|
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
7029
|
-
|
|
7191
|
+
const {
|
|
7030
7192
|
branch: branchName,
|
|
7031
7193
|
repo: repoName
|
|
7032
7194
|
} = cli.flags;
|
|
@@ -7621,11 +7783,36 @@ const cmdScan = {
|
|
|
7621
7783
|
}
|
|
7622
7784
|
};
|
|
7623
7785
|
|
|
7786
|
+
// Note: Widgets does not seem to actually work as code :'(
|
|
7787
|
+
|
|
7624
7788
|
async function getThreatFeed({
|
|
7789
|
+
direction,
|
|
7790
|
+
ecosystem,
|
|
7791
|
+
filter,
|
|
7792
|
+
outputKind,
|
|
7793
|
+
page,
|
|
7794
|
+
perPage
|
|
7795
|
+
}) {
|
|
7796
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7797
|
+
if (!apiToken) {
|
|
7798
|
+
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7799
|
+
}
|
|
7800
|
+
await getThreatFeedWithToken({
|
|
7801
|
+
apiToken,
|
|
7802
|
+
direction,
|
|
7803
|
+
ecosystem,
|
|
7804
|
+
filter,
|
|
7805
|
+
outputKind,
|
|
7806
|
+
page,
|
|
7807
|
+
perPage
|
|
7808
|
+
});
|
|
7809
|
+
}
|
|
7810
|
+
async function getThreatFeedWithToken({
|
|
7625
7811
|
apiToken,
|
|
7626
7812
|
direction,
|
|
7813
|
+
ecosystem,
|
|
7627
7814
|
filter,
|
|
7628
|
-
|
|
7815
|
+
outputKind,
|
|
7629
7816
|
page,
|
|
7630
7817
|
perPage
|
|
7631
7818
|
}) {
|
|
@@ -7633,17 +7820,12 @@ async function getThreatFeed({
|
|
|
7633
7820
|
const {
|
|
7634
7821
|
spinner
|
|
7635
7822
|
} = constants;
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
page,
|
|
7640
|
-
direction,
|
|
7641
|
-
filter
|
|
7642
|
-
}).join('&');
|
|
7643
|
-
const response = await queryAPI(`threat-feed?${formattedQueryParams}`, apiToken);
|
|
7823
|
+
const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
|
|
7824
|
+
spinner.start('Fetching Threat Feed data...');
|
|
7825
|
+
const response = await queryAPI(`threat-feed?${queryParams}`, apiToken);
|
|
7644
7826
|
const data = await response.json();
|
|
7645
|
-
spinner.stop();
|
|
7646
|
-
if (
|
|
7827
|
+
spinner.stop('Threat feed data fetched');
|
|
7828
|
+
if (outputKind === 'json') {
|
|
7647
7829
|
logger.logger.log(data);
|
|
7648
7830
|
return;
|
|
7649
7831
|
}
|
|
@@ -7656,47 +7838,98 @@ async function getThreatFeed({
|
|
|
7656
7838
|
interactive: 'true',
|
|
7657
7839
|
label: 'Threat feed',
|
|
7658
7840
|
width: '100%',
|
|
7659
|
-
height: '
|
|
7841
|
+
height: '70%',
|
|
7842
|
+
// Changed from 100% to 70%
|
|
7660
7843
|
border: {
|
|
7661
7844
|
type: 'line',
|
|
7662
7845
|
fg: 'cyan'
|
|
7663
7846
|
},
|
|
7664
|
-
|
|
7665
|
-
//
|
|
7666
|
-
|
|
7847
|
+
columnWidth: [10, 30, 20, 18, 15, 200],
|
|
7848
|
+
// TODO: the truncation doesn't seem to work too well yet but when we add
|
|
7849
|
+
// `pad` alignment fails, when we extend columnSpacing alignment fails
|
|
7850
|
+
columnSpacing: 1,
|
|
7851
|
+
truncate: '_'
|
|
7852
|
+
});
|
|
7853
|
+
|
|
7854
|
+
// Create details box at the bottom
|
|
7855
|
+
const detailsBox = new BoxWidget({
|
|
7856
|
+
bottom: 0,
|
|
7857
|
+
height: '30%',
|
|
7858
|
+
width: '100%',
|
|
7859
|
+
border: {
|
|
7860
|
+
type: 'line',
|
|
7861
|
+
fg: 'cyan'
|
|
7862
|
+
},
|
|
7863
|
+
label: 'Details',
|
|
7864
|
+
content: 'Use arrow keys to navigate. Press Enter to select a threat. Press q to exit.',
|
|
7865
|
+
style: {
|
|
7866
|
+
fg: 'white'
|
|
7867
|
+
}
|
|
7667
7868
|
});
|
|
7668
7869
|
|
|
7669
7870
|
// allow control the table with the keyboard
|
|
7670
7871
|
table.focus();
|
|
7671
7872
|
screen.append(table);
|
|
7873
|
+
screen.append(detailsBox);
|
|
7672
7874
|
const formattedOutput = formatResults(data.results);
|
|
7875
|
+
const descriptions = data.results.map(d => d.description);
|
|
7673
7876
|
table.setData({
|
|
7674
|
-
headers: ['Ecosystem', 'Name', 'Version', 'Threat type', 'Detected at', 'Details'],
|
|
7877
|
+
headers: [' Ecosystem', ' Name', ' Version', ' Threat type', ' Detected at', ' Details'],
|
|
7675
7878
|
data: formattedOutput
|
|
7676
7879
|
});
|
|
7880
|
+
|
|
7881
|
+
// Update details box when selection changes
|
|
7882
|
+
table.rows.on('select item', () => {
|
|
7883
|
+
const selectedIndex = table.rows.selected;
|
|
7884
|
+
if (selectedIndex !== undefined && selectedIndex >= 0) {
|
|
7885
|
+
const selectedRow = formattedOutput[selectedIndex];
|
|
7886
|
+
if (selectedRow) {
|
|
7887
|
+
// Note: the spacing works around issues with the table; it refuses to pad!
|
|
7888
|
+
detailsBox.setContent(`Ecosystem: ${selectedRow[0]}\n` + `Name: ${selectedRow[1]}\n` + `Version:${selectedRow[2]}\n` + `Threat type:${selectedRow[3]}\n` + `Detected at:${selectedRow[4]}\n` + `Details: ${selectedRow[5]}\n` + `Description: ${descriptions[selectedIndex]}`);
|
|
7889
|
+
screen.render();
|
|
7890
|
+
}
|
|
7891
|
+
}
|
|
7892
|
+
});
|
|
7677
7893
|
screen.render();
|
|
7678
7894
|
screen.key(['escape', 'q', 'C-c'], () => process$1.exit(0));
|
|
7895
|
+
screen.key(['return'], () => {
|
|
7896
|
+
const selectedIndex = table.rows.selected;
|
|
7897
|
+
screen.destroy();
|
|
7898
|
+
const selectedRow = formattedOutput[selectedIndex];
|
|
7899
|
+
console.log(selectedRow);
|
|
7900
|
+
});
|
|
7679
7901
|
}
|
|
7680
7902
|
function formatResults(data) {
|
|
7681
7903
|
return data.map(d => {
|
|
7682
7904
|
const ecosystem = d.purl.split('pkg:')[1].split('/')[0];
|
|
7683
7905
|
const name = d.purl.split('/')[1].split('@')[0];
|
|
7684
7906
|
const version = d.purl.split('@')[1];
|
|
7685
|
-
const
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
return [ecosystem, decodeURIComponent(name), version, d.threatType, hourDiff, d.locationHtmlUrl];
|
|
7907
|
+
const timeDiff = msAtHome(d.createdAt);
|
|
7908
|
+
|
|
7909
|
+
// Note: the spacing works around issues with the table; it refuses to pad!
|
|
7910
|
+
return [ecosystem, decodeURIComponent(name), ` ${version}`, ` ${d.threatType}`, ` ${timeDiff}`, d.locationHtmlUrl];
|
|
7690
7911
|
});
|
|
7691
7912
|
}
|
|
7692
|
-
function
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7913
|
+
function msAtHome(isoTimeStamp) {
|
|
7914
|
+
const timeStart = Date.parse(isoTimeStamp);
|
|
7915
|
+
const timeEnd = Date.now();
|
|
7916
|
+
const rtf = new Intl.RelativeTimeFormat('en', {
|
|
7917
|
+
numeric: 'always',
|
|
7918
|
+
style: 'short'
|
|
7919
|
+
});
|
|
7920
|
+
const delta = timeEnd - timeStart;
|
|
7921
|
+
if (delta < 60 * 60 * 1000) {
|
|
7922
|
+
return rtf.format(-Math.round(delta / (60 * 1000)), 'minute');
|
|
7923
|
+
// return Math.round(delta / (60 * 1000)) + ' min ago'
|
|
7924
|
+
} else if (delta < 24 * 60 * 60 * 1000) {
|
|
7925
|
+
return rtf.format(-(delta / (60 * 60 * 1000)).toFixed(1), 'hour');
|
|
7926
|
+
// return (delta / (60 * 60 * 1000)).toFixed(1) + ' hr ago'
|
|
7927
|
+
} else if (delta < 7 * 24 * 60 * 60 * 1000) {
|
|
7928
|
+
return rtf.format(-(delta / (24 * 60 * 60 * 1000)).toFixed(1), 'day');
|
|
7929
|
+
// return (delta / (24 * 60 * 60 * 1000)).toFixed(1) + ' day ago'
|
|
7930
|
+
} else {
|
|
7931
|
+
return isoTimeStamp.slice(0, 10);
|
|
7932
|
+
}
|
|
7700
7933
|
}
|
|
7701
7934
|
|
|
7702
7935
|
const {
|
|
@@ -7704,7 +7937,7 @@ const {
|
|
|
7704
7937
|
} = constants;
|
|
7705
7938
|
const config$1 = {
|
|
7706
7939
|
commandName: 'threat-feed',
|
|
7707
|
-
description: '
|
|
7940
|
+
description: '[beta] View the threat feed',
|
|
7708
7941
|
hidden: false,
|
|
7709
7942
|
flags: {
|
|
7710
7943
|
...commonFlags,
|
|
@@ -7727,6 +7960,12 @@ const config$1 = {
|
|
|
7727
7960
|
default: 'desc',
|
|
7728
7961
|
description: 'Order asc or desc by the createdAt attribute.'
|
|
7729
7962
|
},
|
|
7963
|
+
eco: {
|
|
7964
|
+
type: 'string',
|
|
7965
|
+
shortFlag: 'e',
|
|
7966
|
+
default: '',
|
|
7967
|
+
description: 'Only show threats for a particular ecosystem'
|
|
7968
|
+
},
|
|
7730
7969
|
filter: {
|
|
7731
7970
|
type: 'string',
|
|
7732
7971
|
shortFlag: 'f',
|
|
@@ -7738,9 +7977,35 @@ const config$1 = {
|
|
|
7738
7977
|
Usage
|
|
7739
7978
|
$ ${command}
|
|
7740
7979
|
|
|
7980
|
+
This feature requires a Threat Feed license. Please contact
|
|
7981
|
+
sales@socket.dev if you are interested in purchasing this access.
|
|
7982
|
+
|
|
7741
7983
|
Options
|
|
7742
7984
|
${getFlagListOutput(config.flags, 6)}
|
|
7743
7985
|
|
|
7986
|
+
Valid filters:
|
|
7987
|
+
|
|
7988
|
+
- anom Anomaly
|
|
7989
|
+
- c Do not filter
|
|
7990
|
+
- fp False Positives
|
|
7991
|
+
- joke Joke / Fake
|
|
7992
|
+
- mal Malware and Possible Malware [default]
|
|
7993
|
+
- secret Secrets
|
|
7994
|
+
- spy Telemetry
|
|
7995
|
+
- tp False Positives and Unreviewed
|
|
7996
|
+
- typo Typo-squat
|
|
7997
|
+
- u Unreviewed
|
|
7998
|
+
- vuln Vulnerability
|
|
7999
|
+
|
|
8000
|
+
Valid ecosystems:
|
|
8001
|
+
|
|
8002
|
+
- gem
|
|
8003
|
+
- golang
|
|
8004
|
+
- maven
|
|
8005
|
+
- npm
|
|
8006
|
+
- nuget
|
|
8007
|
+
- pypi
|
|
8008
|
+
|
|
7744
8009
|
Examples
|
|
7745
8010
|
$ ${command}
|
|
7746
8011
|
$ ${command} --perPage=5 --page=2 --direction=asc --filter=joke
|
|
@@ -7764,17 +8029,13 @@ async function run$1(argv, importMeta, {
|
|
|
7764
8029
|
logger.logger.log(DRY_RUN_BAIL_TEXT$1);
|
|
7765
8030
|
return;
|
|
7766
8031
|
}
|
|
7767
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7768
|
-
if (!apiToken) {
|
|
7769
|
-
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7770
|
-
}
|
|
7771
8032
|
await getThreatFeed({
|
|
7772
|
-
apiToken,
|
|
7773
8033
|
direction: String(cli.flags['direction'] || 'desc'),
|
|
8034
|
+
ecosystem: String(cli.flags['eco'] || ''),
|
|
7774
8035
|
filter: String(cli.flags['filter'] || 'mal'),
|
|
7775
|
-
|
|
7776
|
-
page: String(cli.flags['
|
|
7777
|
-
perPage: Number(cli.flags['
|
|
8036
|
+
outputKind: cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print',
|
|
8037
|
+
page: String(cli.flags['page'] || '1'),
|
|
8038
|
+
perPage: Number(cli.flags['perPage']) || 30
|
|
7778
8039
|
});
|
|
7779
8040
|
}
|
|
7780
8041
|
|
|
@@ -7976,14 +8237,14 @@ async function run(argv, importMeta, {
|
|
|
7976
8237
|
}
|
|
7977
8238
|
|
|
7978
8239
|
const {
|
|
7979
|
-
|
|
8240
|
+
SOCKET_CLI_BIN_NAME,
|
|
7980
8241
|
rootPkgJsonPath
|
|
7981
8242
|
} = constants;
|
|
7982
8243
|
|
|
7983
8244
|
// TODO: Add autocompletion using https://socket.dev/npm/package/omelette
|
|
7984
8245
|
void (async () => {
|
|
7985
8246
|
await vendor.updater({
|
|
7986
|
-
name:
|
|
8247
|
+
name: SOCKET_CLI_BIN_NAME,
|
|
7987
8248
|
version: require(rootPkgJsonPath).version,
|
|
7988
8249
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
7989
8250
|
});
|
|
@@ -8020,7 +8281,7 @@ void (async () => {
|
|
|
8020
8281
|
}
|
|
8021
8282
|
},
|
|
8022
8283
|
argv: process$1.argv.slice(2),
|
|
8023
|
-
name:
|
|
8284
|
+
name: SOCKET_CLI_BIN_NAME,
|
|
8024
8285
|
importMeta: {
|
|
8025
8286
|
url: `${require$$0.pathToFileURL(__filename)}`
|
|
8026
8287
|
}
|
|
@@ -8044,12 +8305,12 @@ void (async () => {
|
|
|
8044
8305
|
} else {
|
|
8045
8306
|
errorTitle = 'Unexpected error with no details';
|
|
8046
8307
|
}
|
|
8047
|
-
logger.logger.fail(`${colors.bgRed(colors.white(errorTitle
|
|
8308
|
+
logger.logger.fail(`${colors.bgRed(colors.white(`${errorTitle}:`))} ${errorMessage}`);
|
|
8048
8309
|
if (errorBody) {
|
|
8049
8310
|
logger.logger.error(`\n${errorBody}`);
|
|
8050
8311
|
}
|
|
8051
8312
|
await shadowNpmInject.captureException(e);
|
|
8052
8313
|
}
|
|
8053
8314
|
})();
|
|
8054
|
-
//# debugId=
|
|
8315
|
+
//# debugId=2e8d9d04-20b0-4f47-8b02-b404f72bd2d
|
|
8055
8316
|
//# sourceMappingURL=cli.js.map
|