@socketsecurity/cli-with-sentry 0.14.66 → 0.14.68
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/dist/blessed/lib/alias.js +521 -0
- package/dist/blessed/lib/blessed.js +34 -0
- package/dist/blessed/lib/colors.js +492 -0
- package/dist/blessed/lib/events.js +197 -0
- package/dist/blessed/lib/gpmclient.js +247 -0
- package/dist/blessed/lib/helpers.js +172 -0
- package/dist/blessed/lib/keys.js +514 -0
- package/dist/blessed/lib/program.js +4532 -0
- package/dist/blessed/lib/tput.js +3113 -0
- package/dist/blessed/lib/unicode.js +914 -0
- package/dist/blessed/lib/widget.js +62 -0
- package/dist/blessed/lib/widgets/ansiimage.js +175 -0
- package/dist/blessed/lib/widgets/bigtext.js +172 -0
- package/dist/blessed/lib/widgets/box.js +36 -0
- package/dist/blessed/lib/widgets/button.js +64 -0
- package/dist/blessed/lib/widgets/checkbox.js +97 -0
- package/dist/blessed/lib/widgets/element.js +2873 -0
- package/dist/blessed/lib/widgets/filemanager.js +225 -0
- package/dist/blessed/lib/widgets/form.js +303 -0
- package/dist/blessed/lib/widgets/image.js +73 -0
- package/dist/blessed/lib/widgets/input.js +36 -0
- package/dist/blessed/lib/widgets/layout.js +251 -0
- package/dist/blessed/lib/widgets/line.js +61 -0
- package/dist/blessed/lib/widgets/list.js +654 -0
- package/dist/blessed/lib/widgets/listbar.js +454 -0
- package/dist/blessed/lib/widgets/listtable.js +267 -0
- package/dist/blessed/lib/widgets/loading.js +90 -0
- package/dist/blessed/lib/widgets/log.js +84 -0
- package/dist/blessed/lib/widgets/message.js +147 -0
- package/dist/blessed/lib/widgets/node.js +316 -0
- package/dist/blessed/lib/widgets/overlayimage.js +796 -0
- package/dist/blessed/lib/widgets/progressbar.js +168 -0
- package/dist/blessed/lib/widgets/prompt.js +129 -0
- package/dist/blessed/lib/widgets/question.js +131 -0
- package/dist/blessed/lib/widgets/radiobutton.js +64 -0
- package/dist/blessed/lib/widgets/radioset.js +38 -0
- package/dist/blessed/lib/widgets/screen.js +2489 -0
- package/dist/blessed/lib/widgets/scrollablebox.js +417 -0
- package/dist/blessed/lib/widgets/scrollabletext.js +37 -0
- package/dist/blessed/lib/widgets/table.js +385 -0
- package/dist/blessed/lib/widgets/terminal.js +454 -0
- package/dist/blessed/lib/widgets/text.js +37 -0
- package/dist/blessed/lib/widgets/textarea.js +378 -0
- package/dist/blessed/lib/widgets/textbox.js +81 -0
- package/dist/blessed/lib/widgets/video.js +132 -0
- package/dist/blessed/usr/fonts/AUTHORS +1 -0
- package/dist/blessed/usr/fonts/LICENSE +94 -0
- package/dist/blessed/usr/fonts/README +340 -0
- package/dist/blessed/usr/fonts/ter-u14b.json +17826 -0
- package/dist/blessed/usr/fonts/ter-u14n.json +17826 -0
- package/dist/blessed/usr/linux +0 -0
- package/dist/blessed/usr/windows-ansi +0 -0
- package/dist/blessed/usr/xterm +0 -0
- package/dist/blessed/usr/xterm-256color +0 -0
- package/dist/blessed/usr/xterm.termcap +243 -0
- package/dist/blessed/usr/xterm.terminfo +1977 -0
- package/dist/blessed/vendor/tng.js +1878 -0
- package/dist/constants.d.ts +271 -205
- package/dist/constants.js +273 -221
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.d.ts +1 -1
- package/dist/instrument-with-sentry.js +27 -24
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/module-sync/artifact.d.ts +60 -26
- package/dist/module-sync/cli.d.ts +1 -1
- package/dist/module-sync/cli.js +6991 -4413
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/cmd.d.ts +4 -4
- package/dist/module-sync/config.d.ts +32 -0
- package/dist/module-sync/edge.d.ts +73 -60
- package/dist/module-sync/errors.d.ts +26 -11
- package/dist/module-sync/fs.d.ts +61 -0
- package/dist/module-sync/index.d.ts +31 -20
- package/dist/module-sync/node.d.ts +118 -83
- package/dist/module-sync/override-set.d.ts +39 -33
- package/dist/module-sync/package-environment.d.ts +83 -52
- package/dist/module-sync/path-resolve.d.ts +14 -9
- package/dist/module-sync/sdk.d.ts +9 -5
- package/dist/module-sync/shadow-bin.d.ts +5 -2
- package/dist/module-sync/shadow-bin.js +82 -66
- package/dist/module-sync/shadow-bin.js.map +1 -1
- package/dist/module-sync/shadow-npm-inject.d.ts +1 -1
- package/dist/module-sync/shadow-npm-inject.js +1209 -1006
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.d.ts +28 -14
- package/dist/module-sync/shadow-npm-paths.js +286 -209
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/module-sync/socket-package-alert.d.ts +95 -39
- package/dist/module-sync/types.d.ts +75 -47
- package/dist/module-sync/vendor.js +11181 -0
- package/dist/{require → module-sync}/vendor.js.map +1 -1
- package/dist/require/cli.d.ts +1 -1
- package/dist/require/cli.js +6991 -4411
- package/dist/require/cli.js.map +1 -1
- package/dist/require/vendor.js +2 -9145
- package/package.json +49 -41
- package/dist/module-sync/settings.d.ts +0 -15
|
@@ -1,176 +1,174 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
function _socketInterop(e) {
|
|
4
4
|
let c = 0
|
|
5
5
|
for (const k in e ?? {}) {
|
|
6
6
|
c = c === 0 && k === 'default' ? 1 : 0
|
|
7
|
-
if (!c && k !== '__esModule')
|
|
7
|
+
if (!c && k !== '__esModule') {
|
|
8
|
+
break
|
|
9
|
+
}
|
|
8
10
|
}
|
|
9
11
|
return c ? e.default : e
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const {
|
|
41
|
-
kInternalsSymbol: kInternalsSymbol$1,
|
|
42
|
-
[kInternalsSymbol$1]: {
|
|
43
|
-
getSentry
|
|
44
|
-
}
|
|
45
|
-
} = constants;
|
|
46
|
-
class AuthError extends Error {}
|
|
47
|
-
class InputError extends Error {
|
|
48
|
-
constructor(message, body) {
|
|
49
|
-
super(message);
|
|
50
|
-
this.body = body;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async function captureException(exception, hint) {
|
|
54
|
-
const result = captureExceptionSync(exception, hint);
|
|
55
|
-
// "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
|
|
56
|
-
await promises.setTimeout(1000);
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
function captureExceptionSync(exception, hint) {
|
|
60
|
-
const Sentry = getSentry();
|
|
61
|
-
if (!Sentry) {
|
|
62
|
-
return '';
|
|
63
|
-
}
|
|
64
|
-
debug.debugLog('captureException: Sending exception to Sentry.');
|
|
65
|
-
return Sentry.captureException(exception, hint);
|
|
66
|
-
}
|
|
67
|
-
function isErrnoException(value) {
|
|
68
|
-
if (!(value instanceof Error)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
return value.code !== undefined;
|
|
72
|
-
}
|
|
14
|
+
const shadowNpmPaths = require('./shadow-npm-paths.js')
|
|
15
|
+
const process$1 = require('node:process')
|
|
16
|
+
const commonTags = _socketInterop(require('common-tags'))
|
|
17
|
+
const logger = require('@socketsecurity/registry/lib/logger')
|
|
18
|
+
const constants = require('./constants.js')
|
|
19
|
+
const semver = _socketInterop(require('semver'))
|
|
20
|
+
const packageurlJs = require('@socketregistry/packageurl-js')
|
|
21
|
+
const registry = require('@socketsecurity/registry')
|
|
22
|
+
const arrays = require('@socketsecurity/registry/lib/arrays')
|
|
23
|
+
const debug = require('@socketsecurity/registry/lib/debug')
|
|
24
|
+
const objects = require('@socketsecurity/registry/lib/objects')
|
|
25
|
+
const npa = _socketInterop(require('npm-package-arg'))
|
|
26
|
+
const hpagent = _socketInterop(require('hpagent'))
|
|
27
|
+
const isInteractive = require('@socketregistry/is-interactive/index.cjs')
|
|
28
|
+
const registryConstants = require('@socketsecurity/registry/lib/constants')
|
|
29
|
+
const prompts = require('@socketsecurity/registry/lib/prompts')
|
|
30
|
+
const strings = require('@socketsecurity/registry/lib/strings')
|
|
31
|
+
const sdk = require('@socketsecurity/sdk')
|
|
32
|
+
const fs = require('node:fs')
|
|
33
|
+
const os = require('node:os')
|
|
34
|
+
const path = require('node:path')
|
|
35
|
+
const config = require('@socketsecurity/config')
|
|
36
|
+
const promises = require('node:timers/promises')
|
|
37
|
+
const colors = _socketInterop(require('yoctocolors-cjs'))
|
|
38
|
+
const packages = require('@socketsecurity/registry/lib/packages')
|
|
39
|
+
const sorts = require('@socketsecurity/registry/lib/sorts')
|
|
40
|
+
const terminalLink = _socketInterop(require('terminal-link'))
|
|
41
|
+
const indentString = require('@socketregistry/indent-string/index.cjs')
|
|
73
42
|
|
|
74
|
-
const {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
signal = abortSignal
|
|
80
|
-
}) {
|
|
81
|
-
let dir = path.resolve(cwd);
|
|
82
|
-
const {
|
|
83
|
-
root
|
|
84
|
-
} = path.parse(dir);
|
|
85
|
-
const names = [name].flat();
|
|
43
|
+
const { abortSignal } = constants
|
|
44
|
+
async function findUp(name, { cwd = process$1.cwd(), signal = abortSignal }) {
|
|
45
|
+
let dir = path.resolve(cwd)
|
|
46
|
+
const { root } = path.parse(dir)
|
|
47
|
+
const names = [name].flat()
|
|
86
48
|
while (dir && dir !== root) {
|
|
87
49
|
for (const name of names) {
|
|
88
50
|
if (signal?.aborted) {
|
|
89
|
-
return undefined
|
|
51
|
+
return undefined
|
|
90
52
|
}
|
|
91
|
-
const filePath = path.join(dir, name)
|
|
53
|
+
const filePath = path.join(dir, name)
|
|
92
54
|
try {
|
|
93
55
|
// eslint-disable-next-line no-await-in-loop
|
|
94
|
-
const stats = await fs.promises.stat(filePath)
|
|
56
|
+
const stats = await fs.promises.stat(filePath)
|
|
95
57
|
if (stats.isFile()) {
|
|
96
|
-
return filePath
|
|
58
|
+
return filePath
|
|
97
59
|
}
|
|
98
60
|
} catch {}
|
|
99
61
|
}
|
|
100
|
-
dir = path.dirname(dir)
|
|
62
|
+
dir = path.dirname(dir)
|
|
101
63
|
}
|
|
102
|
-
return undefined
|
|
64
|
+
return undefined
|
|
103
65
|
}
|
|
104
66
|
async function readFileBinary(filepath, options) {
|
|
105
67
|
return await fs.promises.readFile(filepath, {
|
|
106
68
|
signal: abortSignal,
|
|
107
69
|
...options,
|
|
108
70
|
encoding: 'binary'
|
|
109
|
-
})
|
|
71
|
+
})
|
|
110
72
|
}
|
|
111
73
|
async function readFileUtf8(filepath, options) {
|
|
112
74
|
return await fs.promises.readFile(filepath, {
|
|
113
75
|
signal: abortSignal,
|
|
114
76
|
...options,
|
|
115
77
|
encoding: 'utf8'
|
|
116
|
-
})
|
|
78
|
+
})
|
|
117
79
|
}
|
|
118
80
|
async function safeReadFile(filepath, options) {
|
|
119
81
|
try {
|
|
120
82
|
return await fs.promises.readFile(filepath, {
|
|
121
83
|
encoding: 'utf8',
|
|
122
84
|
signal: abortSignal,
|
|
123
|
-
...(typeof options === 'string'
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
85
|
+
...(typeof options === 'string'
|
|
86
|
+
? {
|
|
87
|
+
encoding: options
|
|
88
|
+
}
|
|
89
|
+
: options)
|
|
90
|
+
})
|
|
127
91
|
} catch {}
|
|
128
|
-
return undefined
|
|
92
|
+
return undefined
|
|
129
93
|
}
|
|
130
94
|
function safeReadFileSync(filepath, options) {
|
|
131
95
|
try {
|
|
132
96
|
return fs.readFileSync(filepath, {
|
|
133
97
|
encoding: 'utf8',
|
|
134
|
-
...(typeof options === 'string'
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
98
|
+
...(typeof options === 'string'
|
|
99
|
+
? {
|
|
100
|
+
encoding: options
|
|
101
|
+
}
|
|
102
|
+
: options)
|
|
103
|
+
})
|
|
138
104
|
} catch {}
|
|
139
|
-
return undefined
|
|
105
|
+
return undefined
|
|
140
106
|
}
|
|
141
107
|
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
108
|
+
const { LOCALAPPDATA, SOCKET_APP_DIR, XDG_DATA_HOME } = constants
|
|
109
|
+
const supportedConfigKeys = new Map([
|
|
110
|
+
['apiBaseUrl', 'Base URL of the API endpoint'],
|
|
111
|
+
['apiProxy', 'A proxy through which to access the API'],
|
|
112
|
+
['apiToken', 'The API token required to access most API endpoints'],
|
|
113
|
+
[
|
|
114
|
+
'defaultOrg',
|
|
115
|
+
'The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.'
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
'enforcedOrgs',
|
|
119
|
+
'Orgs in this list have their security policies enforced on this machine'
|
|
120
|
+
]
|
|
121
|
+
])
|
|
122
|
+
const sensitiveConfigKeys = new Set(['apiToken'])
|
|
123
|
+
let _cachedConfig
|
|
124
|
+
// When using --config or SOCKET_CLI_CONFIG_OVERRIDE, do not persist the config.
|
|
125
|
+
let _readOnlyConfig = false
|
|
126
|
+
function overrideCachedConfig(config) {
|
|
127
|
+
_cachedConfig = {
|
|
128
|
+
...config
|
|
129
|
+
}
|
|
130
|
+
_readOnlyConfig = true
|
|
131
|
+
// Normalize apiKey to apiToken.
|
|
132
|
+
if (_cachedConfig['apiKey']) {
|
|
133
|
+
_cachedConfig['apiToken'] = _cachedConfig['apiKey']
|
|
134
|
+
delete _cachedConfig['apiKey']
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function getConfigValues() {
|
|
138
|
+
if (_cachedConfig === undefined) {
|
|
139
|
+
_cachedConfig = {}
|
|
140
|
+
// Order: env var > --config flag > file
|
|
141
|
+
const configPath = getConfigPath()
|
|
142
|
+
if (configPath) {
|
|
143
|
+
const raw = safeReadFileSync(configPath)
|
|
158
144
|
if (raw) {
|
|
159
145
|
try {
|
|
160
|
-
Object.assign(
|
|
146
|
+
Object.assign(
|
|
147
|
+
_cachedConfig,
|
|
148
|
+
JSON.parse(Buffer.from(raw, 'base64').toString())
|
|
149
|
+
)
|
|
161
150
|
} catch {
|
|
162
|
-
logger.logger.warn(`Failed to parse
|
|
151
|
+
logger.logger.warn(`Failed to parse config at ${configPath}`)
|
|
152
|
+
}
|
|
153
|
+
// Normalize apiKey to apiToken and persist it.
|
|
154
|
+
// This is a one time migration per user.
|
|
155
|
+
if (_cachedConfig['apiKey']) {
|
|
156
|
+
const token = _cachedConfig['apiKey']
|
|
157
|
+
delete _cachedConfig['apiKey']
|
|
158
|
+
updateConfigValue('apiToken', token)
|
|
163
159
|
}
|
|
164
160
|
} else {
|
|
165
|
-
fs.mkdirSync(path.dirname(
|
|
161
|
+
fs.mkdirSync(path.dirname(configPath), {
|
|
166
162
|
recursive: true
|
|
167
|
-
})
|
|
163
|
+
})
|
|
168
164
|
}
|
|
169
165
|
}
|
|
170
166
|
}
|
|
171
|
-
return
|
|
167
|
+
return _cachedConfig
|
|
172
168
|
}
|
|
173
|
-
|
|
169
|
+
let _configPath
|
|
170
|
+
let _warnedConfigPathWin32Missing = false
|
|
171
|
+
function getConfigPath() {
|
|
174
172
|
// Get the OS app data folder:
|
|
175
173
|
// - Win: %LOCALAPPDATA% or fail?
|
|
176
174
|
// - Mac: %XDG_DATA_HOME% or fallback to "~/Library/Application Support/"
|
|
@@ -183,182 +181,248 @@ function getSettingsPath() {
|
|
|
183
181
|
// - Mac: %XDG_DATA_HOME%/socket/settings or "~/Library/Application Support/socket/settings"
|
|
184
182
|
// - Linux: %XDG_DATA_HOME%/socket/settings or "~/.local/share/socket/settings"
|
|
185
183
|
|
|
186
|
-
if (
|
|
184
|
+
if (_configPath === undefined) {
|
|
187
185
|
// Lazily access constants.WIN32.
|
|
188
|
-
const {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
186
|
+
const { WIN32 } = constants
|
|
187
|
+
let dataHome = WIN32
|
|
188
|
+
? // Lazily access constants.ENV[LOCALAPPDATA]
|
|
189
|
+
constants.ENV[LOCALAPPDATA]
|
|
190
|
+
: // Lazily access constants.ENV[XDG_DATA_HOME]
|
|
191
|
+
constants.ENV[XDG_DATA_HOME]
|
|
192
192
|
if (!dataHome) {
|
|
193
193
|
if (WIN32) {
|
|
194
|
-
if (!
|
|
195
|
-
|
|
196
|
-
logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
|
|
194
|
+
if (!_warnedConfigPathWin32Missing) {
|
|
195
|
+
_warnedConfigPathWin32Missing = true
|
|
196
|
+
logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
|
|
197
197
|
}
|
|
198
198
|
} else {
|
|
199
|
-
dataHome = path.join(
|
|
199
|
+
dataHome = path.join(
|
|
200
|
+
os.homedir(),
|
|
201
|
+
...(process$1.platform === 'darwin'
|
|
202
|
+
? ['Library', 'Application Support']
|
|
203
|
+
: ['.local', 'share'])
|
|
204
|
+
)
|
|
200
205
|
}
|
|
201
206
|
}
|
|
202
|
-
|
|
207
|
+
_configPath = dataHome ? path.join(dataHome, SOCKET_APP_DIR) : undefined
|
|
203
208
|
}
|
|
204
|
-
return
|
|
209
|
+
return _configPath
|
|
205
210
|
}
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
211
|
+
function normalizeConfigKey(key) {
|
|
212
|
+
// Note: apiKey was the old name of the token. When we load a config with
|
|
213
|
+
// property apiKey, we'll copy that to apiToken and delete the old property.
|
|
214
|
+
const normalizedKey = key === 'apiKey' ? 'apiToken' : key
|
|
215
|
+
if (!supportedConfigKeys.has(normalizedKey)) {
|
|
216
|
+
throw new Error(`Invalid config key: ${normalizedKey}`)
|
|
217
|
+
}
|
|
218
|
+
return normalizedKey
|
|
212
219
|
}
|
|
213
|
-
function findSocketYmlSync() {
|
|
214
|
-
let prevDir = null
|
|
215
|
-
let dir = process$1.cwd();
|
|
220
|
+
function findSocketYmlSync(dir = process$1.cwd()) {
|
|
221
|
+
let prevDir = null
|
|
216
222
|
while (dir !== prevDir) {
|
|
217
|
-
let ymlPath = path.join(dir, 'socket.yml')
|
|
218
|
-
let yml = safeReadFileSync(ymlPath)
|
|
223
|
+
let ymlPath = path.join(dir, 'socket.yml')
|
|
224
|
+
let yml = safeReadFileSync(ymlPath)
|
|
219
225
|
if (yml === undefined) {
|
|
220
|
-
ymlPath = path.join(dir, 'socket.yaml')
|
|
221
|
-
yml = safeReadFileSync(ymlPath)
|
|
226
|
+
ymlPath = path.join(dir, 'socket.yaml')
|
|
227
|
+
yml = safeReadFileSync(ymlPath)
|
|
222
228
|
}
|
|
223
229
|
if (typeof yml === 'string') {
|
|
224
230
|
try {
|
|
225
231
|
return {
|
|
226
232
|
path: ymlPath,
|
|
227
233
|
parsed: config.parseSocketConfig(yml)
|
|
228
|
-
}
|
|
234
|
+
}
|
|
229
235
|
} catch {
|
|
230
|
-
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
236
|
+
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
231
237
|
}
|
|
232
238
|
}
|
|
233
|
-
prevDir = dir
|
|
234
|
-
dir = path.join(dir, '..')
|
|
239
|
+
prevDir = dir
|
|
240
|
+
dir = path.join(dir, '..')
|
|
235
241
|
}
|
|
236
|
-
return null
|
|
242
|
+
return null
|
|
237
243
|
}
|
|
238
|
-
function
|
|
239
|
-
|
|
244
|
+
function getConfigValue(key) {
|
|
245
|
+
const localConfig = getConfigValues()
|
|
246
|
+
return localConfig[normalizeConfigKey(key)]
|
|
240
247
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
248
|
+
let _pendingSave = false
|
|
249
|
+
function updateConfigValue(key, value) {
|
|
250
|
+
const localConfig = getConfigValues()
|
|
251
|
+
localConfig[normalizeConfigKey(key)] = value
|
|
252
|
+
if (_readOnlyConfig) {
|
|
253
|
+
logger.logger.warn(
|
|
254
|
+
'Not persisting config change; current config overridden through env var or flag'
|
|
255
|
+
)
|
|
256
|
+
} else if (!_pendingSave) {
|
|
257
|
+
_pendingSave = true
|
|
246
258
|
process$1.nextTick(() => {
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
fs.writeFileSync(
|
|
259
|
+
_pendingSave = false
|
|
260
|
+
const configPath = getConfigPath()
|
|
261
|
+
if (configPath) {
|
|
262
|
+
fs.writeFileSync(
|
|
263
|
+
configPath,
|
|
264
|
+
Buffer.from(JSON.stringify(localConfig)).toString('base64')
|
|
265
|
+
)
|
|
251
266
|
}
|
|
252
|
-
})
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const {
|
|
272
|
+
kInternalsSymbol: kInternalsSymbol$1,
|
|
273
|
+
[kInternalsSymbol$1]: { getSentry }
|
|
274
|
+
} = constants
|
|
275
|
+
class AuthError extends Error {}
|
|
276
|
+
class InputError extends Error {
|
|
277
|
+
constructor(message, body) {
|
|
278
|
+
super(message)
|
|
279
|
+
this.body = body
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async function captureException(exception, hint) {
|
|
283
|
+
const result = captureExceptionSync(exception, hint)
|
|
284
|
+
// "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
|
|
285
|
+
await promises.setTimeout(1000)
|
|
286
|
+
return result
|
|
287
|
+
}
|
|
288
|
+
function captureExceptionSync(exception, hint) {
|
|
289
|
+
const Sentry = getSentry()
|
|
290
|
+
if (!Sentry) {
|
|
291
|
+
return ''
|
|
253
292
|
}
|
|
293
|
+
debug.debugLog('captureException: Sending exception to Sentry.')
|
|
294
|
+
return Sentry.captureException(exception, hint)
|
|
254
295
|
}
|
|
255
296
|
|
|
256
297
|
const {
|
|
257
|
-
SOCKET_CLI_NO_API_TOKEN
|
|
258
|
-
|
|
298
|
+
SOCKET_CLI_NO_API_TOKEN,
|
|
299
|
+
SOCKET_SECURITY_API_BASE_URL,
|
|
300
|
+
SOCKET_SECURITY_API_PROXY,
|
|
301
|
+
SOCKET_SECURITY_API_TOKEN
|
|
302
|
+
} = constants
|
|
259
303
|
|
|
260
304
|
// The API server that should be used for operations.
|
|
261
305
|
function getDefaultApiBaseUrl() {
|
|
262
|
-
const baseUrl =
|
|
263
|
-
|
|
306
|
+
const baseUrl =
|
|
307
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_BASE_URL].
|
|
308
|
+
constants.ENV[SOCKET_SECURITY_API_BASE_URL] || getConfigValue('apiBaseUrl')
|
|
309
|
+
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined
|
|
264
310
|
}
|
|
265
311
|
|
|
266
312
|
// The API server that should be used for operations.
|
|
267
313
|
function getDefaultHttpProxy() {
|
|
268
|
-
const apiProxy =
|
|
269
|
-
|
|
314
|
+
const apiProxy =
|
|
315
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_PROXY].
|
|
316
|
+
constants.ENV[SOCKET_SECURITY_API_PROXY] || getConfigValue('apiProxy')
|
|
317
|
+
return strings.isNonEmptyString(apiProxy) ? apiProxy : undefined
|
|
270
318
|
}
|
|
271
319
|
|
|
272
320
|
// This API key should be stored globally for the duration of the CLI execution.
|
|
273
|
-
let _defaultToken
|
|
321
|
+
let _defaultToken
|
|
274
322
|
function getDefaultToken() {
|
|
275
323
|
// Lazily access constants.ENV[SOCKET_CLI_NO_API_TOKEN].
|
|
276
324
|
if (constants.ENV[SOCKET_CLI_NO_API_TOKEN]) {
|
|
277
|
-
_defaultToken = undefined
|
|
325
|
+
_defaultToken = undefined
|
|
278
326
|
} else {
|
|
279
|
-
const key =
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
327
|
+
const key =
|
|
328
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
329
|
+
constants.ENV[SOCKET_SECURITY_API_TOKEN] ||
|
|
330
|
+
getConfigValue('apiToken') ||
|
|
331
|
+
_defaultToken
|
|
332
|
+
_defaultToken = strings.isNonEmptyString(key) ? key : undefined
|
|
333
|
+
}
|
|
334
|
+
return _defaultToken
|
|
286
335
|
}
|
|
287
336
|
function getPublicToken() {
|
|
288
|
-
return (
|
|
337
|
+
return (
|
|
338
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
339
|
+
(constants.ENV[SOCKET_SECURITY_API_TOKEN] || getDefaultToken()) ??
|
|
340
|
+
registryConstants.SOCKET_PUBLIC_API_TOKEN
|
|
341
|
+
)
|
|
289
342
|
}
|
|
290
|
-
async function setupSdk(
|
|
343
|
+
async function setupSdk(
|
|
344
|
+
apiToken = getDefaultToken(),
|
|
345
|
+
apiBaseUrl = getDefaultApiBaseUrl(),
|
|
346
|
+
proxy = getDefaultHttpProxy()
|
|
347
|
+
) {
|
|
291
348
|
if (typeof apiToken !== 'string' && isInteractive()) {
|
|
292
349
|
apiToken = await prompts.password({
|
|
293
|
-
message:
|
|
294
|
-
|
|
295
|
-
|
|
350
|
+
message:
|
|
351
|
+
'Enter your Socket.dev API key (not saved, use socket login to persist)'
|
|
352
|
+
})
|
|
353
|
+
_defaultToken = apiToken
|
|
296
354
|
}
|
|
297
355
|
if (!apiToken) {
|
|
298
|
-
throw new AuthError('You need to provide an API key')
|
|
356
|
+
throw new AuthError('You need to provide an API key')
|
|
299
357
|
}
|
|
300
358
|
return new sdk.SocketSdk(apiToken, {
|
|
301
|
-
agent: proxy
|
|
302
|
-
|
|
303
|
-
|
|
359
|
+
agent: proxy
|
|
360
|
+
? new hpagent.HttpsProxyAgent({
|
|
361
|
+
proxy
|
|
362
|
+
})
|
|
363
|
+
: undefined,
|
|
304
364
|
baseUrl: apiBaseUrl,
|
|
305
365
|
userAgent: sdk.createUserAgentFromPkgJson({
|
|
306
366
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_NAME']".
|
|
307
|
-
name:
|
|
367
|
+
name: '@socketsecurity/cli',
|
|
308
368
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
309
|
-
version:
|
|
369
|
+
version: '0.14.68',
|
|
310
370
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_HOMEPAGE']".
|
|
311
|
-
homepage:
|
|
371
|
+
homepage: 'https://github.com/SocketDev/socket-cli'
|
|
312
372
|
})
|
|
313
|
-
})
|
|
373
|
+
})
|
|
314
374
|
}
|
|
315
375
|
|
|
316
|
-
|
|
317
|
-
DiffAction[
|
|
318
|
-
DiffAction[
|
|
319
|
-
DiffAction[
|
|
320
|
-
return DiffAction
|
|
321
|
-
}({})
|
|
376
|
+
const DiffAction = /*#__PURE__*/ (function (DiffAction) {
|
|
377
|
+
DiffAction['add'] = 'ADD'
|
|
378
|
+
DiffAction['change'] = 'CHANGE'
|
|
379
|
+
DiffAction['remove'] = 'REMOVE'
|
|
380
|
+
return DiffAction
|
|
381
|
+
})({})
|
|
322
382
|
|
|
323
|
-
const depValid = require(shadowNpmPaths.getArboristDepValidPath())
|
|
383
|
+
const depValid = require(shadowNpmPaths.getArboristDepValidPath())
|
|
324
384
|
|
|
325
|
-
const {
|
|
326
|
-
UNDEFINED_TOKEN
|
|
327
|
-
} = constants;
|
|
385
|
+
const { UNDEFINED_TOKEN } = constants
|
|
328
386
|
function tryRequire(req, ...ids) {
|
|
329
387
|
for (const data of ids) {
|
|
330
|
-
let id
|
|
331
|
-
let transformer
|
|
388
|
+
let id
|
|
389
|
+
let transformer
|
|
332
390
|
if (Array.isArray(data)) {
|
|
333
|
-
id = data[0]
|
|
334
|
-
transformer = data[1]
|
|
391
|
+
id = data[0]
|
|
392
|
+
transformer = data[1]
|
|
335
393
|
} else {
|
|
336
|
-
id = data
|
|
337
|
-
transformer = mod => mod
|
|
394
|
+
id = data
|
|
395
|
+
transformer = mod => mod
|
|
338
396
|
}
|
|
339
397
|
try {
|
|
340
398
|
// Check that the transformed value isn't `undefined` because older
|
|
341
399
|
// versions of packages like 'proc-log' may not export a `log` method.
|
|
342
|
-
const exported = transformer(req(id))
|
|
400
|
+
const exported = transformer(req(id))
|
|
343
401
|
if (exported !== undefined) {
|
|
344
|
-
return exported
|
|
402
|
+
return exported
|
|
345
403
|
}
|
|
346
404
|
} catch {}
|
|
347
405
|
}
|
|
348
|
-
return undefined
|
|
406
|
+
return undefined
|
|
349
407
|
}
|
|
350
|
-
let _log = UNDEFINED_TOKEN
|
|
408
|
+
let _log = UNDEFINED_TOKEN
|
|
351
409
|
function getLogger() {
|
|
352
410
|
if (_log === UNDEFINED_TOKEN) {
|
|
353
|
-
_log = tryRequire(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
411
|
+
_log = tryRequire(
|
|
412
|
+
shadowNpmPaths.getNpmRequire(),
|
|
413
|
+
[
|
|
414
|
+
'proc-log/lib/index.js',
|
|
415
|
+
// The proc-log DefinitelyTyped definition is incorrect. The type definition
|
|
416
|
+
// is really that of its export log.
|
|
417
|
+
mod => mod.log
|
|
418
|
+
],
|
|
419
|
+
'npmlog/lib/log.js'
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
return _log
|
|
359
423
|
}
|
|
360
424
|
|
|
361
|
-
const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
|
|
425
|
+
const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
|
|
362
426
|
|
|
363
427
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
364
428
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
|
|
@@ -369,59 +433,64 @@ class SafeOverrideSet extends OverrideSet {
|
|
|
369
433
|
// If override sets contain one another then we can try to use the more
|
|
370
434
|
// specific one. If neither one is more specific, then we consider them to
|
|
371
435
|
// be in conflict.
|
|
372
|
-
return this.findSpecificOverrideSet(first, second) === undefined
|
|
436
|
+
return this.findSpecificOverrideSet(first, second) === undefined
|
|
373
437
|
}
|
|
374
438
|
|
|
375
439
|
// Patch adding findSpecificOverrideSet is based on
|
|
376
440
|
// https://github.com/npm/cli/pull/8089.
|
|
377
441
|
static findSpecificOverrideSet(first, second) {
|
|
378
|
-
for (
|
|
442
|
+
for (
|
|
443
|
+
let overrideSet = second;
|
|
444
|
+
overrideSet;
|
|
445
|
+
overrideSet = overrideSet.parent
|
|
446
|
+
) {
|
|
379
447
|
if (overrideSet.isEqual(first)) {
|
|
380
|
-
return second
|
|
448
|
+
return second
|
|
381
449
|
}
|
|
382
450
|
}
|
|
383
|
-
for (
|
|
451
|
+
for (
|
|
452
|
+
let overrideSet = first;
|
|
453
|
+
overrideSet;
|
|
454
|
+
overrideSet = overrideSet.parent
|
|
455
|
+
) {
|
|
384
456
|
if (overrideSet.isEqual(second)) {
|
|
385
|
-
return first
|
|
457
|
+
return first
|
|
386
458
|
}
|
|
387
459
|
}
|
|
388
460
|
// The override sets are incomparable. Neither one contains the other.
|
|
389
|
-
const log = getLogger()
|
|
390
|
-
log?.silly('Conflicting override sets', first, second)
|
|
391
|
-
return undefined
|
|
461
|
+
const log = getLogger()
|
|
462
|
+
log?.silly('Conflicting override sets', first, second)
|
|
463
|
+
return undefined
|
|
392
464
|
}
|
|
393
465
|
|
|
394
466
|
// Patch adding childrenAreEqual is based on
|
|
395
467
|
// https://github.com/npm/cli/pull/8089.
|
|
396
468
|
childrenAreEqual(otherOverrideSet) {
|
|
397
469
|
if (this.children.size !== otherOverrideSet.children.size) {
|
|
398
|
-
return false
|
|
470
|
+
return false
|
|
399
471
|
}
|
|
400
|
-
for (const {
|
|
401
|
-
|
|
402
|
-
1: childOverrideSet
|
|
403
|
-
} of this.children) {
|
|
404
|
-
const otherChildOverrideSet = otherOverrideSet.children.get(key);
|
|
472
|
+
for (const { 0: key, 1: childOverrideSet } of this.children) {
|
|
473
|
+
const otherChildOverrideSet = otherOverrideSet.children.get(key)
|
|
405
474
|
if (!otherChildOverrideSet) {
|
|
406
|
-
return false
|
|
475
|
+
return false
|
|
407
476
|
}
|
|
408
477
|
if (childOverrideSet.value !== otherChildOverrideSet.value) {
|
|
409
|
-
return false
|
|
478
|
+
return false
|
|
410
479
|
}
|
|
411
480
|
if (!childOverrideSet.childrenAreEqual(otherChildOverrideSet)) {
|
|
412
|
-
return false
|
|
481
|
+
return false
|
|
413
482
|
}
|
|
414
483
|
}
|
|
415
|
-
return true
|
|
484
|
+
return true
|
|
416
485
|
}
|
|
417
486
|
getEdgeRule(edge) {
|
|
418
487
|
for (const rule of this.ruleset.values()) {
|
|
419
488
|
if (rule.name !== edge.name) {
|
|
420
|
-
continue
|
|
489
|
+
continue
|
|
421
490
|
}
|
|
422
491
|
// If keySpec is * we found our override.
|
|
423
492
|
if (rule.keySpec === '*') {
|
|
424
|
-
return rule
|
|
493
|
+
return rule
|
|
425
494
|
}
|
|
426
495
|
// Patch replacing
|
|
427
496
|
// let spec = npa(`${edge.name}@${edge.spec}`)
|
|
@@ -430,53 +499,56 @@ class SafeOverrideSet extends OverrideSet {
|
|
|
430
499
|
// We need to use the rawSpec here, because the spec has the overrides
|
|
431
500
|
// applied to it already. The rawSpec can be undefined, so we need to use
|
|
432
501
|
// the fallback value of spec if it is.
|
|
433
|
-
let spec = npa(`${edge.name}@${edge.rawSpec || edge.spec}`)
|
|
502
|
+
let spec = npa(`${edge.name}@${edge.rawSpec || edge.spec}`)
|
|
434
503
|
if (spec.type === 'alias') {
|
|
435
|
-
spec = spec.subSpec
|
|
504
|
+
spec = spec.subSpec
|
|
436
505
|
}
|
|
437
506
|
if (spec.type === 'git') {
|
|
438
507
|
if (spec.gitRange && semver.intersects(spec.gitRange, rule.keySpec)) {
|
|
439
|
-
return rule
|
|
508
|
+
return rule
|
|
440
509
|
}
|
|
441
|
-
continue
|
|
510
|
+
continue
|
|
442
511
|
}
|
|
443
512
|
if (spec.type === 'range' || spec.type === 'version') {
|
|
444
513
|
if (semver.intersects(spec.fetchSpec, rule.keySpec)) {
|
|
445
|
-
return rule
|
|
514
|
+
return rule
|
|
446
515
|
}
|
|
447
|
-
continue
|
|
516
|
+
continue
|
|
448
517
|
}
|
|
449
518
|
// If we got this far, the spec type is one of tag, directory or file
|
|
450
519
|
// which means we have no real way to make version comparisons, so we
|
|
451
520
|
// just accept the override.
|
|
452
|
-
return rule
|
|
521
|
+
return rule
|
|
453
522
|
}
|
|
454
|
-
return this
|
|
523
|
+
return this
|
|
455
524
|
}
|
|
456
525
|
|
|
457
526
|
// Patch adding isEqual is based on
|
|
458
527
|
// https://github.com/npm/cli/pull/8089.
|
|
459
528
|
isEqual(otherOverrideSet) {
|
|
460
529
|
if (this === otherOverrideSet) {
|
|
461
|
-
return true
|
|
530
|
+
return true
|
|
462
531
|
}
|
|
463
532
|
if (!otherOverrideSet) {
|
|
464
|
-
return false
|
|
533
|
+
return false
|
|
465
534
|
}
|
|
466
|
-
if (
|
|
467
|
-
|
|
535
|
+
if (
|
|
536
|
+
this.key !== otherOverrideSet.key ||
|
|
537
|
+
this.value !== otherOverrideSet.value
|
|
538
|
+
) {
|
|
539
|
+
return false
|
|
468
540
|
}
|
|
469
541
|
if (!this.childrenAreEqual(otherOverrideSet)) {
|
|
470
|
-
return false
|
|
542
|
+
return false
|
|
471
543
|
}
|
|
472
544
|
if (!this.parent) {
|
|
473
|
-
return !otherOverrideSet.parent
|
|
545
|
+
return !otherOverrideSet.parent
|
|
474
546
|
}
|
|
475
|
-
return this.parent.isEqual(otherOverrideSet.parent)
|
|
547
|
+
return this.parent.isEqual(otherOverrideSet.parent)
|
|
476
548
|
}
|
|
477
549
|
}
|
|
478
550
|
|
|
479
|
-
const Node = require(shadowNpmPaths.getArboristNodeClassPath())
|
|
551
|
+
const Node = require(shadowNpmPaths.getArboristNodeClassPath())
|
|
480
552
|
|
|
481
553
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
482
554
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
|
|
@@ -487,28 +559,28 @@ class SafeNode extends Node {
|
|
|
487
559
|
canDedupe(preferDedupe = false) {
|
|
488
560
|
// Not allowed to mess with shrinkwraps or bundles.
|
|
489
561
|
if (this.inDepBundle || this.inShrinkwrap) {
|
|
490
|
-
return false
|
|
562
|
+
return false
|
|
491
563
|
}
|
|
492
564
|
// It's a top level pkg, or a dep of one.
|
|
493
565
|
if (!this.resolveParent?.resolveParent) {
|
|
494
|
-
return false
|
|
566
|
+
return false
|
|
495
567
|
}
|
|
496
568
|
// No one wants it, remove it.
|
|
497
569
|
if (this.edgesIn.size === 0) {
|
|
498
|
-
return true
|
|
570
|
+
return true
|
|
499
571
|
}
|
|
500
|
-
const other = this.resolveParent.resolveParent.resolve(this.name)
|
|
572
|
+
const other = this.resolveParent.resolveParent.resolve(this.name)
|
|
501
573
|
// Nothing else, need this one.
|
|
502
574
|
if (!other) {
|
|
503
|
-
return false
|
|
575
|
+
return false
|
|
504
576
|
}
|
|
505
577
|
// If it's the same thing, then always fine to remove.
|
|
506
578
|
if (other.matches(this)) {
|
|
507
|
-
return true
|
|
579
|
+
return true
|
|
508
580
|
}
|
|
509
581
|
// If the other thing can't replace this, then skip it.
|
|
510
582
|
if (!other.canReplace(this)) {
|
|
511
|
-
return false
|
|
583
|
+
return false
|
|
512
584
|
}
|
|
513
585
|
// Patch replacing
|
|
514
586
|
// if (preferDedupe || semver.gte(other.version, this.version)) {
|
|
@@ -518,14 +590,14 @@ class SafeNode extends Node {
|
|
|
518
590
|
//
|
|
519
591
|
// If we prefer dedupe, or if the version is equal, take the other.
|
|
520
592
|
if (preferDedupe || semver.eq(other.version, this.version)) {
|
|
521
|
-
return true
|
|
593
|
+
return true
|
|
522
594
|
}
|
|
523
595
|
// If our current version isn't the result of an override, then prefer to
|
|
524
596
|
// take the greater version.
|
|
525
597
|
if (!this.overridden && semver.gt(other.version, this.version)) {
|
|
526
|
-
return true
|
|
598
|
+
return true
|
|
527
599
|
}
|
|
528
|
-
return false
|
|
600
|
+
return false
|
|
529
601
|
}
|
|
530
602
|
|
|
531
603
|
// Is it safe to replace one node with another? check the edges to
|
|
@@ -539,7 +611,7 @@ class SafeNode extends Node {
|
|
|
539
611
|
// it with more tree construction, because it's a user request.
|
|
540
612
|
canReplaceWith(node, ignorePeers) {
|
|
541
613
|
if (this.name !== node.name || this.packageName !== node.packageName) {
|
|
542
|
-
return false
|
|
614
|
+
return false
|
|
543
615
|
}
|
|
544
616
|
// Patch replacing
|
|
545
617
|
// if (node.overrides !== this.overrides) {
|
|
@@ -553,11 +625,11 @@ class SafeNode extends Node {
|
|
|
553
625
|
// XXX need to check for two root nodes?
|
|
554
626
|
if (node.overrides) {
|
|
555
627
|
if (!node.overrides.isEqual(this.overrides)) {
|
|
556
|
-
return false
|
|
628
|
+
return false
|
|
557
629
|
}
|
|
558
630
|
} else {
|
|
559
631
|
if (this.overrides) {
|
|
560
|
-
return false
|
|
632
|
+
return false
|
|
561
633
|
}
|
|
562
634
|
}
|
|
563
635
|
}
|
|
@@ -565,29 +637,27 @@ class SafeNode extends Node {
|
|
|
565
637
|
// so that the condition we want to replace,
|
|
566
638
|
// if (this.overrides !== node.overrides) {
|
|
567
639
|
// , is not hit.`
|
|
568
|
-
const oldOverrideSet = this.overrides
|
|
569
|
-
let result = true
|
|
640
|
+
const oldOverrideSet = this.overrides
|
|
641
|
+
let result = true
|
|
570
642
|
if (oldOverrideSet !== node.overrides) {
|
|
571
|
-
this.overrides = node.overrides
|
|
643
|
+
this.overrides = node.overrides
|
|
572
644
|
}
|
|
573
645
|
try {
|
|
574
|
-
result = super.canReplaceWith(node, ignorePeers)
|
|
575
|
-
this.overrides = oldOverrideSet
|
|
646
|
+
result = super.canReplaceWith(node, ignorePeers)
|
|
647
|
+
this.overrides = oldOverrideSet
|
|
576
648
|
} catch (e) {
|
|
577
|
-
this.overrides = oldOverrideSet
|
|
578
|
-
throw e
|
|
649
|
+
this.overrides = oldOverrideSet
|
|
650
|
+
throw e
|
|
579
651
|
}
|
|
580
|
-
return result
|
|
652
|
+
return result
|
|
581
653
|
}
|
|
582
654
|
|
|
583
655
|
// Patch adding deleteEdgeIn is based on https://github.com/npm/cli/pull/8089.
|
|
584
656
|
deleteEdgeIn(edge) {
|
|
585
|
-
this.edgesIn.delete(edge)
|
|
586
|
-
const {
|
|
587
|
-
overrides
|
|
588
|
-
} = edge;
|
|
657
|
+
this.edgesIn.delete(edge)
|
|
658
|
+
const { overrides } = edge
|
|
589
659
|
if (overrides) {
|
|
590
|
-
this.updateOverridesEdgeInRemoved(overrides)
|
|
660
|
+
this.updateOverridesEdgeInRemoved(overrides)
|
|
591
661
|
}
|
|
592
662
|
}
|
|
593
663
|
addEdgeIn(edge) {
|
|
@@ -600,11 +670,11 @@ class SafeNode extends Node {
|
|
|
600
670
|
// We need to handle the case where the new edge in has an overrides field
|
|
601
671
|
// which is different from the current value.
|
|
602
672
|
if (!this.overrides || !this.overrides.isEqual(edge.overrides)) {
|
|
603
|
-
this.updateOverridesEdgeInAdded(edge.overrides)
|
|
673
|
+
this.updateOverridesEdgeInAdded(edge.overrides)
|
|
604
674
|
}
|
|
605
|
-
this.edgesIn.add(edge)
|
|
675
|
+
this.edgesIn.add(edge)
|
|
606
676
|
// Try to get metadata from the yarn.lock file.
|
|
607
|
-
this.root.meta?.addEdge(edge)
|
|
677
|
+
this.root.meta?.addEdge(edge)
|
|
608
678
|
}
|
|
609
679
|
|
|
610
680
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
@@ -612,8 +682,12 @@ class SafeNode extends Node {
|
|
|
612
682
|
// Patch replacing
|
|
613
683
|
// return !!(this.overrides && this.overrides.value && this.overrides.name === this.name)
|
|
614
684
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
615
|
-
if (
|
|
616
|
-
|
|
685
|
+
if (
|
|
686
|
+
!this.overrides ||
|
|
687
|
+
!this.overrides.value ||
|
|
688
|
+
this.overrides.name !== this.name
|
|
689
|
+
) {
|
|
690
|
+
return false
|
|
617
691
|
}
|
|
618
692
|
// The overrides rule is for a package with this name, but some override
|
|
619
693
|
// rules only apply to specific versions. To make sure this package was
|
|
@@ -621,13 +695,17 @@ class SafeNode extends Node {
|
|
|
621
695
|
// applied to it, in which case its overrides set is different than its
|
|
622
696
|
// source node.
|
|
623
697
|
for (const edge of this.edgesIn) {
|
|
624
|
-
if (
|
|
698
|
+
if (
|
|
699
|
+
edge.overrides &&
|
|
700
|
+
edge.overrides.name === this.name &&
|
|
701
|
+
edge.overrides.value === this.version
|
|
702
|
+
) {
|
|
625
703
|
if (!edge.overrides.isEqual(edge.from?.overrides)) {
|
|
626
|
-
return true
|
|
704
|
+
return true
|
|
627
705
|
}
|
|
628
706
|
}
|
|
629
707
|
}
|
|
630
|
-
return false
|
|
708
|
+
return false
|
|
631
709
|
}
|
|
632
710
|
set parent(newParent) {
|
|
633
711
|
// Patch removing
|
|
@@ -639,18 +717,16 @@ class SafeNode extends Node {
|
|
|
639
717
|
// The "parent" setter is a really large and complex function. To satisfy
|
|
640
718
|
// the patch we hold on to the old overrides value and set `this.overrides`
|
|
641
719
|
// to `undefined` so that the condition we want to remove is not hit.
|
|
642
|
-
const {
|
|
643
|
-
overrides
|
|
644
|
-
} = this;
|
|
720
|
+
const { overrides } = this
|
|
645
721
|
if (overrides) {
|
|
646
|
-
this.overrides = undefined
|
|
722
|
+
this.overrides = undefined
|
|
647
723
|
}
|
|
648
724
|
try {
|
|
649
|
-
super.parent = newParent
|
|
650
|
-
this.overrides = overrides
|
|
725
|
+
super.parent = newParent
|
|
726
|
+
this.overrides = overrides
|
|
651
727
|
} catch (e) {
|
|
652
|
-
this.overrides = overrides
|
|
653
|
-
throw e
|
|
728
|
+
this.overrides = overrides
|
|
729
|
+
throw e
|
|
654
730
|
}
|
|
655
731
|
}
|
|
656
732
|
|
|
@@ -659,9 +735,9 @@ class SafeNode extends Node {
|
|
|
659
735
|
recalculateOutEdgesOverrides() {
|
|
660
736
|
// For each edge out propagate the new overrides through.
|
|
661
737
|
for (const edge of this.edgesOut.values()) {
|
|
662
|
-
edge.reload(true)
|
|
738
|
+
edge.reload(true)
|
|
663
739
|
if (edge.to) {
|
|
664
|
-
edge.to.updateOverridesEdgeInAdded(edge.overrides)
|
|
740
|
+
edge.to.updateOverridesEdgeInAdded(edge.overrides)
|
|
665
741
|
}
|
|
666
742
|
}
|
|
667
743
|
}
|
|
@@ -680,14 +756,14 @@ class SafeNode extends Node {
|
|
|
680
756
|
if (!this.overrides) {
|
|
681
757
|
this.overrides = new SafeOverrideSet({
|
|
682
758
|
overrides: ''
|
|
683
|
-
})
|
|
759
|
+
})
|
|
684
760
|
}
|
|
685
761
|
try {
|
|
686
|
-
super.root = newRoot
|
|
687
|
-
this.overrides = undefined
|
|
762
|
+
super.root = newRoot
|
|
763
|
+
this.overrides = undefined
|
|
688
764
|
} catch (e) {
|
|
689
|
-
this.overrides = undefined
|
|
690
|
-
throw e
|
|
765
|
+
this.overrides = undefined
|
|
766
|
+
throw e
|
|
691
767
|
}
|
|
692
768
|
}
|
|
693
769
|
|
|
@@ -711,30 +787,33 @@ class SafeNode extends Node {
|
|
|
711
787
|
// undefined for any node at the end state of the tree. So if the new edge's
|
|
712
788
|
// overrides is undefined it will be updated later. So we can wait with
|
|
713
789
|
// updating the node's overrides field.
|
|
714
|
-
return false
|
|
790
|
+
return false
|
|
715
791
|
}
|
|
716
792
|
if (!this.overrides) {
|
|
717
|
-
this.overrides = otherOverrideSet
|
|
718
|
-
this.recalculateOutEdgesOverrides()
|
|
719
|
-
return true
|
|
793
|
+
this.overrides = otherOverrideSet
|
|
794
|
+
this.recalculateOutEdgesOverrides()
|
|
795
|
+
return true
|
|
720
796
|
}
|
|
721
797
|
if (this.overrides.isEqual(otherOverrideSet)) {
|
|
722
|
-
return false
|
|
798
|
+
return false
|
|
723
799
|
}
|
|
724
|
-
const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
800
|
+
const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
801
|
+
this.overrides,
|
|
802
|
+
otherOverrideSet
|
|
803
|
+
)
|
|
725
804
|
if (newOverrideSet) {
|
|
726
805
|
if (this.overrides.isEqual(newOverrideSet)) {
|
|
727
|
-
return false
|
|
806
|
+
return false
|
|
728
807
|
}
|
|
729
|
-
this.overrides = newOverrideSet
|
|
730
|
-
this.recalculateOutEdgesOverrides()
|
|
731
|
-
return true
|
|
808
|
+
this.overrides = newOverrideSet
|
|
809
|
+
this.recalculateOutEdgesOverrides()
|
|
810
|
+
return true
|
|
732
811
|
}
|
|
733
812
|
// This is an error condition. We can only get here if the new override set
|
|
734
813
|
// is in conflict with the existing.
|
|
735
|
-
const log = getLogger()
|
|
736
|
-
log?.silly('Conflicting override sets', this.name)
|
|
737
|
-
return false
|
|
814
|
+
const log = getLogger()
|
|
815
|
+
log?.silly('Conflicting override sets', this.name)
|
|
816
|
+
return false
|
|
738
817
|
}
|
|
739
818
|
|
|
740
819
|
// Patch adding updateOverridesEdgeInRemoved is based on
|
|
@@ -743,36 +822,37 @@ class SafeNode extends Node {
|
|
|
743
822
|
// If this edge's overrides isn't equal to this node's overrides,
|
|
744
823
|
// then removing it won't change newOverrideSet later.
|
|
745
824
|
if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) {
|
|
746
|
-
return false
|
|
825
|
+
return false
|
|
747
826
|
}
|
|
748
|
-
let newOverrideSet
|
|
827
|
+
let newOverrideSet
|
|
749
828
|
for (const edge of this.edgesIn) {
|
|
750
|
-
const {
|
|
751
|
-
overrides: edgeOverrides
|
|
752
|
-
} = edge;
|
|
829
|
+
const { overrides: edgeOverrides } = edge
|
|
753
830
|
if (newOverrideSet && edgeOverrides) {
|
|
754
|
-
newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
831
|
+
newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
832
|
+
edgeOverrides,
|
|
833
|
+
newOverrideSet
|
|
834
|
+
)
|
|
755
835
|
} else {
|
|
756
|
-
newOverrideSet = edgeOverrides
|
|
836
|
+
newOverrideSet = edgeOverrides
|
|
757
837
|
}
|
|
758
838
|
}
|
|
759
839
|
if (this.overrides.isEqual(newOverrideSet)) {
|
|
760
|
-
return false
|
|
840
|
+
return false
|
|
761
841
|
}
|
|
762
|
-
this.overrides = newOverrideSet
|
|
842
|
+
this.overrides = newOverrideSet
|
|
763
843
|
if (newOverrideSet) {
|
|
764
844
|
// Optimization: If there's any override set at all, then no non-extraneous
|
|
765
845
|
// node has an empty override set. So if we temporarily have no override set
|
|
766
846
|
// (for example, we removed all the edges in), there's no use updating all
|
|
767
847
|
// the edges out right now. Let's just wait until we have an actual override
|
|
768
848
|
// set later.
|
|
769
|
-
this.recalculateOutEdgesOverrides()
|
|
849
|
+
this.recalculateOutEdgesOverrides()
|
|
770
850
|
}
|
|
771
|
-
return true
|
|
851
|
+
return true
|
|
772
852
|
}
|
|
773
853
|
}
|
|
774
854
|
|
|
775
|
-
const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
|
|
855
|
+
const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
|
|
776
856
|
|
|
777
857
|
// The Edge class makes heavy use of private properties which subclasses do NOT
|
|
778
858
|
// have access to. So we have to recreate any functionality that relies on those
|
|
@@ -787,115 +867,129 @@ const Edge = require(shadowNpmPaths.getArboristEdgeClassPath());
|
|
|
787
867
|
// An edge in the dependency graph.
|
|
788
868
|
// Represents a dependency relationship of some kind.
|
|
789
869
|
class SafeEdge extends Edge {
|
|
790
|
-
#safeError
|
|
791
|
-
#safeExplanation
|
|
792
|
-
#safeFrom
|
|
793
|
-
#safeTo
|
|
870
|
+
#safeError
|
|
871
|
+
#safeExplanation
|
|
872
|
+
#safeFrom
|
|
873
|
+
#safeTo
|
|
794
874
|
constructor(options) {
|
|
795
|
-
const {
|
|
796
|
-
from
|
|
797
|
-
} = options;
|
|
875
|
+
const { from } = options
|
|
798
876
|
// Defer to supper to validate options and assign non-private values.
|
|
799
|
-
super(options)
|
|
877
|
+
super(options)
|
|
800
878
|
if (from.constructor !== SafeNode) {
|
|
801
|
-
Reflect.setPrototypeOf(from, SafeNode.prototype)
|
|
879
|
+
Reflect.setPrototypeOf(from, SafeNode.prototype)
|
|
802
880
|
}
|
|
803
|
-
this.#safeError = null
|
|
804
|
-
this.#safeExplanation = null
|
|
805
|
-
this.#safeFrom = from
|
|
806
|
-
this.#safeTo = null
|
|
807
|
-
this.reload(true)
|
|
881
|
+
this.#safeError = null
|
|
882
|
+
this.#safeExplanation = null
|
|
883
|
+
this.#safeFrom = from
|
|
884
|
+
this.#safeTo = null
|
|
885
|
+
this.reload(true)
|
|
808
886
|
}
|
|
809
887
|
get bundled() {
|
|
810
|
-
return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
|
|
888
|
+
return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
|
|
811
889
|
}
|
|
812
890
|
get error() {
|
|
813
891
|
if (!this.#safeError) {
|
|
814
892
|
if (!this.#safeTo) {
|
|
815
893
|
if (this.optional) {
|
|
816
|
-
this.#safeError = null
|
|
894
|
+
this.#safeError = null
|
|
817
895
|
} else {
|
|
818
|
-
this.#safeError = 'MISSING'
|
|
896
|
+
this.#safeError = 'MISSING'
|
|
819
897
|
}
|
|
820
|
-
} else if (
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
898
|
+
} else if (
|
|
899
|
+
this.peer &&
|
|
900
|
+
this.#safeFrom === this.#safeTo.parent &&
|
|
901
|
+
// Patch adding "?." use based on
|
|
902
|
+
// https://github.com/npm/cli/pull/8089.
|
|
903
|
+
!this.#safeFrom?.isTop
|
|
904
|
+
) {
|
|
905
|
+
this.#safeError = 'PEER LOCAL'
|
|
825
906
|
} else if (!this.satisfiedBy(this.#safeTo)) {
|
|
826
|
-
this.#safeError = 'INVALID'
|
|
907
|
+
this.#safeError = 'INVALID'
|
|
827
908
|
}
|
|
828
909
|
// Patch adding "else if" condition is based on
|
|
829
910
|
// https://github.com/npm/cli/pull/8089.
|
|
830
|
-
else if (
|
|
911
|
+
else if (
|
|
912
|
+
this.overrides &&
|
|
913
|
+
this.#safeTo.edgesOut.size &&
|
|
914
|
+
SafeOverrideSet.doOverrideSetsConflict(
|
|
915
|
+
this.overrides,
|
|
916
|
+
this.#safeTo.overrides
|
|
917
|
+
)
|
|
918
|
+
) {
|
|
831
919
|
// Any inconsistency between the edge's override set and the target's
|
|
832
920
|
// override set is potentially problematic. But we only say the edge is
|
|
833
921
|
// in error if the override sets are plainly conflicting. Note that if
|
|
834
922
|
// the target doesn't have any dependencies of their own, then this
|
|
835
923
|
// inconsistency is irrelevant.
|
|
836
|
-
this.#safeError = 'INVALID'
|
|
924
|
+
this.#safeError = 'INVALID'
|
|
837
925
|
} else {
|
|
838
|
-
this.#safeError = 'OK'
|
|
926
|
+
this.#safeError = 'OK'
|
|
839
927
|
}
|
|
840
928
|
}
|
|
841
929
|
if (this.#safeError === 'OK') {
|
|
842
|
-
return null
|
|
930
|
+
return null
|
|
843
931
|
}
|
|
844
|
-
return this.#safeError
|
|
932
|
+
return this.#safeError
|
|
845
933
|
}
|
|
846
934
|
|
|
847
935
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
848
936
|
get from() {
|
|
849
|
-
return this.#safeFrom
|
|
937
|
+
return this.#safeFrom
|
|
850
938
|
}
|
|
851
939
|
|
|
852
940
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
853
941
|
get spec() {
|
|
854
|
-
if (
|
|
942
|
+
if (
|
|
943
|
+
this.overrides?.value &&
|
|
944
|
+
this.overrides.value !== '*' &&
|
|
945
|
+
this.overrides.name === this.name
|
|
946
|
+
) {
|
|
855
947
|
if (this.overrides.value.startsWith('$')) {
|
|
856
|
-
const ref = this.overrides.value.slice(1)
|
|
948
|
+
const ref = this.overrides.value.slice(1)
|
|
857
949
|
// We may be a virtual root, if we are we want to resolve reference
|
|
858
950
|
// overrides from the real root, not the virtual one.
|
|
859
951
|
//
|
|
860
952
|
// Patch adding "?." use based on
|
|
861
953
|
// https://github.com/npm/cli/pull/8089.
|
|
862
|
-
const pkg = this.#safeFrom?.sourceReference
|
|
954
|
+
const pkg = this.#safeFrom?.sourceReference
|
|
955
|
+
? this.#safeFrom?.sourceReference.root.package
|
|
956
|
+
: this.#safeFrom?.root?.package
|
|
863
957
|
if (pkg?.devDependencies?.[ref]) {
|
|
864
|
-
return pkg.devDependencies[ref]
|
|
958
|
+
return pkg.devDependencies[ref]
|
|
865
959
|
}
|
|
866
960
|
if (pkg?.optionalDependencies?.[ref]) {
|
|
867
|
-
return pkg.optionalDependencies[ref]
|
|
961
|
+
return pkg.optionalDependencies[ref]
|
|
868
962
|
}
|
|
869
963
|
if (pkg?.dependencies?.[ref]) {
|
|
870
|
-
return pkg.dependencies[ref]
|
|
964
|
+
return pkg.dependencies[ref]
|
|
871
965
|
}
|
|
872
966
|
if (pkg?.peerDependencies?.[ref]) {
|
|
873
|
-
return pkg.peerDependencies[ref]
|
|
967
|
+
return pkg.peerDependencies[ref]
|
|
874
968
|
}
|
|
875
|
-
throw new Error(`Unable to resolve reference ${this.overrides.value}`)
|
|
969
|
+
throw new Error(`Unable to resolve reference ${this.overrides.value}`)
|
|
876
970
|
}
|
|
877
|
-
return this.overrides.value
|
|
971
|
+
return this.overrides.value
|
|
878
972
|
}
|
|
879
|
-
return this.rawSpec
|
|
973
|
+
return this.rawSpec
|
|
880
974
|
}
|
|
881
975
|
|
|
882
976
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
883
977
|
get to() {
|
|
884
|
-
return this.#safeTo
|
|
978
|
+
return this.#safeTo
|
|
885
979
|
}
|
|
886
980
|
detach() {
|
|
887
|
-
this.#safeExplanation = null
|
|
981
|
+
this.#safeExplanation = null
|
|
888
982
|
// Patch replacing
|
|
889
983
|
// if (this.#to) {
|
|
890
984
|
// this.#to.edgesIn.delete(this)
|
|
891
985
|
// }
|
|
892
986
|
// this.#from.edgesOut.delete(this.#name)
|
|
893
987
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
894
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
895
|
-
this.#safeFrom?.edgesOut.delete(this.name)
|
|
896
|
-
this.#safeTo = null
|
|
897
|
-
this.#safeError = 'DETACHED'
|
|
898
|
-
this.#safeFrom = null
|
|
988
|
+
this.#safeTo?.deleteEdgeIn(this)
|
|
989
|
+
this.#safeFrom?.edgesOut.delete(this.name)
|
|
990
|
+
this.#safeTo = null
|
|
991
|
+
this.#safeError = 'DETACHED'
|
|
992
|
+
this.#safeFrom = null
|
|
899
993
|
}
|
|
900
994
|
|
|
901
995
|
// Return the edge data, and an explanation of how that edge came to be here.
|
|
@@ -911,66 +1005,66 @@ class SafeEdge extends Edge {
|
|
|
911
1005
|
error: undefined,
|
|
912
1006
|
from: undefined,
|
|
913
1007
|
rawSpec: undefined
|
|
914
|
-
}
|
|
1008
|
+
}
|
|
915
1009
|
if (this.rawSpec !== this.spec) {
|
|
916
|
-
explanation.rawSpec = this.rawSpec
|
|
917
|
-
explanation.overridden = true
|
|
1010
|
+
explanation.rawSpec = this.rawSpec
|
|
1011
|
+
explanation.overridden = true
|
|
918
1012
|
}
|
|
919
1013
|
if (this.bundled) {
|
|
920
|
-
explanation.bundled = this.bundled
|
|
1014
|
+
explanation.bundled = this.bundled
|
|
921
1015
|
}
|
|
922
1016
|
if (this.error) {
|
|
923
|
-
explanation.error = this.error
|
|
1017
|
+
explanation.error = this.error
|
|
924
1018
|
}
|
|
925
1019
|
if (this.#safeFrom) {
|
|
926
|
-
explanation.from = this.#safeFrom.explain()
|
|
1020
|
+
explanation.from = this.#safeFrom.explain()
|
|
927
1021
|
}
|
|
928
|
-
this.#safeExplanation = explanation
|
|
1022
|
+
this.#safeExplanation = explanation
|
|
929
1023
|
}
|
|
930
|
-
return this.#safeExplanation
|
|
1024
|
+
return this.#safeExplanation
|
|
931
1025
|
}
|
|
932
1026
|
reload(hard = false) {
|
|
933
|
-
this.#safeExplanation = null
|
|
1027
|
+
this.#safeExplanation = null
|
|
934
1028
|
// Patch replacing
|
|
935
1029
|
// if (this.#from.overrides) {
|
|
936
1030
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
937
|
-
let needToUpdateOverrideSet = false
|
|
938
|
-
let newOverrideSet
|
|
939
|
-
let oldOverrideSet
|
|
1031
|
+
let needToUpdateOverrideSet = false
|
|
1032
|
+
let newOverrideSet
|
|
1033
|
+
let oldOverrideSet
|
|
940
1034
|
if (this.#safeFrom?.overrides) {
|
|
941
|
-
newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
|
|
1035
|
+
newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
|
|
942
1036
|
if (newOverrideSet && !newOverrideSet.isEqual(this.overrides)) {
|
|
943
1037
|
// If there's a new different override set we need to propagate it to
|
|
944
1038
|
// the nodes. If we're deleting the override set then there's no point
|
|
945
1039
|
// propagating it right now since it will be filled with another value
|
|
946
1040
|
// later.
|
|
947
|
-
needToUpdateOverrideSet = true
|
|
948
|
-
oldOverrideSet = this.overrides
|
|
949
|
-
this.overrides = newOverrideSet
|
|
1041
|
+
needToUpdateOverrideSet = true
|
|
1042
|
+
oldOverrideSet = this.overrides
|
|
1043
|
+
this.overrides = newOverrideSet
|
|
950
1044
|
}
|
|
951
1045
|
} else {
|
|
952
|
-
this.overrides = undefined
|
|
1046
|
+
this.overrides = undefined
|
|
953
1047
|
}
|
|
954
1048
|
// Patch adding "?." use based on
|
|
955
1049
|
// https://github.com/npm/cli/pull/8089.
|
|
956
|
-
const newTo = this.#safeFrom?.resolve(this.name)
|
|
1050
|
+
const newTo = this.#safeFrom?.resolve(this.name)
|
|
957
1051
|
if (newTo !== this.#safeTo) {
|
|
958
1052
|
// Patch replacing
|
|
959
1053
|
// this.#to.edgesIn.delete(this)
|
|
960
1054
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
961
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
962
|
-
this.#safeTo = newTo ?? null
|
|
963
|
-
this.#safeError = null
|
|
964
|
-
this.#safeTo?.addEdgeIn(this)
|
|
1055
|
+
this.#safeTo?.deleteEdgeIn(this)
|
|
1056
|
+
this.#safeTo = newTo ?? null
|
|
1057
|
+
this.#safeError = null
|
|
1058
|
+
this.#safeTo?.addEdgeIn(this)
|
|
965
1059
|
} else if (hard) {
|
|
966
|
-
this.#safeError = null
|
|
1060
|
+
this.#safeError = null
|
|
967
1061
|
}
|
|
968
1062
|
// Patch adding "else if" condition based on
|
|
969
1063
|
// https://github.com/npm/cli/pull/8089.
|
|
970
1064
|
else if (needToUpdateOverrideSet && this.#safeTo) {
|
|
971
1065
|
// Propagate the new override set to the target node.
|
|
972
|
-
this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
|
|
973
|
-
this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
|
|
1066
|
+
this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
|
|
1067
|
+
this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
|
|
974
1068
|
}
|
|
975
1069
|
}
|
|
976
1070
|
satisfiedBy(node) {
|
|
@@ -980,12 +1074,12 @@ class SafeEdge extends Edge {
|
|
|
980
1074
|
// }
|
|
981
1075
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
982
1076
|
if (node.name !== this.name || !this.#safeFrom) {
|
|
983
|
-
return false
|
|
1077
|
+
return false
|
|
984
1078
|
}
|
|
985
1079
|
// NOTE: this condition means we explicitly do not support overriding
|
|
986
1080
|
// bundled or shrinkwrapped dependencies
|
|
987
1081
|
if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
|
|
988
|
-
return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
|
|
1082
|
+
return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
|
|
989
1083
|
}
|
|
990
1084
|
// Patch replacing
|
|
991
1085
|
// return depValid(node, this.spec, this.#accept, this.#from)
|
|
@@ -993,16 +1087,16 @@ class SafeEdge extends Edge {
|
|
|
993
1087
|
//
|
|
994
1088
|
// If there's no override we just use the spec.
|
|
995
1089
|
if (!this.overrides?.keySpec) {
|
|
996
|
-
return depValid(node, this.spec, this.accept, this.#safeFrom)
|
|
1090
|
+
return depValid(node, this.spec, this.accept, this.#safeFrom)
|
|
997
1091
|
}
|
|
998
1092
|
// There's some override. If the target node satisfies the overriding spec
|
|
999
1093
|
// then it's okay.
|
|
1000
1094
|
if (depValid(node, this.spec, this.accept, this.#safeFrom)) {
|
|
1001
|
-
return true
|
|
1095
|
+
return true
|
|
1002
1096
|
}
|
|
1003
1097
|
// If it doesn't, then it should at least satisfy the original spec.
|
|
1004
1098
|
if (!depValid(node, this.rawSpec, this.accept, this.#safeFrom)) {
|
|
1005
|
-
return false
|
|
1099
|
+
return false
|
|
1006
1100
|
}
|
|
1007
1101
|
// It satisfies the original spec, not the overriding spec. We need to make
|
|
1008
1102
|
// sure it doesn't use the overridden spec.
|
|
@@ -1014,7 +1108,7 @@ class SafeEdge extends Edge {
|
|
|
1014
1108
|
// If the node is 8.23.0, then it's not okay because even though it's consistent
|
|
1015
1109
|
// with the rawSpec, it's also consistent with the keySpec.
|
|
1016
1110
|
// So we're looking for ^8.0.0 or 9.0.0 and not 8.23.0.
|
|
1017
|
-
return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
|
|
1111
|
+
return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
|
|
1018
1112
|
}
|
|
1019
1113
|
}
|
|
1020
1114
|
|
|
@@ -1023,364 +1117,260 @@ const {
|
|
|
1023
1117
|
ALERT_TYPE_CVE,
|
|
1024
1118
|
ALERT_TYPE_MEDIUM_CVE,
|
|
1025
1119
|
ALERT_TYPE_MILD_CVE
|
|
1026
|
-
} = constants
|
|
1120
|
+
} = constants
|
|
1027
1121
|
function isArtifactAlertCve(alert) {
|
|
1028
|
-
const {
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
ALERT_FIX_TYPE["cve"] = "cve";
|
|
1036
|
-
ALERT_FIX_TYPE["upgrade"] = "upgrade";
|
|
1037
|
-
return ALERT_FIX_TYPE;
|
|
1038
|
-
}({});
|
|
1039
|
-
|
|
1040
|
-
const ERROR_UX = {
|
|
1041
|
-
block: true,
|
|
1042
|
-
display: true
|
|
1043
|
-
};
|
|
1044
|
-
const IGNORE_UX = {
|
|
1045
|
-
block: false,
|
|
1046
|
-
display: false
|
|
1047
|
-
};
|
|
1048
|
-
const WARN_UX = {
|
|
1049
|
-
block: false,
|
|
1050
|
-
display: true
|
|
1051
|
-
};
|
|
1052
|
-
|
|
1053
|
-
// Iterates over all entries with ordered issue rule for deferral. Iterates over
|
|
1054
|
-
// all issue rules and finds the first defined value that does not defer otherwise
|
|
1055
|
-
// uses the defaultValue. Takes the value and converts into a UX workflow.
|
|
1056
|
-
function resolveAlertRuleUX(orderedRulesCollection, defaultValue) {
|
|
1057
|
-
if (defaultValue === true || defaultValue === null || defaultValue === undefined) {
|
|
1058
|
-
defaultValue = {
|
|
1059
|
-
action: 'error'
|
|
1060
|
-
};
|
|
1061
|
-
} else if (defaultValue === false) {
|
|
1062
|
-
defaultValue = {
|
|
1063
|
-
action: 'ignore'
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
let block = false;
|
|
1067
|
-
let display = false;
|
|
1068
|
-
let needDefault = true;
|
|
1069
|
-
iterate_entries: for (const rules of orderedRulesCollection) {
|
|
1070
|
-
for (const rule of rules) {
|
|
1071
|
-
if (ruleValueDoesNotDefer(rule)) {
|
|
1072
|
-
needDefault = false;
|
|
1073
|
-
const narrowingFilter = uxForDefinedNonDeferValue(rule);
|
|
1074
|
-
block = block || narrowingFilter.block;
|
|
1075
|
-
display = display || narrowingFilter.display;
|
|
1076
|
-
continue iterate_entries;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
1080
|
-
block = block || narrowingFilter.block;
|
|
1081
|
-
display = display || narrowingFilter.display;
|
|
1082
|
-
}
|
|
1083
|
-
if (needDefault) {
|
|
1084
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
1085
|
-
block = block || narrowingFilter.block;
|
|
1086
|
-
display = display || narrowingFilter.display;
|
|
1087
|
-
}
|
|
1088
|
-
return {
|
|
1089
|
-
block,
|
|
1090
|
-
display
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
// Negative form because it is narrowing the type.
|
|
1095
|
-
function ruleValueDoesNotDefer(rule) {
|
|
1096
|
-
if (rule === undefined) {
|
|
1097
|
-
return false;
|
|
1098
|
-
}
|
|
1099
|
-
if (objects.isObject(rule)) {
|
|
1100
|
-
const {
|
|
1101
|
-
action
|
|
1102
|
-
} = rule;
|
|
1103
|
-
if (action === undefined || action === 'defer') {
|
|
1104
|
-
return false;
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
return true;
|
|
1122
|
+
const { type } = alert
|
|
1123
|
+
return (
|
|
1124
|
+
type === ALERT_TYPE_CVE ||
|
|
1125
|
+
type === ALERT_TYPE_MEDIUM_CVE ||
|
|
1126
|
+
type === ALERT_TYPE_MILD_CVE ||
|
|
1127
|
+
type === ALERT_TYPE_CRITICAL_CVE
|
|
1128
|
+
)
|
|
1108
1129
|
}
|
|
1109
1130
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
const {
|
|
1116
|
-
action
|
|
1117
|
-
} = ruleValue;
|
|
1118
|
-
if (action === 'warn') {
|
|
1119
|
-
return WARN_UX;
|
|
1120
|
-
} else if (action === 'ignore') {
|
|
1121
|
-
return IGNORE_UX;
|
|
1122
|
-
}
|
|
1123
|
-
return ERROR_UX;
|
|
1124
|
-
}
|
|
1125
|
-
function createAlertUXLookup(settings) {
|
|
1126
|
-
const cachedUX = new Map();
|
|
1127
|
-
return context => {
|
|
1128
|
-
const {
|
|
1129
|
-
type
|
|
1130
|
-
} = context.alert;
|
|
1131
|
-
let ux = cachedUX.get(type);
|
|
1132
|
-
if (ux) {
|
|
1133
|
-
return ux;
|
|
1134
|
-
}
|
|
1135
|
-
const orderedRulesCollection = [];
|
|
1136
|
-
for (const settingsEntry of settings.entries) {
|
|
1137
|
-
const orderedRules = [];
|
|
1138
|
-
let target = settingsEntry.start;
|
|
1139
|
-
while (target !== null) {
|
|
1140
|
-
const resolvedTarget = settingsEntry.settings[target];
|
|
1141
|
-
if (!resolvedTarget) {
|
|
1142
|
-
break;
|
|
1143
|
-
}
|
|
1144
|
-
const issueRuleValue = resolvedTarget.issueRules?.[type];
|
|
1145
|
-
if (typeof issueRuleValue !== 'undefined') {
|
|
1146
|
-
orderedRules.push(issueRuleValue);
|
|
1147
|
-
}
|
|
1148
|
-
target = resolvedTarget.deferTo ?? null;
|
|
1149
|
-
}
|
|
1150
|
-
orderedRulesCollection.push(orderedRules);
|
|
1151
|
-
}
|
|
1152
|
-
const defaultValue = settings.defaults.issueRules[type];
|
|
1153
|
-
let resolvedDefaultValue = {
|
|
1154
|
-
action: 'error'
|
|
1155
|
-
};
|
|
1156
|
-
if (defaultValue === false) {
|
|
1157
|
-
resolvedDefaultValue = {
|
|
1158
|
-
action: 'ignore'
|
|
1159
|
-
};
|
|
1160
|
-
} else if (defaultValue && defaultValue !== true) {
|
|
1161
|
-
resolvedDefaultValue = {
|
|
1162
|
-
action: defaultValue.action ?? 'error'
|
|
1163
|
-
};
|
|
1164
|
-
}
|
|
1165
|
-
ux = resolveAlertRuleUX(orderedRulesCollection, resolvedDefaultValue);
|
|
1166
|
-
cachedUX.set(type, ux);
|
|
1167
|
-
return ux;
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
let _uxLookup;
|
|
1171
|
-
async function uxLookup(settings) {
|
|
1172
|
-
if (_uxLookup === undefined) {
|
|
1173
|
-
const {
|
|
1174
|
-
orgs,
|
|
1175
|
-
settings
|
|
1176
|
-
} = await (async () => {
|
|
1177
|
-
try {
|
|
1178
|
-
const sockSdk = await setupSdk(getPublicToken());
|
|
1179
|
-
const orgResult = await sockSdk.getOrganizations();
|
|
1180
|
-
if (!orgResult.success) {
|
|
1181
|
-
if (orgResult.status === 429) {
|
|
1182
|
-
throw new Error(`API token quota exceeded: ${orgResult.error}`);
|
|
1183
|
-
}
|
|
1184
|
-
throw new Error(`Failed to fetch Socket organization info: ${orgResult.error}`);
|
|
1185
|
-
}
|
|
1186
|
-
const {
|
|
1187
|
-
organizations
|
|
1188
|
-
} = orgResult.data;
|
|
1189
|
-
const orgs = [];
|
|
1190
|
-
for (const org of Object.values(organizations)) {
|
|
1191
|
-
if (org) {
|
|
1192
|
-
orgs.push(org);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
const settingsResult = await sockSdk.postSettings(orgs.map(org => ({
|
|
1196
|
-
organization: org.id
|
|
1197
|
-
})));
|
|
1198
|
-
if (!settingsResult.success) {
|
|
1199
|
-
throw new Error(`Failed to fetch API key settings: ${settingsResult.error}`);
|
|
1200
|
-
}
|
|
1201
|
-
return {
|
|
1202
|
-
orgs,
|
|
1203
|
-
settings: settingsResult.data
|
|
1204
|
-
};
|
|
1205
|
-
} catch (e) {
|
|
1206
|
-
const cause = objects.isObject(e) && 'cause' in e ? e['cause'] : undefined;
|
|
1207
|
-
if (isErrnoException(cause) && (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED')) {
|
|
1208
|
-
throw new Error('Unable to connect to socket.dev, ensure internet connectivity before retrying', {
|
|
1209
|
-
cause: e
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
throw e;
|
|
1213
|
-
}
|
|
1214
|
-
})();
|
|
1215
|
-
// Remove any organizations not being enforced.
|
|
1216
|
-
const enforcedOrgs = getSetting('enforcedOrgs') ?? [];
|
|
1217
|
-
for (const {
|
|
1218
|
-
0: i,
|
|
1219
|
-
1: org
|
|
1220
|
-
} of orgs.entries()) {
|
|
1221
|
-
if (!enforcedOrgs.includes(org.id)) {
|
|
1222
|
-
settings.entries.splice(i, 1);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
const socketYml = findSocketYmlSync();
|
|
1226
|
-
if (socketYml) {
|
|
1227
|
-
settings.entries.push({
|
|
1228
|
-
start: socketYml.path,
|
|
1229
|
-
settings: {
|
|
1230
|
-
[socketYml.path]: {
|
|
1231
|
-
deferTo: null,
|
|
1232
|
-
// TODO: TypeScript complains about the type not matching. We should
|
|
1233
|
-
// figure out why are providing
|
|
1234
|
-
// issueRules: { [issueName: string]: boolean }
|
|
1235
|
-
// but expecting
|
|
1236
|
-
// issueRules: { [issueName: string]: { action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' } }
|
|
1237
|
-
issueRules: socketYml.parsed.issueRules
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
});
|
|
1241
|
-
}
|
|
1242
|
-
_uxLookup = createAlertUXLookup(settings);
|
|
1243
|
-
}
|
|
1244
|
-
return _uxLookup(settings);
|
|
1245
|
-
}
|
|
1131
|
+
const ALERT_FIX_TYPE = /*#__PURE__*/ (function (ALERT_FIX_TYPE) {
|
|
1132
|
+
ALERT_FIX_TYPE['cve'] = 'cve'
|
|
1133
|
+
ALERT_FIX_TYPE['upgrade'] = 'upgrade'
|
|
1134
|
+
return ALERT_FIX_TYPE
|
|
1135
|
+
})({})
|
|
1246
1136
|
|
|
1247
1137
|
function pick(input, keys) {
|
|
1248
|
-
const result = {}
|
|
1138
|
+
const result = {}
|
|
1249
1139
|
for (const key of keys) {
|
|
1250
|
-
result[key] = input[key]
|
|
1140
|
+
result[key] = input[key]
|
|
1251
1141
|
}
|
|
1252
|
-
return result
|
|
1142
|
+
return result
|
|
1253
1143
|
}
|
|
1254
1144
|
|
|
1255
1145
|
function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
|
|
1256
|
-
const values = list.filter(Boolean)
|
|
1257
|
-
const {
|
|
1258
|
-
length
|
|
1259
|
-
} = values;
|
|
1146
|
+
const values = list.filter(Boolean)
|
|
1147
|
+
const { length } = values
|
|
1260
1148
|
if (!length) {
|
|
1261
|
-
return ''
|
|
1149
|
+
return ''
|
|
1262
1150
|
}
|
|
1263
1151
|
if (length === 1) {
|
|
1264
|
-
return values[0]
|
|
1152
|
+
return values[0]
|
|
1265
1153
|
}
|
|
1266
|
-
const finalValue = values.pop()
|
|
1267
|
-
return `${values.join(', ')}${separator}${finalValue}
|
|
1154
|
+
const finalValue = values.pop()
|
|
1155
|
+
return `${values.join(', ')}${separator}${finalValue}`
|
|
1268
1156
|
}
|
|
1269
1157
|
|
|
1270
|
-
|
|
1271
|
-
ALERT_SEVERITY[
|
|
1272
|
-
ALERT_SEVERITY[
|
|
1273
|
-
ALERT_SEVERITY[
|
|
1274
|
-
ALERT_SEVERITY[
|
|
1275
|
-
return ALERT_SEVERITY
|
|
1276
|
-
}({})
|
|
1158
|
+
const ALERT_SEVERITY = /*#__PURE__*/ (function (ALERT_SEVERITY) {
|
|
1159
|
+
ALERT_SEVERITY['critical'] = 'critical'
|
|
1160
|
+
ALERT_SEVERITY['high'] = 'high'
|
|
1161
|
+
ALERT_SEVERITY['middle'] = 'middle'
|
|
1162
|
+
ALERT_SEVERITY['low'] = 'low'
|
|
1163
|
+
return ALERT_SEVERITY
|
|
1164
|
+
})({})
|
|
1277
1165
|
// Ordered from most severe to least.
|
|
1278
|
-
const
|
|
1166
|
+
const ALERT_SEVERITIES_SORTED = Object.freeze([
|
|
1167
|
+
'critical',
|
|
1168
|
+
'high',
|
|
1169
|
+
'middle',
|
|
1170
|
+
'low'
|
|
1171
|
+
])
|
|
1279
1172
|
function getDesiredSeverities(lowestToInclude) {
|
|
1280
|
-
const result = []
|
|
1281
|
-
for (const severity of
|
|
1282
|
-
result.push(severity)
|
|
1173
|
+
const result = []
|
|
1174
|
+
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1175
|
+
result.push(severity)
|
|
1283
1176
|
if (severity === lowestToInclude) {
|
|
1284
|
-
break
|
|
1177
|
+
break
|
|
1285
1178
|
}
|
|
1286
1179
|
}
|
|
1287
|
-
return result
|
|
1180
|
+
return result
|
|
1288
1181
|
}
|
|
1289
1182
|
function formatSeverityCount(severityCount) {
|
|
1290
|
-
const summary = []
|
|
1291
|
-
for (const severity of
|
|
1183
|
+
const summary = []
|
|
1184
|
+
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1292
1185
|
if (severityCount[severity]) {
|
|
1293
|
-
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1186
|
+
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1294
1187
|
}
|
|
1295
1188
|
}
|
|
1296
|
-
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1189
|
+
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1297
1190
|
}
|
|
1298
1191
|
function getSeverityCount(issues, lowestToInclude) {
|
|
1299
|
-
const severityCount = pick(
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1192
|
+
const severityCount = pick(
|
|
1193
|
+
{
|
|
1194
|
+
low: 0,
|
|
1195
|
+
middle: 0,
|
|
1196
|
+
high: 0,
|
|
1197
|
+
critical: 0
|
|
1198
|
+
},
|
|
1199
|
+
getDesiredSeverities(lowestToInclude)
|
|
1200
|
+
)
|
|
1305
1201
|
for (const issue of issues) {
|
|
1306
|
-
const {
|
|
1307
|
-
value
|
|
1308
|
-
} = issue;
|
|
1202
|
+
const { value } = issue
|
|
1309
1203
|
if (!value) {
|
|
1310
|
-
continue
|
|
1204
|
+
continue
|
|
1311
1205
|
}
|
|
1312
|
-
const {
|
|
1313
|
-
severity
|
|
1314
|
-
} = value;
|
|
1206
|
+
const { severity } = value
|
|
1315
1207
|
if (severityCount[severity] !== undefined) {
|
|
1316
|
-
severityCount[severity] += 1
|
|
1208
|
+
severityCount[severity] += 1
|
|
1317
1209
|
}
|
|
1318
1210
|
}
|
|
1319
|
-
return severityCount
|
|
1211
|
+
return severityCount
|
|
1320
1212
|
}
|
|
1321
1213
|
|
|
1322
1214
|
class ColorOrMarkdown {
|
|
1323
1215
|
constructor(useMarkdown) {
|
|
1324
|
-
this.useMarkdown = !!useMarkdown
|
|
1216
|
+
this.useMarkdown = !!useMarkdown
|
|
1325
1217
|
}
|
|
1326
1218
|
bold(text) {
|
|
1327
|
-
return this.useMarkdown ? `**${text}**` : colors.bold(`${text}`)
|
|
1219
|
+
return this.useMarkdown ? `**${text}**` : colors.bold(`${text}`)
|
|
1328
1220
|
}
|
|
1329
1221
|
header(text, level = 1) {
|
|
1330
|
-
return this.useMarkdown
|
|
1222
|
+
return this.useMarkdown
|
|
1223
|
+
? `\n${''.padStart(level, '#')} ${text}\n`
|
|
1224
|
+
: colors.underline(`\n${level === 1 ? colors.bold(text) : text}\n`)
|
|
1331
1225
|
}
|
|
1332
|
-
hyperlink(text, url, {
|
|
1333
|
-
fallback = true,
|
|
1334
|
-
fallbackToUrl
|
|
1335
|
-
} = {}) {
|
|
1226
|
+
hyperlink(text, url, { fallback = true, fallbackToUrl } = {}) {
|
|
1336
1227
|
if (url) {
|
|
1337
|
-
return this.useMarkdown
|
|
1338
|
-
|
|
1339
|
-
|
|
1228
|
+
return this.useMarkdown
|
|
1229
|
+
? `[${text}](${url})`
|
|
1230
|
+
: terminalLink(text, url, {
|
|
1231
|
+
fallback: fallbackToUrl ? (_text, url) => url : fallback
|
|
1232
|
+
})
|
|
1340
1233
|
}
|
|
1341
|
-
return text
|
|
1234
|
+
return text
|
|
1342
1235
|
}
|
|
1343
1236
|
indent(...args) {
|
|
1344
|
-
return indentString(...args)
|
|
1237
|
+
return indentString(...args)
|
|
1345
1238
|
}
|
|
1346
1239
|
italic(text) {
|
|
1347
|
-
return this.useMarkdown ? `_${text}_` : colors.italic(`${text}`)
|
|
1240
|
+
return this.useMarkdown ? `_${text}_` : colors.italic(`${text}`)
|
|
1348
1241
|
}
|
|
1349
1242
|
json(value) {
|
|
1350
|
-
return this.useMarkdown
|
|
1243
|
+
return this.useMarkdown
|
|
1244
|
+
? '```json\n' + JSON.stringify(value) + '\n```'
|
|
1245
|
+
: JSON.stringify(value)
|
|
1351
1246
|
}
|
|
1352
1247
|
list(items) {
|
|
1353
|
-
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
1354
|
-
return this.useMarkdown
|
|
1248
|
+
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
1249
|
+
return this.useMarkdown
|
|
1250
|
+
? `* ${indentedContent.join('\n* ')}\n`
|
|
1251
|
+
: `${indentedContent.join('\n')}\n`
|
|
1355
1252
|
}
|
|
1356
1253
|
}
|
|
1357
1254
|
|
|
1358
1255
|
function getSocketDevAlertUrl(alertType) {
|
|
1359
|
-
return `https://socket.dev/alerts/${alertType}
|
|
1256
|
+
return `https://socket.dev/alerts/${alertType}`
|
|
1360
1257
|
}
|
|
1361
1258
|
function getSocketDevPackageOverviewUrl(eco, name, version) {
|
|
1362
|
-
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}
|
|
1259
|
+
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}`
|
|
1363
1260
|
}
|
|
1364
1261
|
|
|
1365
|
-
let _translations
|
|
1262
|
+
let _translations
|
|
1366
1263
|
function getTranslations() {
|
|
1367
1264
|
if (_translations === undefined) {
|
|
1368
1265
|
_translations = require(
|
|
1369
|
-
|
|
1370
|
-
|
|
1266
|
+
// Lazily access constants.rootPath.
|
|
1267
|
+
path.join(constants.rootPath, 'translations.json')
|
|
1268
|
+
)
|
|
1371
1269
|
}
|
|
1372
|
-
return _translations
|
|
1270
|
+
return _translations
|
|
1373
1271
|
}
|
|
1374
1272
|
|
|
1375
|
-
const {
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1273
|
+
const ALERT_SEVERITY_COLOR = /*#__PURE__*/ (function (ALERT_SEVERITY_COLOR) {
|
|
1274
|
+
ALERT_SEVERITY_COLOR['critical'] = 'magenta'
|
|
1275
|
+
ALERT_SEVERITY_COLOR['high'] = 'red'
|
|
1276
|
+
ALERT_SEVERITY_COLOR['middle'] = 'yellow'
|
|
1277
|
+
ALERT_SEVERITY_COLOR['low'] = 'white'
|
|
1278
|
+
return ALERT_SEVERITY_COLOR
|
|
1279
|
+
})({})
|
|
1280
|
+
const ALERT_SEVERITY_ORDER = /*#__PURE__*/ (function (ALERT_SEVERITY_ORDER) {
|
|
1281
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['critical'] = 0)] = 'critical'
|
|
1282
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['high'] = 1)] = 'high'
|
|
1283
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['middle'] = 2)] = 'middle'
|
|
1284
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['low'] = 3)] = 'low'
|
|
1285
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['none'] = 4)] = 'none'
|
|
1286
|
+
return ALERT_SEVERITY_ORDER
|
|
1287
|
+
})({})
|
|
1288
|
+
const { CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER, NPM: NPM$2 } =
|
|
1289
|
+
constants
|
|
1290
|
+
const MIN_ABOVE_THE_FOLD_COUNT = 3
|
|
1291
|
+
const MIN_ABOVE_THE_FOLD_ALERT_COUNT = 1
|
|
1292
|
+
const format = new ColorOrMarkdown(false)
|
|
1293
|
+
function alertsHaveBlocked(alerts) {
|
|
1294
|
+
return alerts.find(a => a.blocked) !== undefined
|
|
1295
|
+
}
|
|
1296
|
+
function alertsHaveSeverity(alerts, severity) {
|
|
1297
|
+
return alerts.find(a => a.raw.severity === severity) !== undefined
|
|
1298
|
+
}
|
|
1299
|
+
function alertSeverityComparator(a, b) {
|
|
1300
|
+
return getAlertSeverityOrder(a) - getAlertSeverityOrder(b)
|
|
1301
|
+
}
|
|
1302
|
+
function getAlertSeverityOrder(alert) {
|
|
1303
|
+
const { severity } = alert.raw
|
|
1304
|
+
return severity === ALERT_SEVERITY.critical
|
|
1305
|
+
? 0
|
|
1306
|
+
: severity === ALERT_SEVERITY.high
|
|
1307
|
+
? 1
|
|
1308
|
+
: severity === ALERT_SEVERITY.middle
|
|
1309
|
+
? 2
|
|
1310
|
+
: severity === ALERT_SEVERITY.low
|
|
1311
|
+
? 3
|
|
1312
|
+
: 4
|
|
1313
|
+
}
|
|
1314
|
+
function getAlertsSeverityOrder(alerts) {
|
|
1315
|
+
return alertsHaveBlocked(alerts) ||
|
|
1316
|
+
alertsHaveSeverity(alerts, ALERT_SEVERITY.critical)
|
|
1317
|
+
? 0
|
|
1318
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.high)
|
|
1319
|
+
? 1
|
|
1320
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.middle)
|
|
1321
|
+
? 2
|
|
1322
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.low)
|
|
1323
|
+
? 3
|
|
1324
|
+
: 4
|
|
1325
|
+
}
|
|
1326
|
+
function getHiddenRiskCounts(hiddenAlerts) {
|
|
1327
|
+
const riskCounts = {
|
|
1328
|
+
critical: 0,
|
|
1329
|
+
high: 0,
|
|
1330
|
+
middle: 0,
|
|
1331
|
+
low: 0
|
|
1332
|
+
}
|
|
1333
|
+
for (const alert of hiddenAlerts) {
|
|
1334
|
+
switch (getAlertSeverityOrder(alert)) {
|
|
1335
|
+
case ALERT_SEVERITY_ORDER.critical:
|
|
1336
|
+
riskCounts.critical += 1
|
|
1337
|
+
break
|
|
1338
|
+
case ALERT_SEVERITY_ORDER.high:
|
|
1339
|
+
riskCounts.high += 1
|
|
1340
|
+
break
|
|
1341
|
+
case ALERT_SEVERITY_ORDER.middle:
|
|
1342
|
+
riskCounts.middle += 1
|
|
1343
|
+
break
|
|
1344
|
+
case ALERT_SEVERITY_ORDER.low:
|
|
1345
|
+
riskCounts.low += 1
|
|
1346
|
+
break
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
return riskCounts
|
|
1350
|
+
}
|
|
1351
|
+
function getHiddenRisksDescription(riskCounts) {
|
|
1352
|
+
const descriptions = []
|
|
1353
|
+
if (riskCounts.critical) {
|
|
1354
|
+
descriptions.push(`${riskCounts.critical} ${getSeverityLabel('critical')}`)
|
|
1355
|
+
}
|
|
1356
|
+
if (riskCounts.high) {
|
|
1357
|
+
descriptions.push(`${riskCounts.high} ${getSeverityLabel('high')}`)
|
|
1358
|
+
}
|
|
1359
|
+
if (riskCounts.middle) {
|
|
1360
|
+
descriptions.push(`${riskCounts.middle} ${getSeverityLabel('middle')}`)
|
|
1361
|
+
}
|
|
1362
|
+
if (riskCounts.low) {
|
|
1363
|
+
descriptions.push(`${riskCounts.low} ${getSeverityLabel('low')}`)
|
|
1364
|
+
}
|
|
1365
|
+
return `(${descriptions.join('; ')})`
|
|
1366
|
+
}
|
|
1367
|
+
function getSeverityLabel(severity) {
|
|
1368
|
+
return severity === 'middle' ? 'moderate' : severity
|
|
1369
|
+
}
|
|
1380
1370
|
async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
1381
1371
|
// Make TypeScript happy.
|
|
1382
1372
|
if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
|
|
1383
|
-
return alertsByPkgId
|
|
1373
|
+
return alertsByPkgId
|
|
1384
1374
|
}
|
|
1385
1375
|
const {
|
|
1386
1376
|
consolidate = false,
|
|
@@ -1389,176 +1379,322 @@ async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
|
1389
1379
|
} = {
|
|
1390
1380
|
__proto__: null,
|
|
1391
1381
|
...options
|
|
1392
|
-
}
|
|
1382
|
+
}
|
|
1393
1383
|
const include = {
|
|
1394
1384
|
__proto__: null,
|
|
1385
|
+
blocked: true,
|
|
1395
1386
|
critical: true,
|
|
1396
1387
|
cve: true,
|
|
1397
1388
|
unfixable: true,
|
|
1398
|
-
|
|
1389
|
+
upgradable: false,
|
|
1399
1390
|
..._include
|
|
1400
|
-
}
|
|
1401
|
-
const name = packages.resolvePackageName(artifact)
|
|
1402
|
-
const {
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
const
|
|
1406
|
-
const
|
|
1407
|
-
|
|
1391
|
+
}
|
|
1392
|
+
const name = packages.resolvePackageName(artifact)
|
|
1393
|
+
const { version } = artifact
|
|
1394
|
+
const pkgId = `${name}@${version}`
|
|
1395
|
+
const major = semver.major(version)
|
|
1396
|
+
const socketYml = findSocketYmlSync()
|
|
1397
|
+
const enabledState = {
|
|
1398
|
+
__proto__: null,
|
|
1399
|
+
...socketYml?.parsed.issueRules
|
|
1400
|
+
}
|
|
1401
|
+
let sockPkgAlerts = []
|
|
1408
1402
|
for (const alert of artifact.alerts) {
|
|
1409
|
-
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
const
|
|
1420
|
-
const
|
|
1421
|
-
const
|
|
1422
|
-
const
|
|
1423
|
-
const
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1426
|
-
|
|
1403
|
+
const action = alert.action ?? ''
|
|
1404
|
+
const enabledFlag = enabledState[alert.type]
|
|
1405
|
+
if (
|
|
1406
|
+
(action === 'ignore' && enabledFlag !== true) ||
|
|
1407
|
+
enabledFlag === false
|
|
1408
|
+
) {
|
|
1409
|
+
continue
|
|
1410
|
+
}
|
|
1411
|
+
const blocked = action === 'error'
|
|
1412
|
+
const critical = alert.severity === ALERT_SEVERITY.critical
|
|
1413
|
+
const cve = isArtifactAlertCve(alert)
|
|
1414
|
+
const fixType = alert.fix?.type ?? ''
|
|
1415
|
+
const fixableCve = fixType === ALERT_FIX_TYPE.cve
|
|
1416
|
+
const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade
|
|
1417
|
+
const fixable = fixableCve || fixableUpgrade
|
|
1418
|
+
const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name)
|
|
1419
|
+
if (
|
|
1420
|
+
(include.blocked && blocked) ||
|
|
1421
|
+
(include.critical && critical) ||
|
|
1422
|
+
(include.cve && cve) ||
|
|
1423
|
+
(include.unfixable && !fixable) ||
|
|
1424
|
+
(include.upgradable && upgradable)
|
|
1425
|
+
) {
|
|
1427
1426
|
sockPkgAlerts.push({
|
|
1428
1427
|
name,
|
|
1429
1428
|
version,
|
|
1430
1429
|
key: alert.key,
|
|
1431
1430
|
type: alert.type,
|
|
1432
|
-
|
|
1431
|
+
blocked,
|
|
1433
1432
|
critical,
|
|
1434
|
-
display: ux.display,
|
|
1435
1433
|
fixable,
|
|
1436
1434
|
raw: alert,
|
|
1437
|
-
|
|
1438
|
-
})
|
|
1435
|
+
upgradable
|
|
1436
|
+
})
|
|
1439
1437
|
}
|
|
1440
1438
|
}
|
|
1441
1439
|
if (!sockPkgAlerts.length) {
|
|
1442
|
-
return alertsByPkgId
|
|
1440
|
+
return alertsByPkgId
|
|
1443
1441
|
}
|
|
1444
1442
|
if (consolidate) {
|
|
1445
|
-
const highestForCve = new Map()
|
|
1446
|
-
const highestForUpgrade = new Map()
|
|
1447
|
-
const unfixableAlerts = []
|
|
1443
|
+
const highestForCve = new Map()
|
|
1444
|
+
const highestForUpgrade = new Map()
|
|
1445
|
+
const unfixableAlerts = []
|
|
1448
1446
|
for (const sockPkgAlert of sockPkgAlerts) {
|
|
1449
|
-
const alert = sockPkgAlert.raw
|
|
1450
|
-
const fixType = alert.fix?.type ?? ''
|
|
1447
|
+
const alert = sockPkgAlert.raw
|
|
1448
|
+
const fixType = alert.fix?.type ?? ''
|
|
1451
1449
|
if (fixType === ALERT_FIX_TYPE.cve) {
|
|
1452
|
-
const patchedVersion =
|
|
1453
|
-
|
|
1454
|
-
const
|
|
1455
|
-
const
|
|
1450
|
+
const patchedVersion =
|
|
1451
|
+
alert.props[CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER]
|
|
1452
|
+
const patchedMajor = semver.major(patchedVersion)
|
|
1453
|
+
const oldHighest = highestForCve.get(patchedMajor)
|
|
1454
|
+
const highest = oldHighest?.version ?? '0.0.0'
|
|
1456
1455
|
if (semver.gt(patchedVersion, highest)) {
|
|
1457
1456
|
highestForCve.set(patchedMajor, {
|
|
1458
1457
|
alert: sockPkgAlert,
|
|
1459
1458
|
version: patchedVersion
|
|
1460
|
-
})
|
|
1459
|
+
})
|
|
1461
1460
|
}
|
|
1462
1461
|
} else if (fixType === ALERT_FIX_TYPE.upgrade) {
|
|
1463
|
-
const oldHighest = highestForUpgrade.get(major)
|
|
1464
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
1462
|
+
const oldHighest = highestForUpgrade.get(major)
|
|
1463
|
+
const highest = oldHighest?.version ?? '0.0.0'
|
|
1465
1464
|
if (semver.gt(version, highest)) {
|
|
1466
1465
|
highestForUpgrade.set(major, {
|
|
1467
1466
|
alert: sockPkgAlert,
|
|
1468
1467
|
version
|
|
1469
|
-
})
|
|
1468
|
+
})
|
|
1470
1469
|
}
|
|
1471
1470
|
} else {
|
|
1472
|
-
unfixableAlerts.push(sockPkgAlert)
|
|
1471
|
+
unfixableAlerts.push(sockPkgAlert)
|
|
1473
1472
|
}
|
|
1474
1473
|
}
|
|
1475
|
-
sockPkgAlerts = [
|
|
1474
|
+
sockPkgAlerts = [
|
|
1475
|
+
...unfixableAlerts,
|
|
1476
|
+
...[...highestForCve.values()].map(d => d.alert),
|
|
1477
|
+
...[...highestForUpgrade.values()].map(d => d.alert)
|
|
1478
|
+
]
|
|
1476
1479
|
}
|
|
1477
1480
|
if (sockPkgAlerts.length) {
|
|
1478
|
-
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
1479
|
-
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
1481
|
+
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
1482
|
+
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
1480
1483
|
}
|
|
1481
|
-
return alertsByPkgId
|
|
1484
|
+
return alertsByPkgId
|
|
1482
1485
|
}
|
|
1483
1486
|
function getCveInfoByAlertsMap(alertsMap, options) {
|
|
1484
1487
|
const exclude = {
|
|
1485
|
-
|
|
1488
|
+
upgradable: true,
|
|
1486
1489
|
...{
|
|
1487
1490
|
__proto__: null,
|
|
1488
1491
|
...options
|
|
1489
1492
|
}.exclude
|
|
1490
|
-
}
|
|
1491
|
-
let infoByPkg = null
|
|
1493
|
+
}
|
|
1494
|
+
let infoByPkg = null
|
|
1492
1495
|
for (const [pkgId, sockPkgAlerts] of alertsMap) {
|
|
1493
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1494
|
-
const name = packages.resolvePackageName(purlObj)
|
|
1496
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1497
|
+
const name = packages.resolvePackageName(purlObj)
|
|
1495
1498
|
for (const sockPkgAlert of sockPkgAlerts) {
|
|
1496
|
-
const alert = sockPkgAlert.raw
|
|
1497
|
-
if (
|
|
1498
|
-
|
|
1499
|
+
const alert = sockPkgAlert.raw
|
|
1500
|
+
if (
|
|
1501
|
+
alert.fix?.type !== ALERT_FIX_TYPE.cve ||
|
|
1502
|
+
(exclude.upgradable && registry.getManifestData(NPM$2, name))
|
|
1503
|
+
) {
|
|
1504
|
+
continue
|
|
1499
1505
|
}
|
|
1500
1506
|
if (!infoByPkg) {
|
|
1501
|
-
infoByPkg = new Map()
|
|
1507
|
+
infoByPkg = new Map()
|
|
1502
1508
|
}
|
|
1503
|
-
let infos = infoByPkg.get(name)
|
|
1509
|
+
let infos = infoByPkg.get(name)
|
|
1504
1510
|
if (!infos) {
|
|
1505
|
-
infos = []
|
|
1506
|
-
infoByPkg.set(name, infos)
|
|
1511
|
+
infos = []
|
|
1512
|
+
infoByPkg.set(name, infos)
|
|
1507
1513
|
}
|
|
1508
|
-
const {
|
|
1509
|
-
|
|
1510
|
-
vulnerableVersionRange
|
|
1511
|
-
} = alert.props;
|
|
1514
|
+
const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
|
|
1515
|
+
alert.props
|
|
1512
1516
|
infos.push({
|
|
1513
1517
|
firstPatchedVersionIdentifier,
|
|
1514
|
-
vulnerableVersionRange: new semver.Range(
|
|
1515
|
-
|
|
1518
|
+
vulnerableVersionRange: new semver.Range(
|
|
1519
|
+
vulnerableVersionRange
|
|
1520
|
+
).format()
|
|
1521
|
+
})
|
|
1516
1522
|
}
|
|
1517
1523
|
}
|
|
1518
|
-
return infoByPkg
|
|
1524
|
+
return infoByPkg
|
|
1519
1525
|
}
|
|
1520
1526
|
function logAlertsMap(alertsMap, options) {
|
|
1521
|
-
const {
|
|
1522
|
-
output = process.stderr
|
|
1523
|
-
} = {
|
|
1527
|
+
const { hideAt = 'middle', output = process.stderr } = {
|
|
1524
1528
|
__proto__: null,
|
|
1525
1529
|
...options
|
|
1526
|
-
}
|
|
1527
|
-
const translations = getTranslations()
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1530
|
+
}
|
|
1531
|
+
const translations = getTranslations()
|
|
1532
|
+
const sortedEntries = [...alertsMap.entries()].sort(
|
|
1533
|
+
(a, b) => getAlertsSeverityOrder(a[1]) - getAlertsSeverityOrder(b[1])
|
|
1534
|
+
)
|
|
1535
|
+
const aboveTheFoldPkgIds = new Set()
|
|
1536
|
+
const viewableAlertsByPkgId = new Map()
|
|
1537
|
+
const hiddenAlertsByPkgId = new Map()
|
|
1538
|
+
for (let i = 0, { length } = sortedEntries; i < length; i += 1) {
|
|
1539
|
+
const { 0: pkgId, 1: alerts } = sortedEntries[i]
|
|
1540
|
+
const hiddenAlerts = []
|
|
1541
|
+
const viewableAlerts = alerts.filter(a => {
|
|
1542
|
+
const keep =
|
|
1543
|
+
a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER[hideAt]
|
|
1544
|
+
if (!keep) {
|
|
1545
|
+
hiddenAlerts.push(a)
|
|
1546
|
+
}
|
|
1547
|
+
return keep
|
|
1548
|
+
})
|
|
1549
|
+
if (hiddenAlerts.length) {
|
|
1550
|
+
hiddenAlertsByPkgId.set(pkgId, hiddenAlerts.sort(alertSeverityComparator))
|
|
1551
|
+
}
|
|
1552
|
+
if (!viewableAlerts.length) {
|
|
1553
|
+
continue
|
|
1554
|
+
}
|
|
1555
|
+
viewableAlerts.sort(alertSeverityComparator)
|
|
1556
|
+
viewableAlertsByPkgId.set(pkgId, viewableAlerts)
|
|
1557
|
+
if (
|
|
1558
|
+
viewableAlerts.find(
|
|
1559
|
+
a => a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER.middle
|
|
1560
|
+
)
|
|
1561
|
+
) {
|
|
1562
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
// If MIN_ABOVE_THE_FOLD_COUNT is NOT met add more from viewable pkg ids.
|
|
1567
|
+
for (const { 0: pkgId } of viewableAlertsByPkgId.entries()) {
|
|
1568
|
+
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
1569
|
+
break
|
|
1570
|
+
}
|
|
1571
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1572
|
+
}
|
|
1573
|
+
// If MIN_ABOVE_THE_FOLD_COUNT is STILL NOT met add more from hidden pkg ids.
|
|
1574
|
+
for (const { 0: pkgId, 1: hiddenAlerts } of hiddenAlertsByPkgId.entries()) {
|
|
1575
|
+
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
1576
|
+
break
|
|
1577
|
+
}
|
|
1578
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1579
|
+
const viewableAlerts = viewableAlertsByPkgId.get(pkgId) ?? []
|
|
1580
|
+
if (viewableAlerts.length < MIN_ABOVE_THE_FOLD_ALERT_COUNT) {
|
|
1581
|
+
const neededCount = MIN_ABOVE_THE_FOLD_ALERT_COUNT - viewableAlerts.length
|
|
1582
|
+
let removedHiddenAlerts
|
|
1583
|
+
if (hiddenAlerts.length - neededCount > 0) {
|
|
1584
|
+
removedHiddenAlerts = hiddenAlerts.splice(
|
|
1585
|
+
0,
|
|
1586
|
+
MIN_ABOVE_THE_FOLD_ALERT_COUNT
|
|
1587
|
+
)
|
|
1588
|
+
} else {
|
|
1589
|
+
removedHiddenAlerts = hiddenAlerts
|
|
1590
|
+
hiddenAlertsByPkgId.delete(pkgId)
|
|
1591
|
+
}
|
|
1592
|
+
viewableAlertsByPkgId.set(pkgId, [
|
|
1593
|
+
...viewableAlerts,
|
|
1594
|
+
...removedHiddenAlerts
|
|
1595
|
+
])
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
const mentionedPkgIdsWithHiddenAlerts = new Set()
|
|
1599
|
+
for (
|
|
1600
|
+
let i = 0,
|
|
1601
|
+
prevAboveTheFold = true,
|
|
1602
|
+
entries = [...viewableAlertsByPkgId.entries()],
|
|
1603
|
+
{ length } = entries;
|
|
1604
|
+
i < length;
|
|
1605
|
+
i += 1
|
|
1606
|
+
) {
|
|
1607
|
+
const { 0: pkgId, 1: alerts } = entries[i]
|
|
1608
|
+
const lines = new Set()
|
|
1531
1609
|
for (const alert of alerts) {
|
|
1532
|
-
const {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1610
|
+
const { type } = alert
|
|
1611
|
+
const severity = alert.raw.severity ?? ''
|
|
1612
|
+
const attributes = [
|
|
1613
|
+
...(severity
|
|
1614
|
+
? [colors[ALERT_SEVERITY_COLOR[severity]](getSeverityLabel(severity))]
|
|
1615
|
+
: []),
|
|
1616
|
+
...(alert.blocked ? [colors.bold(colors.red('blocked'))] : []),
|
|
1617
|
+
...(alert.fixable ? ['fixable'] : [])
|
|
1618
|
+
]
|
|
1619
|
+
const maybeAttributes = attributes.length
|
|
1620
|
+
? ` ${colors.italic(`(${attributes.join('; ')})`)}`
|
|
1621
|
+
: ''
|
|
1537
1622
|
// Based data from { pageProps: { alertTypes } } of:
|
|
1538
1623
|
// https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
|
|
1539
|
-
const info = translations.alerts[type]
|
|
1540
|
-
const title = info?.title ?? type
|
|
1541
|
-
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
1624
|
+
const info = translations.alerts[type]
|
|
1625
|
+
const title = info?.title ?? type
|
|
1626
|
+
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
1627
|
+
const content = `${title}${maybeAttributes}${maybeDesc}`
|
|
1542
1628
|
// TODO: emoji seems to mis-align terminals sometimes
|
|
1543
|
-
lines.add(` ${
|
|
1629
|
+
lines.add(` ${content}`)
|
|
1630
|
+
}
|
|
1631
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1632
|
+
const hyperlink = format.hyperlink(
|
|
1633
|
+
pkgId,
|
|
1634
|
+
getSocketDevPackageOverviewUrl(
|
|
1635
|
+
NPM$2,
|
|
1636
|
+
packages.resolvePackageName(purlObj),
|
|
1637
|
+
purlObj.version
|
|
1638
|
+
)
|
|
1639
|
+
)
|
|
1640
|
+
const isAboveTheFold = aboveTheFoldPkgIds.has(pkgId)
|
|
1641
|
+
if (isAboveTheFold) {
|
|
1642
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1643
|
+
output.write(`${i ? '\n' : ''}${hyperlink}:\n`)
|
|
1644
|
+
} else {
|
|
1645
|
+
output.write(`${prevAboveTheFold ? '\n' : ''}${hyperlink}:\n`)
|
|
1544
1646
|
}
|
|
1545
|
-
output.write(`(socket) ${format.hyperlink(pkgId, getSocketDevPackageOverviewUrl(NPM$2, packages.resolvePackageName(purlObj), purlObj.version))} contains risks:\n`);
|
|
1546
1647
|
for (const line of lines) {
|
|
1547
|
-
output.write(`${line}\n`)
|
|
1648
|
+
output.write(`${line}\n`)
|
|
1649
|
+
}
|
|
1650
|
+
const hiddenAlerts = hiddenAlertsByPkgId.get(pkgId) ?? []
|
|
1651
|
+
const { length: hiddenAlertsCount } = hiddenAlerts
|
|
1652
|
+
if (hiddenAlertsCount) {
|
|
1653
|
+
mentionedPkgIdsWithHiddenAlerts.add(pkgId)
|
|
1654
|
+
if (hiddenAlertsCount === 1) {
|
|
1655
|
+
output.write(
|
|
1656
|
+
` ${colors.dim(`+1 Hidden ${getSeverityLabel(hiddenAlerts[0].raw.severity ?? 'low')} risk alert`)}\n`
|
|
1657
|
+
)
|
|
1658
|
+
} else {
|
|
1659
|
+
output.write(
|
|
1660
|
+
` ${colors.dim(`+${hiddenAlertsCount} Hidden alerts ${colors.italic(getHiddenRisksDescription(getHiddenRiskCounts(hiddenAlerts)))}`)}\n`
|
|
1661
|
+
)
|
|
1662
|
+
}
|
|
1548
1663
|
}
|
|
1664
|
+
prevAboveTheFold = isAboveTheFold
|
|
1549
1665
|
}
|
|
1666
|
+
const additionalHiddenCount =
|
|
1667
|
+
hiddenAlertsByPkgId.size - mentionedPkgIdsWithHiddenAlerts.size
|
|
1668
|
+
if (additionalHiddenCount) {
|
|
1669
|
+
const totalRiskCounts = {
|
|
1670
|
+
critical: 0,
|
|
1671
|
+
high: 0,
|
|
1672
|
+
middle: 0,
|
|
1673
|
+
low: 0
|
|
1674
|
+
}
|
|
1675
|
+
for (const { 0: pkgId, 1: alerts } of hiddenAlertsByPkgId.entries()) {
|
|
1676
|
+
if (mentionedPkgIdsWithHiddenAlerts.has(pkgId)) {
|
|
1677
|
+
continue
|
|
1678
|
+
}
|
|
1679
|
+
const riskCounts = getHiddenRiskCounts(alerts)
|
|
1680
|
+
totalRiskCounts.critical += riskCounts.critical
|
|
1681
|
+
totalRiskCounts.high += riskCounts.high
|
|
1682
|
+
totalRiskCounts.middle += riskCounts.middle
|
|
1683
|
+
totalRiskCounts.low += riskCounts.low
|
|
1684
|
+
}
|
|
1685
|
+
output.write(
|
|
1686
|
+
`${aboveTheFoldPkgIds.size ? '\n' : ''}${colors.dim(`${aboveTheFoldPkgIds.size ? '+' : ''}${additionalHiddenCount} Packages with hidden alerts ${colors.italic(getHiddenRisksDescription(totalRiskCounts))}`)}\n`
|
|
1687
|
+
)
|
|
1688
|
+
}
|
|
1689
|
+
output.write('\n')
|
|
1550
1690
|
}
|
|
1551
1691
|
|
|
1552
|
-
const {
|
|
1553
|
-
LOOP_SENTINEL,
|
|
1554
|
-
NPM: NPM$1,
|
|
1555
|
-
NPM_REGISTRY_URL
|
|
1556
|
-
} = constants;
|
|
1692
|
+
const { LOOP_SENTINEL, NPM: NPM$1, NPM_REGISTRY_URL } = constants
|
|
1557
1693
|
function getDetailsFromDiff(diff_, options) {
|
|
1558
|
-
const details = []
|
|
1694
|
+
const details = []
|
|
1559
1695
|
// `diff_` is `null` when `npm install --package-lock-only` is passed.
|
|
1560
1696
|
if (!diff_) {
|
|
1561
|
-
return details
|
|
1697
|
+
return details
|
|
1562
1698
|
}
|
|
1563
1699
|
const include = {
|
|
1564
1700
|
__proto__: null,
|
|
@@ -1568,252 +1704,285 @@ function getDetailsFromDiff(diff_, options) {
|
|
|
1568
1704
|
__proto__: null,
|
|
1569
1705
|
...options
|
|
1570
1706
|
}.include
|
|
1571
|
-
}
|
|
1572
|
-
const queue = [...diff_.children]
|
|
1573
|
-
let pos = 0
|
|
1574
|
-
let {
|
|
1575
|
-
length: queueLength
|
|
1576
|
-
} = queue;
|
|
1707
|
+
}
|
|
1708
|
+
const queue = [...diff_.children]
|
|
1709
|
+
let pos = 0
|
|
1710
|
+
let { length: queueLength } = queue
|
|
1577
1711
|
while (pos < queueLength) {
|
|
1578
1712
|
if (pos === LOOP_SENTINEL) {
|
|
1579
|
-
throw new Error('Detected infinite loop while walking Arborist diff')
|
|
1713
|
+
throw new Error('Detected infinite loop while walking Arborist diff')
|
|
1580
1714
|
}
|
|
1581
|
-
const diff = queue[pos++]
|
|
1582
|
-
const {
|
|
1583
|
-
action
|
|
1584
|
-
} = diff;
|
|
1715
|
+
const diff = queue[pos++]
|
|
1716
|
+
const { action } = diff
|
|
1585
1717
|
if (action) {
|
|
1586
1718
|
// The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
|
|
1587
1719
|
// action is 'REMOVE'
|
|
1588
1720
|
// The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
|
|
1589
1721
|
// action is 'ADD'.
|
|
1590
|
-
const {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
} = diff;
|
|
1594
|
-
let existing;
|
|
1595
|
-
let keep = false;
|
|
1722
|
+
const { actual: oldNode, ideal: pkgNode } = diff
|
|
1723
|
+
let existing
|
|
1724
|
+
let keep = false
|
|
1596
1725
|
if (action === DiffAction.change) {
|
|
1597
1726
|
if (pkgNode?.package.version !== oldNode?.package.version) {
|
|
1598
|
-
keep = true
|
|
1599
|
-
if (
|
|
1600
|
-
|
|
1727
|
+
keep = true
|
|
1728
|
+
if (
|
|
1729
|
+
oldNode?.package.name &&
|
|
1730
|
+
oldNode.package.name === pkgNode?.package.name
|
|
1731
|
+
) {
|
|
1732
|
+
existing = oldNode
|
|
1601
1733
|
}
|
|
1602
1734
|
} else {
|
|
1603
|
-
debug.debugLog('SKIPPING META CHANGE ON', diff)
|
|
1735
|
+
debug.debugLog('SKIPPING META CHANGE ON', diff)
|
|
1604
1736
|
}
|
|
1605
1737
|
} else {
|
|
1606
|
-
keep = action !== DiffAction.remove
|
|
1738
|
+
keep = action !== DiffAction.remove
|
|
1607
1739
|
}
|
|
1608
1740
|
if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
|
|
1609
|
-
if (
|
|
1741
|
+
if (
|
|
1742
|
+
include.unknownOrigin ||
|
|
1743
|
+
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1744
|
+
) {
|
|
1610
1745
|
details.push({
|
|
1611
1746
|
node: pkgNode,
|
|
1612
1747
|
existing
|
|
1613
|
-
})
|
|
1748
|
+
})
|
|
1614
1749
|
}
|
|
1615
1750
|
}
|
|
1616
1751
|
}
|
|
1617
1752
|
for (const child of diff.children) {
|
|
1618
|
-
queue[queueLength++] = child
|
|
1753
|
+
queue[queueLength++] = child
|
|
1619
1754
|
}
|
|
1620
1755
|
}
|
|
1621
1756
|
if (include.unchanged) {
|
|
1622
|
-
const {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
if (include.unknownOrigin || getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL) {
|
|
1757
|
+
const { unchanged } = diff_
|
|
1758
|
+
for (let i = 0, { length } = unchanged; i < length; i += 1) {
|
|
1759
|
+
const pkgNode = unchanged[i]
|
|
1760
|
+
if (
|
|
1761
|
+
include.unknownOrigin ||
|
|
1762
|
+
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1763
|
+
) {
|
|
1630
1764
|
details.push({
|
|
1631
1765
|
node: pkgNode,
|
|
1632
1766
|
existing: pkgNode
|
|
1633
|
-
})
|
|
1767
|
+
})
|
|
1634
1768
|
}
|
|
1635
1769
|
}
|
|
1636
1770
|
}
|
|
1637
|
-
return details
|
|
1771
|
+
return details
|
|
1638
1772
|
}
|
|
1639
1773
|
function getUrlOrigin(input) {
|
|
1640
1774
|
try {
|
|
1641
|
-
|
|
1775
|
+
// TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
|
|
1776
|
+
// https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base
|
|
1777
|
+
// return URL.parse(input)?.origin ?? ''
|
|
1778
|
+
return new URL(input).origin ?? ''
|
|
1642
1779
|
} catch {}
|
|
1643
|
-
return ''
|
|
1780
|
+
return ''
|
|
1644
1781
|
}
|
|
1645
|
-
function findBestPatchVersion(
|
|
1646
|
-
|
|
1647
|
-
|
|
1782
|
+
function findBestPatchVersion(
|
|
1783
|
+
node,
|
|
1784
|
+
availableVersions,
|
|
1785
|
+
vulnerableVersionRange,
|
|
1786
|
+
_firstPatchedVersionIdentifier
|
|
1787
|
+
) {
|
|
1788
|
+
const manifestData = registry.getManifestData(NPM$1, node.name)
|
|
1789
|
+
let eligibleVersions
|
|
1648
1790
|
if (manifestData && manifestData.name === manifestData.package) {
|
|
1649
|
-
const major = semver.major(manifestData.version)
|
|
1650
|
-
eligibleVersions = availableVersions.filter(v => semver.major(v) === major)
|
|
1791
|
+
const major = semver.major(manifestData.version)
|
|
1792
|
+
eligibleVersions = availableVersions.filter(v => semver.major(v) === major)
|
|
1651
1793
|
} else {
|
|
1652
|
-
const major = semver.major(node.version)
|
|
1653
|
-
eligibleVersions = availableVersions.filter(
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1794
|
+
const major = semver.major(node.version)
|
|
1795
|
+
eligibleVersions = availableVersions.filter(
|
|
1796
|
+
v =>
|
|
1797
|
+
// Filter for versions that are within the current major version and
|
|
1798
|
+
// are NOT in the vulnerable range.
|
|
1799
|
+
semver.major(v) === major &&
|
|
1800
|
+
(!vulnerableVersionRange ||
|
|
1801
|
+
!semver.satisfies(v, vulnerableVersionRange))
|
|
1802
|
+
)
|
|
1803
|
+
}
|
|
1804
|
+
return semver.maxSatisfying(eligibleVersions, '*')
|
|
1659
1805
|
}
|
|
1660
1806
|
function findPackageNodes(tree, packageName) {
|
|
1661
|
-
const queue = [
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1807
|
+
const queue = [
|
|
1808
|
+
{
|
|
1809
|
+
node: tree
|
|
1810
|
+
}
|
|
1811
|
+
]
|
|
1812
|
+
const matches = []
|
|
1813
|
+
let sentinel = 0
|
|
1666
1814
|
while (queue.length) {
|
|
1667
1815
|
if (sentinel++ === LOOP_SENTINEL) {
|
|
1668
|
-
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1816
|
+
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1669
1817
|
}
|
|
1670
|
-
const {
|
|
1671
|
-
|
|
1672
|
-
} = queue.pop();
|
|
1673
|
-
const node = currentNode.children.get(packageName);
|
|
1818
|
+
const { node: currentNode } = queue.pop()
|
|
1819
|
+
const node = currentNode.children.get(packageName)
|
|
1674
1820
|
if (node) {
|
|
1675
|
-
matches.push(node)
|
|
1821
|
+
matches.push(node)
|
|
1676
1822
|
}
|
|
1677
|
-
const children = [...currentNode.children.values()]
|
|
1823
|
+
const children = [...currentNode.children.values()]
|
|
1678
1824
|
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
1679
1825
|
queue.push({
|
|
1680
1826
|
node: children[i]
|
|
1681
|
-
})
|
|
1827
|
+
})
|
|
1682
1828
|
}
|
|
1683
1829
|
}
|
|
1684
|
-
return matches
|
|
1830
|
+
return matches
|
|
1685
1831
|
}
|
|
1686
1832
|
async function getAlertsMapFromArborist(arb, options) {
|
|
1687
|
-
const {
|
|
1688
|
-
include: _include,
|
|
1689
|
-
spinner
|
|
1690
|
-
} = {
|
|
1833
|
+
const { include: _include, spinner } = {
|
|
1691
1834
|
__proto__: null,
|
|
1692
1835
|
...options
|
|
1693
|
-
}
|
|
1836
|
+
}
|
|
1694
1837
|
const include = {
|
|
1695
1838
|
__proto__: null,
|
|
1839
|
+
blocked: true,
|
|
1840
|
+
critical: true,
|
|
1841
|
+
cve: true,
|
|
1696
1842
|
existing: false,
|
|
1697
1843
|
unfixable: true,
|
|
1844
|
+
upgradable: false,
|
|
1698
1845
|
..._include
|
|
1699
|
-
}
|
|
1846
|
+
}
|
|
1700
1847
|
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
1701
1848
|
include: {
|
|
1702
1849
|
unchanged: include.existing
|
|
1703
1850
|
}
|
|
1704
|
-
})
|
|
1705
|
-
const pkgIds = arrays.arrayUnique(needInfoOn.map(d => d.node.pkgid))
|
|
1706
|
-
let {
|
|
1707
|
-
|
|
1708
|
-
} = pkgIds;
|
|
1709
|
-
const alertsByPkgId = new Map();
|
|
1851
|
+
})
|
|
1852
|
+
const pkgIds = arrays.arrayUnique(needInfoOn.map(d => d.node.pkgid))
|
|
1853
|
+
let { length: remaining } = pkgIds
|
|
1854
|
+
const alertsByPkgId = new Map()
|
|
1710
1855
|
if (!remaining) {
|
|
1711
|
-
return alertsByPkgId
|
|
1712
|
-
}
|
|
1713
|
-
const getText = () => `Looking up data for ${remaining} packages
|
|
1714
|
-
spinner?.start(getText())
|
|
1715
|
-
let overrides
|
|
1716
|
-
const overridesMap = (
|
|
1856
|
+
return alertsByPkgId
|
|
1857
|
+
}
|
|
1858
|
+
const getText = () => `Looking up data for ${remaining} packages`
|
|
1859
|
+
spinner?.start(getText())
|
|
1860
|
+
let overrides
|
|
1861
|
+
const overridesMap = (
|
|
1862
|
+
arb.actualTree ??
|
|
1863
|
+
arb.idealTree ??
|
|
1864
|
+
(await arb.loadActual())
|
|
1865
|
+
)?.overrides?.children
|
|
1717
1866
|
if (overridesMap) {
|
|
1718
|
-
overrides = Object.fromEntries(
|
|
1719
|
-
|
|
1720
|
-
|
|
1867
|
+
overrides = Object.fromEntries(
|
|
1868
|
+
[...overridesMap.entries()].map(([key, overrideSet]) => {
|
|
1869
|
+
return [key, overrideSet.value]
|
|
1870
|
+
})
|
|
1871
|
+
)
|
|
1721
1872
|
}
|
|
1722
|
-
const
|
|
1873
|
+
const sockSdk = await setupSdk(getPublicToken())
|
|
1723
1874
|
const toAlertsMapOptions = {
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1875
|
+
...options,
|
|
1876
|
+
include,
|
|
1877
|
+
overrides
|
|
1878
|
+
}
|
|
1879
|
+
for await (const batchPackageFetchResult of sockSdk.batchPackageStream(
|
|
1880
|
+
{
|
|
1881
|
+
alerts: 'true',
|
|
1882
|
+
compact: 'true',
|
|
1883
|
+
fixable: include.unfixable ? 'false' : 'true'
|
|
1884
|
+
},
|
|
1885
|
+
{
|
|
1886
|
+
components: pkgIds.map(id => ({
|
|
1887
|
+
purl: `pkg:npm/${id}`
|
|
1888
|
+
}))
|
|
1889
|
+
}
|
|
1890
|
+
)) {
|
|
1736
1891
|
if (batchPackageFetchResult.success) {
|
|
1737
|
-
await addArtifactToAlertsMap(
|
|
1892
|
+
await addArtifactToAlertsMap(
|
|
1893
|
+
batchPackageFetchResult.data,
|
|
1894
|
+
alertsByPkgId,
|
|
1895
|
+
toAlertsMapOptions
|
|
1896
|
+
)
|
|
1738
1897
|
}
|
|
1739
|
-
remaining -= 1
|
|
1898
|
+
remaining -= 1
|
|
1740
1899
|
if (spinner && remaining > 0) {
|
|
1741
|
-
spinner.start()
|
|
1742
|
-
spinner.setText(getText())
|
|
1900
|
+
spinner.start()
|
|
1901
|
+
spinner.setText(getText())
|
|
1743
1902
|
}
|
|
1744
1903
|
}
|
|
1745
|
-
spinner?.stop()
|
|
1746
|
-
return alertsByPkgId
|
|
1904
|
+
spinner?.stop()
|
|
1905
|
+
return alertsByPkgId
|
|
1747
1906
|
}
|
|
1748
|
-
function updateNode(
|
|
1749
|
-
|
|
1907
|
+
function updateNode(
|
|
1908
|
+
node,
|
|
1909
|
+
packument,
|
|
1910
|
+
vulnerableVersionRange,
|
|
1911
|
+
firstPatchedVersionIdentifier
|
|
1912
|
+
) {
|
|
1913
|
+
const availableVersions = Object.keys(packument.versions)
|
|
1750
1914
|
// Find the highest non-vulnerable version within the same major range
|
|
1751
|
-
const targetVersion = findBestPatchVersion(
|
|
1752
|
-
|
|
1915
|
+
const targetVersion = findBestPatchVersion(
|
|
1916
|
+
node,
|
|
1917
|
+
availableVersions,
|
|
1918
|
+
vulnerableVersionRange
|
|
1919
|
+
)
|
|
1920
|
+
const targetPackument = targetVersion
|
|
1921
|
+
? packument.versions[targetVersion]
|
|
1922
|
+
: undefined
|
|
1753
1923
|
// Check !targetVersion to make TypeScript happy.
|
|
1754
1924
|
if (!targetVersion || !targetPackument) {
|
|
1755
1925
|
// No suitable patch version found.
|
|
1756
|
-
return false
|
|
1926
|
+
return false
|
|
1757
1927
|
}
|
|
1758
1928
|
// Use Object.defineProperty to override the version.
|
|
1759
1929
|
Object.defineProperty(node, 'version', {
|
|
1760
1930
|
configurable: true,
|
|
1761
1931
|
enumerable: true,
|
|
1762
1932
|
get: () => targetVersion
|
|
1763
|
-
})
|
|
1764
|
-
node.package.version = targetVersion
|
|
1933
|
+
})
|
|
1934
|
+
node.package.version = targetVersion
|
|
1765
1935
|
// Update resolved and clear integrity for the new version.
|
|
1766
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
|
|
1767
|
-
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${targetVersion}.tgz
|
|
1768
|
-
const {
|
|
1769
|
-
integrity
|
|
1770
|
-
} = targetPackument.dist;
|
|
1936
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
|
|
1937
|
+
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${targetVersion}.tgz`
|
|
1938
|
+
const { integrity } = targetPackument.dist
|
|
1771
1939
|
if (integrity) {
|
|
1772
|
-
node.integrity = integrity
|
|
1940
|
+
node.integrity = integrity
|
|
1773
1941
|
} else {
|
|
1774
|
-
delete node.integrity
|
|
1942
|
+
delete node.integrity
|
|
1775
1943
|
}
|
|
1776
1944
|
if ('deprecated' in targetPackument) {
|
|
1777
|
-
node.package['deprecated'] = targetPackument.deprecated
|
|
1945
|
+
node.package['deprecated'] = targetPackument.deprecated
|
|
1778
1946
|
} else {
|
|
1779
|
-
delete node.package['deprecated']
|
|
1947
|
+
delete node.package['deprecated']
|
|
1780
1948
|
}
|
|
1781
1949
|
const newDeps = {
|
|
1782
1950
|
...targetPackument.dependencies
|
|
1783
|
-
}
|
|
1784
|
-
const {
|
|
1785
|
-
|
|
1786
|
-
} = node.package;
|
|
1787
|
-
node.package.dependencies = newDeps;
|
|
1951
|
+
}
|
|
1952
|
+
const { dependencies: oldDeps } = node.package
|
|
1953
|
+
node.package.dependencies = newDeps
|
|
1788
1954
|
if (oldDeps) {
|
|
1789
1955
|
for (const oldDepName of Object.keys(oldDeps)) {
|
|
1790
1956
|
if (!objects.hasOwn(newDeps, oldDepName)) {
|
|
1791
|
-
node.edgesOut.get(oldDepName)?.detach()
|
|
1957
|
+
node.edgesOut.get(oldDepName)?.detach()
|
|
1792
1958
|
}
|
|
1793
1959
|
}
|
|
1794
1960
|
}
|
|
1795
1961
|
for (const newDepName of Object.keys(newDeps)) {
|
|
1796
1962
|
if (!objects.hasOwn(oldDeps, newDepName)) {
|
|
1797
|
-
node.addEdgeOut(
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1963
|
+
node.addEdgeOut(
|
|
1964
|
+
new Edge({
|
|
1965
|
+
from: node,
|
|
1966
|
+
name: newDepName,
|
|
1967
|
+
spec: newDeps[newDepName],
|
|
1968
|
+
type: 'prod'
|
|
1969
|
+
})
|
|
1970
|
+
)
|
|
1803
1971
|
}
|
|
1804
1972
|
}
|
|
1805
|
-
return true
|
|
1973
|
+
return true
|
|
1806
1974
|
}
|
|
1807
1975
|
|
|
1808
1976
|
const {
|
|
1809
1977
|
NPM,
|
|
1810
1978
|
NPX,
|
|
1811
|
-
|
|
1979
|
+
SOCKET_CLI_ACCEPT_RISKS,
|
|
1980
|
+
SOCKET_CLI_SAFE_BIN,
|
|
1981
|
+
SOCKET_CLI_SAFE_PROGRESS,
|
|
1982
|
+
SOCKET_CLI_VIEW_ALL_RISKS,
|
|
1812
1983
|
kInternalsSymbol,
|
|
1813
|
-
[kInternalsSymbol]: {
|
|
1814
|
-
|
|
1815
|
-
}
|
|
1816
|
-
} = constants;
|
|
1984
|
+
[kInternalsSymbol]: { getIpc }
|
|
1985
|
+
} = constants
|
|
1817
1986
|
const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
1818
1987
|
__proto__: null,
|
|
1819
1988
|
audit: false,
|
|
@@ -1824,34 +1993,44 @@ const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
|
1824
1993
|
save: false,
|
|
1825
1994
|
saveBundle: false,
|
|
1826
1995
|
silent: true
|
|
1827
|
-
}
|
|
1828
|
-
const kCtorArgs = Symbol('ctorArgs')
|
|
1829
|
-
const kRiskyReify = Symbol('riskyReify')
|
|
1830
|
-
const Arborist = require(shadowNpmPaths.getArboristClassPath())
|
|
1996
|
+
}
|
|
1997
|
+
const kCtorArgs = Symbol('ctorArgs')
|
|
1998
|
+
const kRiskyReify = Symbol('riskyReify')
|
|
1999
|
+
const Arborist = require(shadowNpmPaths.getArboristClassPath())
|
|
1831
2000
|
|
|
1832
2001
|
// Implementation code not related to our custom behavior is based on
|
|
1833
2002
|
// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
|
|
1834
2003
|
class SafeArborist extends Arborist {
|
|
1835
2004
|
constructor(...ctorArgs) {
|
|
1836
|
-
super(
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
2005
|
+
super(
|
|
2006
|
+
{
|
|
2007
|
+
path:
|
|
2008
|
+
(ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process$1.cwd(),
|
|
2009
|
+
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2010
|
+
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2011
|
+
},
|
|
2012
|
+
...ctorArgs.slice(1)
|
|
2013
|
+
)
|
|
2014
|
+
this[kCtorArgs] = ctorArgs
|
|
1842
2015
|
}
|
|
1843
2016
|
async [kRiskyReify](...args) {
|
|
1844
|
-
const ctorArgs = this[kCtorArgs]
|
|
1845
|
-
const arb = new Arborist(
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
...(
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
2017
|
+
const ctorArgs = this[kCtorArgs]
|
|
2018
|
+
const arb = new Arborist(
|
|
2019
|
+
{
|
|
2020
|
+
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2021
|
+
progress: false
|
|
2022
|
+
},
|
|
2023
|
+
...ctorArgs.slice(1)
|
|
2024
|
+
)
|
|
2025
|
+
const ret = await arb.reify(
|
|
2026
|
+
{
|
|
2027
|
+
...(args.length ? args[0] : undefined),
|
|
2028
|
+
progress: false
|
|
2029
|
+
},
|
|
2030
|
+
...args.slice(1)
|
|
2031
|
+
)
|
|
2032
|
+
Object.assign(this, arb)
|
|
2033
|
+
return ret
|
|
1855
2034
|
}
|
|
1856
2035
|
|
|
1857
2036
|
// @ts-ignore Incorrectly typed.
|
|
@@ -1859,95 +2038,119 @@ class SafeArborist extends Arborist {
|
|
|
1859
2038
|
const options = {
|
|
1860
2039
|
__proto__: null,
|
|
1861
2040
|
...(args.length ? args[0] : undefined)
|
|
1862
|
-
};
|
|
1863
|
-
const safeWrapperName = options.dryRun ? undefined : await getIpc(SOCKET_CLI_SAFE_WRAPPER);
|
|
1864
|
-
const isSafeNpm = safeWrapperName === NPM;
|
|
1865
|
-
const isSafeNpx = safeWrapperName === NPX;
|
|
1866
|
-
if (!safeWrapperName || isSafeNpx && options['yes']) {
|
|
1867
|
-
return await this[kRiskyReify](...args);
|
|
1868
2041
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
}
|
|
1874
|
-
await super.reify(
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2042
|
+
const ipc = await getIpc()
|
|
2043
|
+
const binName = ipc[SOCKET_CLI_SAFE_BIN]
|
|
2044
|
+
if (!binName) {
|
|
2045
|
+
return await this[kRiskyReify](...args)
|
|
2046
|
+
}
|
|
2047
|
+
await super.reify(
|
|
2048
|
+
{
|
|
2049
|
+
...options,
|
|
2050
|
+
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
|
|
2051
|
+
progress: false
|
|
2052
|
+
},
|
|
2053
|
+
// @ts-ignore: TS gets grumpy about rest parameters.
|
|
2054
|
+
...args.slice(1)
|
|
2055
|
+
)
|
|
2056
|
+
const progress = ipc[SOCKET_CLI_SAFE_PROGRESS]
|
|
2057
|
+
const spinner =
|
|
2058
|
+
options['silent'] || !progress
|
|
2059
|
+
? undefined
|
|
2060
|
+
: // Lazily access constants.spinner.
|
|
2061
|
+
constants.spinner
|
|
2062
|
+
const isSafeNpm = binName === NPM
|
|
2063
|
+
const isSafeNpx = binName === NPX
|
|
1881
2064
|
const alertsMap = await getAlertsMapFromArborist(this, {
|
|
1882
2065
|
spinner,
|
|
1883
|
-
include:
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
2066
|
+
include:
|
|
2067
|
+
options.dryRun ||
|
|
2068
|
+
options['yes'] ||
|
|
2069
|
+
// Lazily access constants.ENV[SOCKET_CLI_ACCEPT_RISKS].
|
|
2070
|
+
constants.ENV[SOCKET_CLI_ACCEPT_RISKS]
|
|
2071
|
+
? {
|
|
2072
|
+
blocked: true,
|
|
2073
|
+
critical: false,
|
|
2074
|
+
cve: false,
|
|
2075
|
+
unfixable: false
|
|
2076
|
+
}
|
|
2077
|
+
: {
|
|
2078
|
+
existing: isSafeNpx,
|
|
2079
|
+
unfixable: isSafeNpm
|
|
2080
|
+
}
|
|
2081
|
+
})
|
|
1888
2082
|
if (alertsMap.size) {
|
|
2083
|
+
process$1.exitCode = 1
|
|
1889
2084
|
logAlertsMap(alertsMap, {
|
|
2085
|
+
// Lazily access constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS].
|
|
2086
|
+
hideAt: constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS] ? 'none' : 'middle',
|
|
1890
2087
|
output: process$1.stderr
|
|
1891
|
-
})
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2088
|
+
})
|
|
2089
|
+
throw new Error(commonTags.stripIndents`
|
|
2090
|
+
Socket ${binName} exiting due to risks.
|
|
2091
|
+
View all risks - Rerun with environment variable ${SOCKET_CLI_VIEW_ALL_RISKS}=1.
|
|
2092
|
+
Accept risks - Rerun with environment variable ${SOCKET_CLI_ACCEPT_RISKS}=1.
|
|
2093
|
+
`)
|
|
2094
|
+
} else if (!options['silent']) {
|
|
2095
|
+
logger.logger.success(`Socket ${binName} found no risks!`)
|
|
2096
|
+
if (binName === NPX) {
|
|
2097
|
+
logger.logger.log(`Running ${options.add[0]}`)
|
|
1897
2098
|
}
|
|
1898
|
-
} else {
|
|
1899
|
-
logger.logger.success('Socket npm found no risks!');
|
|
1900
2099
|
}
|
|
1901
|
-
return await this[kRiskyReify](...args)
|
|
2100
|
+
return await this[kRiskyReify](...args)
|
|
1902
2101
|
}
|
|
1903
2102
|
}
|
|
1904
2103
|
|
|
1905
2104
|
function installSafeArborist() {
|
|
1906
2105
|
// Override '@npmcli/arborist' module exports with patched variants based on
|
|
1907
2106
|
// https://github.com/npm/cli/pull/8089.
|
|
1908
|
-
const cache = require.cache
|
|
2107
|
+
const cache = require.cache
|
|
1909
2108
|
cache[shadowNpmPaths.getArboristClassPath()] = {
|
|
1910
2109
|
exports: SafeArborist
|
|
1911
|
-
}
|
|
2110
|
+
}
|
|
1912
2111
|
cache[shadowNpmPaths.getArboristEdgeClassPath()] = {
|
|
1913
2112
|
exports: SafeEdge
|
|
1914
|
-
}
|
|
2113
|
+
}
|
|
1915
2114
|
cache[shadowNpmPaths.getArboristNodeClassPath()] = {
|
|
1916
2115
|
exports: SafeNode
|
|
1917
|
-
}
|
|
2116
|
+
}
|
|
1918
2117
|
cache[shadowNpmPaths.getArboristOverrideSetClassPath()] = {
|
|
1919
2118
|
exports: SafeOverrideSet
|
|
1920
|
-
}
|
|
2119
|
+
}
|
|
1921
2120
|
}
|
|
1922
2121
|
|
|
1923
|
-
installSafeArborist()
|
|
2122
|
+
installSafeArborist()
|
|
1924
2123
|
|
|
1925
|
-
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
1926
|
-
exports.Arborist = Arborist
|
|
1927
|
-
exports.AuthError = AuthError
|
|
1928
|
-
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
1929
|
-
exports.InputError = InputError
|
|
1930
|
-
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
1931
|
-
|
|
1932
|
-
exports.
|
|
1933
|
-
exports.
|
|
1934
|
-
exports.
|
|
1935
|
-
exports.
|
|
1936
|
-
exports.
|
|
1937
|
-
exports.
|
|
1938
|
-
exports.
|
|
1939
|
-
exports.
|
|
1940
|
-
exports.
|
|
1941
|
-
exports.
|
|
1942
|
-
exports.
|
|
1943
|
-
exports.
|
|
1944
|
-
exports.
|
|
1945
|
-
exports.
|
|
1946
|
-
exports.
|
|
1947
|
-
exports.
|
|
1948
|
-
exports.
|
|
1949
|
-
exports.
|
|
1950
|
-
exports.
|
|
1951
|
-
exports.
|
|
1952
|
-
|
|
2124
|
+
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
2125
|
+
exports.Arborist = Arborist
|
|
2126
|
+
exports.AuthError = AuthError
|
|
2127
|
+
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
2128
|
+
exports.InputError = InputError
|
|
2129
|
+
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
2130
|
+
SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2131
|
+
exports.SafeArborist = SafeArborist
|
|
2132
|
+
exports.addArtifactToAlertsMap = addArtifactToAlertsMap
|
|
2133
|
+
exports.captureException = captureException
|
|
2134
|
+
exports.findBestPatchVersion = findBestPatchVersion
|
|
2135
|
+
exports.findPackageNodes = findPackageNodes
|
|
2136
|
+
exports.findUp = findUp
|
|
2137
|
+
exports.formatSeverityCount = formatSeverityCount
|
|
2138
|
+
exports.getAlertsMapFromArborist = getAlertsMapFromArborist
|
|
2139
|
+
exports.getConfigValue = getConfigValue
|
|
2140
|
+
exports.getCveInfoByAlertsMap = getCveInfoByAlertsMap
|
|
2141
|
+
exports.getDefaultToken = getDefaultToken
|
|
2142
|
+
exports.getPublicToken = getPublicToken
|
|
2143
|
+
exports.getSeverityCount = getSeverityCount
|
|
2144
|
+
exports.getSocketDevAlertUrl = getSocketDevAlertUrl
|
|
2145
|
+
exports.getSocketDevPackageOverviewUrl = getSocketDevPackageOverviewUrl
|
|
2146
|
+
exports.overrideCachedConfig = overrideCachedConfig
|
|
2147
|
+
exports.readFileBinary = readFileBinary
|
|
2148
|
+
exports.readFileUtf8 = readFileUtf8
|
|
2149
|
+
exports.safeReadFile = safeReadFile
|
|
2150
|
+
exports.sensitiveConfigKeys = sensitiveConfigKeys
|
|
2151
|
+
exports.setupSdk = setupSdk
|
|
2152
|
+
exports.supportedConfigKeys = supportedConfigKeys
|
|
2153
|
+
exports.updateConfigValue = updateConfigValue
|
|
2154
|
+
exports.updateNode = updateNode
|
|
2155
|
+
//# debugId=c4cc0383-a1f3-4096-bddd-173589820ed1
|
|
1953
2156
|
//# sourceMappingURL=shadow-npm-inject.js.map
|