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