@socketsecurity/cli 0.14.68 → 0.14.70
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/module-sync/cli.js +687 -707
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/config.d.ts +13 -1
- package/dist/module-sync/shadow-npm-inject.js +70 -18
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.js +25 -10
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/module-sync/vendor.js +3883 -9
- package/dist/module-sync/vendor.js.map +1 -1
- package/dist/require/cli.js +686 -707
- package/dist/require/cli.js.map +1 -1
- package/package.json +6 -4
package/dist/require/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ const logger = require('@socketsecurity/registry/lib/logger')
|
|
|
19
19
|
const assert = require('node:assert')
|
|
20
20
|
const fs = require('node:fs/promises')
|
|
21
21
|
const commonTags = _socketInterop(require('common-tags'))
|
|
22
|
+
const debug = require('@socketsecurity/registry/lib/debug')
|
|
22
23
|
const strings = require('@socketsecurity/registry/lib/strings')
|
|
23
24
|
const shadowNpmInject = require('./shadow-npm-inject.js')
|
|
24
25
|
const constants = require('./constants.js')
|
|
@@ -27,22 +28,21 @@ const path$1 = require('node:path')
|
|
|
27
28
|
const objects = require('@socketsecurity/registry/lib/objects')
|
|
28
29
|
const path = require('@socketsecurity/registry/lib/path')
|
|
29
30
|
const regexps = require('@socketsecurity/registry/lib/regexps')
|
|
30
|
-
const prompts = require('@socketsecurity/registry/lib/prompts')
|
|
31
31
|
const yargsParse = _socketInterop(require('yargs-parser'))
|
|
32
32
|
const words = require('@socketsecurity/registry/lib/words')
|
|
33
33
|
const fs$1 = require('node:fs')
|
|
34
34
|
const shadowBin = require('./shadow-bin.js')
|
|
35
|
+
const prompts = require('@socketsecurity/registry/lib/prompts')
|
|
35
36
|
const chalkTable = _socketInterop(require('chalk-table'))
|
|
36
37
|
const require$$0$1 = require('node:util')
|
|
37
38
|
const registry = require('@socketsecurity/registry')
|
|
38
39
|
const npm = require('@socketsecurity/registry/lib/npm')
|
|
39
40
|
const packages = require('@socketsecurity/registry/lib/packages')
|
|
40
41
|
const lockfile_fs = _socketInterop(require('@pnpm/lockfile.fs'))
|
|
42
|
+
const spawn = require('@socketsecurity/registry/lib/spawn')
|
|
41
43
|
const lockfile_detectDepTypes = _socketInterop(
|
|
42
44
|
require('@pnpm/lockfile.detect-dep-types')
|
|
43
45
|
)
|
|
44
|
-
const debug = require('@socketsecurity/registry/lib/debug')
|
|
45
|
-
const spawn = require('@socketsecurity/registry/lib/spawn')
|
|
46
46
|
const shadowNpmPaths = require('./shadow-npm-paths.js')
|
|
47
47
|
const browserslist = _socketInterop(require('browserslist'))
|
|
48
48
|
const semver = _socketInterop(require('semver'))
|
|
@@ -56,8 +56,6 @@ const npa = _socketInterop(require('npm-package-arg'))
|
|
|
56
56
|
const tinyglobby = _socketInterop(require('tinyglobby'))
|
|
57
57
|
const promises = require('@socketsecurity/registry/lib/promises')
|
|
58
58
|
const yaml = _socketInterop(require('yaml'))
|
|
59
|
-
const betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'))
|
|
60
|
-
const config$K = require('@socketsecurity/config')
|
|
61
59
|
|
|
62
60
|
function failMsgWithBadge(badge, msg) {
|
|
63
61
|
return `${colors.bgRed(colors.bold(colors.white(` ${badge}: `)))} ${colors.bold(msg)}`
|
|
@@ -72,7 +70,7 @@ function handleUnsuccessfulApiResponse(_name, sockSdkError) {
|
|
|
72
70
|
spinner.stop()
|
|
73
71
|
throw new shadowNpmInject.AuthError(message)
|
|
74
72
|
}
|
|
75
|
-
logger.logger.fail(failMsgWithBadge('API returned an error
|
|
73
|
+
logger.logger.fail(failMsgWithBadge('Socket API returned an error', message))
|
|
76
74
|
|
|
77
75
|
process$1.exit(1)
|
|
78
76
|
}
|
|
@@ -80,23 +78,25 @@ async function handleApiCall(value, description) {
|
|
|
80
78
|
let result
|
|
81
79
|
try {
|
|
82
80
|
result = await value
|
|
83
|
-
} catch (
|
|
81
|
+
} catch (e) {
|
|
82
|
+
debug.debugLog(`handleApiCall[${description}] error:\n`, e)
|
|
84
83
|
throw new Error(`Failed ${description}`, {
|
|
85
|
-
cause
|
|
84
|
+
cause: e
|
|
86
85
|
})
|
|
87
86
|
}
|
|
88
87
|
return result
|
|
89
88
|
}
|
|
90
89
|
async function handleApiError(code) {
|
|
91
90
|
if (code === 400) {
|
|
92
|
-
return 'One of the options passed might be incorrect
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
return 'One of the options passed might be incorrect'
|
|
92
|
+
}
|
|
93
|
+
if (code === 403) {
|
|
94
|
+
return 'Your API token may not have the required permissions for this command or you might be trying to access (data from) an organization that is not linked to the API key you are logged in with'
|
|
95
|
+
}
|
|
96
|
+
if (code === 404) {
|
|
96
97
|
return 'The requested Socket API endpoint was not found (404) or there was no result for the requested parameters. This could be a temporary problem caused by an incident or a bug in the CLI. If the problem persists please let us know.'
|
|
97
|
-
} else {
|
|
98
|
-
return `Server responded with status code ${code}`
|
|
99
98
|
}
|
|
99
|
+
return `Server responded with status code ${code}`
|
|
100
100
|
}
|
|
101
101
|
function getLastFiveOfApiToken(token) {
|
|
102
102
|
// Get the last 5 characters of the API token before the trailing "_api".
|
|
@@ -141,14 +141,13 @@ async function fetchOrgAnalyticsData(time, spinner) {
|
|
|
141
141
|
)
|
|
142
142
|
if (result.success === false) {
|
|
143
143
|
handleUnsuccessfulApiResponse('getOrgAnalytics', result)
|
|
144
|
-
return undefined
|
|
145
144
|
}
|
|
146
145
|
spinner.stop()
|
|
147
146
|
if (!result.data.length) {
|
|
148
147
|
logger.logger.log(
|
|
149
148
|
'No analytics data is available for this organization yet.'
|
|
150
149
|
)
|
|
151
|
-
return
|
|
150
|
+
return
|
|
152
151
|
}
|
|
153
152
|
return result.data
|
|
154
153
|
}
|
|
@@ -161,14 +160,13 @@ async function fetchRepoAnalyticsData(repo, time, spinner) {
|
|
|
161
160
|
)
|
|
162
161
|
if (result.success === false) {
|
|
163
162
|
handleUnsuccessfulApiResponse('getRepoAnalytics', result)
|
|
164
|
-
return undefined
|
|
165
163
|
}
|
|
166
164
|
spinner.stop()
|
|
167
165
|
if (!result.data.length) {
|
|
168
166
|
logger.logger.log(
|
|
169
167
|
'No analytics data is available for this organization yet.'
|
|
170
168
|
)
|
|
171
|
-
return
|
|
169
|
+
return
|
|
172
170
|
}
|
|
173
171
|
return result.data
|
|
174
172
|
}
|
|
@@ -730,7 +728,7 @@ function getHelpListOutput(
|
|
|
730
728
|
return result.trim() || '(none)'
|
|
731
729
|
}
|
|
732
730
|
|
|
733
|
-
const { DRY_RUN_LABEL:
|
|
731
|
+
const { DRY_RUN_LABEL, REDACTED: REDACTED$1 } = constants
|
|
734
732
|
async function meowWithSubcommands(subcommands, options) {
|
|
735
733
|
const {
|
|
736
734
|
aliases = {},
|
|
@@ -803,15 +801,43 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
803
801
|
// Hard override the config if instructed to do so.
|
|
804
802
|
// The env var overrides the --flag, which overrides the persisted config
|
|
805
803
|
// Also, when either of these are used, config updates won't persist.
|
|
804
|
+
let configOverrideResult
|
|
806
805
|
if (process$1.env['SOCKET_CLI_CONFIG']) {
|
|
807
|
-
shadowNpmInject.overrideCachedConfig(
|
|
808
|
-
|
|
806
|
+
configOverrideResult = shadowNpmInject.overrideCachedConfig(
|
|
807
|
+
process$1.env['SOCKET_CLI_CONFIG']
|
|
809
808
|
)
|
|
810
809
|
} else if (cli.flags['config']) {
|
|
811
|
-
shadowNpmInject.overrideCachedConfig(
|
|
812
|
-
|
|
810
|
+
configOverrideResult = shadowNpmInject.overrideCachedConfig(
|
|
811
|
+
String(cli.flags['config'] || '')
|
|
813
812
|
)
|
|
814
813
|
}
|
|
814
|
+
if (process$1.env['SOCKET_CLI_NO_API_TOKEN']) {
|
|
815
|
+
// This overrides the config override and even the explicit token env var.
|
|
816
|
+
// The config will be marked as readOnly to prevent persisting it.
|
|
817
|
+
shadowNpmInject.overrideConfigApiToken(undefined)
|
|
818
|
+
} else {
|
|
819
|
+
// Note: these are SOCKET_SECURITY prefixed because they're not specific to
|
|
820
|
+
// the CLI. For the sake of consistency we'll also support the env
|
|
821
|
+
// keys that do have the SOCKET_CLI prefix, it's an easy mistake.
|
|
822
|
+
// In case multiple are supplied, the tokens supersede the keys and the
|
|
823
|
+
// security prefix supersedes the cli prefix. "Adventure mode" ;)
|
|
824
|
+
const tokenOverride =
|
|
825
|
+
process$1.env['SOCKET_CLI_API_KEY'] ||
|
|
826
|
+
process$1.env['SOCKET_SECURITY_API_KEY'] ||
|
|
827
|
+
process$1.env['SOCKET_CLI_API_TOKEN'] ||
|
|
828
|
+
process$1.env['SOCKET_SECURITY_API_TOKEN']
|
|
829
|
+
if (tokenOverride) {
|
|
830
|
+
// This will set the token (even if there was a config override) and
|
|
831
|
+
// set it to readOnly, making sure the temp token won't be persisted.
|
|
832
|
+
shadowNpmInject.overrideConfigApiToken(tokenOverride)
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (configOverrideResult?.ok === false) {
|
|
836
|
+
emitBanner(name)
|
|
837
|
+
logger.logger.fail(configOverrideResult.message)
|
|
838
|
+
process$1.exitCode = 2
|
|
839
|
+
return
|
|
840
|
+
}
|
|
815
841
|
|
|
816
842
|
// If we got at least some args, then lets find out if we can find a command.
|
|
817
843
|
if (commandOrAliasName) {
|
|
@@ -836,7 +862,7 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
836
862
|
}
|
|
837
863
|
if (!cli.flags['help'] && cli.flags['dryRun']) {
|
|
838
864
|
process$1.exitCode = 0
|
|
839
|
-
logger.logger.log(`${DRY_RUN_LABEL
|
|
865
|
+
logger.logger.log(`${DRY_RUN_LABEL}: No-op, call a sub-command; ok`)
|
|
840
866
|
} else {
|
|
841
867
|
cli.showHelp()
|
|
842
868
|
}
|
|
@@ -885,9 +911,9 @@ function emitBanner(name) {
|
|
|
885
911
|
logger.logger.error(getAsciiHeader(name))
|
|
886
912
|
}
|
|
887
913
|
function getAsciiHeader(command) {
|
|
888
|
-
const cliVersion = '0.14.
|
|
914
|
+
const cliVersion = '0.14.70:1042a5b:48e75331:pub' // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION_HASH']".
|
|
889
915
|
const nodeVersion = process$1.version
|
|
890
|
-
const apiToken = shadowNpmInject.
|
|
916
|
+
const apiToken = shadowNpmInject.getDefaultToken()
|
|
891
917
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no'
|
|
892
918
|
const relCwd = path.normalizePath(
|
|
893
919
|
process$1
|
|
@@ -908,7 +934,7 @@ function getAsciiHeader(command) {
|
|
|
908
934
|
return ` ${body}\n`
|
|
909
935
|
}
|
|
910
936
|
|
|
911
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
937
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$G } = constants
|
|
912
938
|
const config$J = {
|
|
913
939
|
commandName: 'analytics',
|
|
914
940
|
description: `Look up analytics data`,
|
|
@@ -921,7 +947,7 @@ const config$J = {
|
|
|
921
947
|
shortFlag: 'f',
|
|
922
948
|
default: '-',
|
|
923
949
|
description:
|
|
924
|
-
'
|
|
950
|
+
'Filepath to save output. Only valid with --json/--markdown. Defaults to stdout.'
|
|
925
951
|
},
|
|
926
952
|
repo: {
|
|
927
953
|
type: 'string',
|
|
@@ -947,6 +973,10 @@ const config$J = {
|
|
|
947
973
|
Usage
|
|
948
974
|
$ ${command} --scope=<scope> --time=<time filter>
|
|
949
975
|
|
|
976
|
+
API Token Requirements
|
|
977
|
+
- Quota: 1 unit
|
|
978
|
+
- Permissions: report:write
|
|
979
|
+
|
|
950
980
|
Default parameters are set to show the organization-level analytics over the
|
|
951
981
|
last 7 days.
|
|
952
982
|
|
|
@@ -1022,7 +1052,7 @@ async function run$J(argv, importMeta, { parentName }) {
|
|
|
1022
1052
|
return
|
|
1023
1053
|
}
|
|
1024
1054
|
if (cli.flags['dryRun']) {
|
|
1025
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1055
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$G)
|
|
1026
1056
|
return
|
|
1027
1057
|
}
|
|
1028
1058
|
assert(assertScope(scope))
|
|
@@ -1063,31 +1093,43 @@ async function fetchAuditLog({ logType, orgSlug, outputKind, page, perPage }) {
|
|
|
1063
1093
|
)
|
|
1064
1094
|
if (!result.success) {
|
|
1065
1095
|
handleUnsuccessfulApiResponse('getAuditLogEvents', result)
|
|
1066
|
-
return
|
|
1067
1096
|
}
|
|
1068
1097
|
spinner.stop()
|
|
1069
1098
|
return result.data
|
|
1070
1099
|
}
|
|
1071
1100
|
|
|
1101
|
+
const { REDACTED } = constants
|
|
1072
1102
|
async function outputAuditLog(
|
|
1073
1103
|
auditLogs,
|
|
1074
1104
|
{ logType, orgSlug, outputKind, page, perPage }
|
|
1075
1105
|
) {
|
|
1076
1106
|
if (outputKind === 'json') {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1107
|
+
logger.logger.log(
|
|
1108
|
+
await outputAsJson(auditLogs.results, {
|
|
1109
|
+
logType,
|
|
1110
|
+
orgSlug,
|
|
1111
|
+
page,
|
|
1112
|
+
perPage
|
|
1113
|
+
})
|
|
1114
|
+
)
|
|
1080
1115
|
} else {
|
|
1081
|
-
|
|
1116
|
+
logger.logger.log(
|
|
1117
|
+
await outputAsMarkdown(auditLogs.results, {
|
|
1118
|
+
logType,
|
|
1119
|
+
orgSlug,
|
|
1120
|
+
page,
|
|
1121
|
+
perPage
|
|
1122
|
+
})
|
|
1123
|
+
)
|
|
1082
1124
|
}
|
|
1083
1125
|
}
|
|
1084
|
-
async function outputAsJson(auditLogs,
|
|
1126
|
+
async function outputAsJson(auditLogs, { logType, orgSlug, page, perPage }) {
|
|
1085
1127
|
let json
|
|
1086
1128
|
try {
|
|
1087
1129
|
json = JSON.stringify(
|
|
1088
1130
|
{
|
|
1089
1131
|
desc: 'Audit logs for given query',
|
|
1090
|
-
generated: new Date().toISOString(),
|
|
1132
|
+
generated: false ? REDACTED : new Date().toISOString(),
|
|
1091
1133
|
org: orgSlug,
|
|
1092
1134
|
logType,
|
|
1093
1135
|
page,
|
|
@@ -1116,15 +1158,21 @@ async function outputAsJson(auditLogs, orgSlug, logType, page, perPage) {
|
|
|
1116
1158
|
2
|
|
1117
1159
|
)
|
|
1118
1160
|
} catch (e) {
|
|
1119
|
-
process.exitCode = 1
|
|
1161
|
+
process$1.exitCode = 1
|
|
1120
1162
|
logger.logger.fail(
|
|
1121
1163
|
'There was a problem converting the logs to JSON, please try without the `--json` flag'
|
|
1122
1164
|
)
|
|
1123
|
-
|
|
1165
|
+
if (debug.isDebug()) {
|
|
1166
|
+
debug.debugLog('Error:\n', e)
|
|
1167
|
+
}
|
|
1168
|
+
return '{}'
|
|
1124
1169
|
}
|
|
1125
|
-
|
|
1170
|
+
return json
|
|
1126
1171
|
}
|
|
1127
|
-
async function outputAsMarkdown(
|
|
1172
|
+
async function outputAsMarkdown(
|
|
1173
|
+
auditLogs,
|
|
1174
|
+
{ logType, orgSlug, page, perPage }
|
|
1175
|
+
) {
|
|
1128
1176
|
try {
|
|
1129
1177
|
const table = mdTable(auditLogs, [
|
|
1130
1178
|
'event_id',
|
|
@@ -1134,7 +1182,7 @@ async function outputAsMarkdown(auditLogs, orgSlug, logType, page, perPage) {
|
|
|
1134
1182
|
'ip_address',
|
|
1135
1183
|
'user_agent'
|
|
1136
1184
|
])
|
|
1137
|
-
|
|
1185
|
+
return `
|
|
1138
1186
|
# Socket Audit Logs
|
|
1139
1187
|
|
|
1140
1188
|
These are the Socket.dev audit logs as per requested query.
|
|
@@ -1142,50 +1190,21 @@ These are the Socket.dev audit logs as per requested query.
|
|
|
1142
1190
|
- type filter: ${logType || '(none)'}
|
|
1143
1191
|
- page: ${page}
|
|
1144
1192
|
- per page: ${perPage}
|
|
1145
|
-
- generated: ${new Date().toISOString()}
|
|
1193
|
+
- generated: ${false ? REDACTED : new Date().toISOString()}
|
|
1146
1194
|
|
|
1147
1195
|
${table}
|
|
1148
|
-
`
|
|
1196
|
+
`
|
|
1149
1197
|
} catch (e) {
|
|
1150
|
-
process.exitCode = 1
|
|
1198
|
+
process$1.exitCode = 1
|
|
1151
1199
|
logger.logger.fail(
|
|
1152
|
-
'There was a problem converting the logs to
|
|
1200
|
+
'There was a problem converting the logs to Markdown, please try the `--json` flag'
|
|
1153
1201
|
)
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
async function outputAsPrint(auditLogs, orgSlug, logType) {
|
|
1159
|
-
const data = []
|
|
1160
|
-
const logDetails = {}
|
|
1161
|
-
for (const d of auditLogs) {
|
|
1162
|
-
const { created_at } = d
|
|
1163
|
-
if (created_at) {
|
|
1164
|
-
const name = `${new Date(created_at).toLocaleDateString('en-us', {
|
|
1165
|
-
year: 'numeric',
|
|
1166
|
-
month: 'numeric',
|
|
1167
|
-
day: 'numeric'
|
|
1168
|
-
})} - ${d.user_email} - ${d.type} - ${d.ip_address} - ${d.user_agent}`
|
|
1169
|
-
data.push(
|
|
1170
|
-
{
|
|
1171
|
-
name
|
|
1172
|
-
},
|
|
1173
|
-
new prompts.Separator()
|
|
1174
|
-
)
|
|
1175
|
-
logDetails[name] = JSON.stringify(d.payload)
|
|
1202
|
+
if (debug.isDebug()) {
|
|
1203
|
+
debug.debugLog('Error:\n', e)
|
|
1176
1204
|
}
|
|
1205
|
+
// logger.error(e)
|
|
1206
|
+
return ''
|
|
1177
1207
|
}
|
|
1178
|
-
logger.logger.log(
|
|
1179
|
-
logDetails[
|
|
1180
|
-
await prompts.select({
|
|
1181
|
-
message: logType
|
|
1182
|
-
? `\n Audit log for: ${orgSlug} with type: ${logType}\n`
|
|
1183
|
-
: `\n Audit log for: ${orgSlug}\n`,
|
|
1184
|
-
choices: data,
|
|
1185
|
-
pageSize: 30
|
|
1186
|
-
})
|
|
1187
|
-
]
|
|
1188
|
-
)
|
|
1189
1208
|
}
|
|
1190
1209
|
|
|
1191
1210
|
async function handleAuditLog({ logType, orgSlug, outputKind, page, perPage }) {
|
|
@@ -1208,7 +1227,7 @@ async function handleAuditLog({ logType, orgSlug, outputKind, page, perPage }) {
|
|
|
1208
1227
|
})
|
|
1209
1228
|
}
|
|
1210
1229
|
|
|
1211
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1230
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$F } = constants
|
|
1212
1231
|
const config$I = {
|
|
1213
1232
|
commandName: 'audit-log',
|
|
1214
1233
|
description: 'Look up the audit log for an organization',
|
|
@@ -1239,6 +1258,10 @@ const config$I = {
|
|
|
1239
1258
|
Usage
|
|
1240
1259
|
$ ${command} <org slug>
|
|
1241
1260
|
|
|
1261
|
+
API Token Requirements
|
|
1262
|
+
- Quota: 1 unit
|
|
1263
|
+
- Permissions: audit-log:list
|
|
1264
|
+
|
|
1242
1265
|
This feature requires an Enterprise Plan. To learn more about getting access
|
|
1243
1266
|
to this feature and many more, please visit https://socket.dev/pricing
|
|
1244
1267
|
|
|
@@ -1294,7 +1317,7 @@ async function run$I(argv, importMeta, { parentName }) {
|
|
|
1294
1317
|
return
|
|
1295
1318
|
}
|
|
1296
1319
|
if (cli.flags['dryRun']) {
|
|
1297
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1320
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$F)
|
|
1298
1321
|
return
|
|
1299
1322
|
}
|
|
1300
1323
|
await handleAuditLog({
|
|
@@ -1422,7 +1445,7 @@ function isHelpFlag(cmdArg) {
|
|
|
1422
1445
|
}
|
|
1423
1446
|
|
|
1424
1447
|
// import { meowOrExit } from '../../utils/meow-with-subcommands'
|
|
1425
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1448
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$E } = constants
|
|
1426
1449
|
|
|
1427
1450
|
// TODO: convert yargs to meow. Or convert all the other things to yargs.
|
|
1428
1451
|
const toLower = arg => arg.toLowerCase()
|
|
@@ -1585,7 +1608,7 @@ async function run$H(argv, importMeta, { parentName }) {
|
|
|
1585
1608
|
return
|
|
1586
1609
|
}
|
|
1587
1610
|
if (cli.flags['dryRun']) {
|
|
1588
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1611
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$E)
|
|
1589
1612
|
return
|
|
1590
1613
|
}
|
|
1591
1614
|
if (yargv.output === undefined) {
|
|
@@ -1621,7 +1644,7 @@ async function discoverConfigValue(key) {
|
|
|
1621
1644
|
success: false,
|
|
1622
1645
|
value: undefined,
|
|
1623
1646
|
message:
|
|
1624
|
-
'When uncertain, unset this key. Otherwise ask your network administrator
|
|
1647
|
+
'When uncertain, unset this key. Otherwise ask your network administrator'
|
|
1625
1648
|
}
|
|
1626
1649
|
}
|
|
1627
1650
|
if (key === 'apiToken') {
|
|
@@ -1835,7 +1858,7 @@ async function handleConfigAuto({ key, outputKind }) {
|
|
|
1835
1858
|
await outputConfigAuto(key, result, outputKind)
|
|
1836
1859
|
}
|
|
1837
1860
|
|
|
1838
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1861
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$D } = constants
|
|
1839
1862
|
const config$G = {
|
|
1840
1863
|
commandName: 'auto',
|
|
1841
1864
|
description: 'Automatically discover and set the correct value config item',
|
|
@@ -1900,7 +1923,7 @@ async function run$G(argv, importMeta, { parentName }) {
|
|
|
1900
1923
|
return
|
|
1901
1924
|
}
|
|
1902
1925
|
if (cli.flags['dryRun']) {
|
|
1903
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1926
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$D)
|
|
1904
1927
|
return
|
|
1905
1928
|
}
|
|
1906
1929
|
await handleConfigAuto({
|
|
@@ -1909,7 +1932,13 @@ async function run$G(argv, importMeta, { parentName }) {
|
|
|
1909
1932
|
})
|
|
1910
1933
|
}
|
|
1911
1934
|
|
|
1912
|
-
async function outputConfigGet(
|
|
1935
|
+
async function outputConfigGet(
|
|
1936
|
+
key,
|
|
1937
|
+
value,
|
|
1938
|
+
readOnly,
|
|
1939
|
+
// Is config in read-only mode? (Overrides applied)
|
|
1940
|
+
outputKind
|
|
1941
|
+
) {
|
|
1913
1942
|
if (outputKind === 'json') {
|
|
1914
1943
|
logger.logger.log(
|
|
1915
1944
|
JSON.stringify({
|
|
@@ -1917,24 +1946,38 @@ async function outputConfigGet(key, value, outputKind) {
|
|
|
1917
1946
|
result: {
|
|
1918
1947
|
key,
|
|
1919
1948
|
value
|
|
1920
|
-
}
|
|
1949
|
+
},
|
|
1950
|
+
readOnly
|
|
1921
1951
|
})
|
|
1922
1952
|
)
|
|
1923
1953
|
} else if (outputKind === 'markdown') {
|
|
1924
1954
|
logger.logger.log(`# Config Value`)
|
|
1925
1955
|
logger.logger.log('')
|
|
1926
1956
|
logger.logger.log(`Config key '${key}' has value '${value}`)
|
|
1957
|
+
if (readOnly) {
|
|
1958
|
+
logger.logger.log('')
|
|
1959
|
+
logger.logger.log(
|
|
1960
|
+
'Note: the config is in read-only mode, meaning at least one key was temporarily\n overridden from an env var or command flag.'
|
|
1961
|
+
)
|
|
1962
|
+
}
|
|
1927
1963
|
} else {
|
|
1928
1964
|
logger.logger.log(`${key}: ${value}`)
|
|
1965
|
+
if (readOnly) {
|
|
1966
|
+
logger.logger.log('')
|
|
1967
|
+
logger.logger.log(
|
|
1968
|
+
'Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag.'
|
|
1969
|
+
)
|
|
1970
|
+
}
|
|
1929
1971
|
}
|
|
1930
1972
|
}
|
|
1931
1973
|
|
|
1932
1974
|
async function handleConfigGet({ key, outputKind }) {
|
|
1933
1975
|
const value = shadowNpmInject.getConfigValue(key)
|
|
1934
|
-
|
|
1976
|
+
const readOnly = shadowNpmInject.isReadOnlyConfig()
|
|
1977
|
+
await outputConfigGet(key, value, readOnly, outputKind)
|
|
1935
1978
|
}
|
|
1936
1979
|
|
|
1937
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1980
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$C } = constants
|
|
1938
1981
|
const config$F = {
|
|
1939
1982
|
commandName: 'get',
|
|
1940
1983
|
description: 'Get the value of a local CLI config item',
|
|
@@ -1994,7 +2037,7 @@ async function run$F(argv, importMeta, { parentName }) {
|
|
|
1994
2037
|
return
|
|
1995
2038
|
}
|
|
1996
2039
|
if (cli.flags['dryRun']) {
|
|
1997
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2040
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$C)
|
|
1998
2041
|
return
|
|
1999
2042
|
}
|
|
2000
2043
|
await handleConfigGet({
|
|
@@ -2004,6 +2047,7 @@ async function run$F(argv, importMeta, { parentName }) {
|
|
|
2004
2047
|
}
|
|
2005
2048
|
|
|
2006
2049
|
async function outputConfigList({ full, outputKind }) {
|
|
2050
|
+
const readOnly = shadowNpmInject.isReadOnlyConfig()
|
|
2007
2051
|
if (outputKind === 'json') {
|
|
2008
2052
|
const obj = {}
|
|
2009
2053
|
for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
|
|
@@ -2020,7 +2064,8 @@ async function outputConfigList({ full, outputKind }) {
|
|
|
2020
2064
|
{
|
|
2021
2065
|
success: true,
|
|
2022
2066
|
full,
|
|
2023
|
-
config: obj
|
|
2067
|
+
config: obj,
|
|
2068
|
+
readOnly
|
|
2024
2069
|
},
|
|
2025
2070
|
null,
|
|
2026
2071
|
2
|
|
@@ -2045,10 +2090,16 @@ async function outputConfigList({ full, outputKind }) {
|
|
|
2045
2090
|
)
|
|
2046
2091
|
}
|
|
2047
2092
|
}
|
|
2093
|
+
if (readOnly) {
|
|
2094
|
+
logger.logger.log('')
|
|
2095
|
+
logger.logger.log(
|
|
2096
|
+
'Note: the config is in read-only mode, meaning at least one key was temporarily\n overridden from an env var or command flag.'
|
|
2097
|
+
)
|
|
2098
|
+
}
|
|
2048
2099
|
}
|
|
2049
2100
|
}
|
|
2050
2101
|
|
|
2051
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
2102
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$B } = constants
|
|
2052
2103
|
const config$E = {
|
|
2053
2104
|
commandName: 'list',
|
|
2054
2105
|
description: 'Show all local CLI config items and their values',
|
|
@@ -2104,7 +2155,7 @@ async function run$E(argv, importMeta, { parentName }) {
|
|
|
2104
2155
|
return
|
|
2105
2156
|
}
|
|
2106
2157
|
if (cli.flags['dryRun']) {
|
|
2107
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2158
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$B)
|
|
2108
2159
|
return
|
|
2109
2160
|
}
|
|
2110
2161
|
await outputConfigList({
|
|
@@ -2113,29 +2164,43 @@ async function run$E(argv, importMeta, { parentName }) {
|
|
|
2113
2164
|
})
|
|
2114
2165
|
}
|
|
2115
2166
|
|
|
2116
|
-
async function outputConfigSet(key, _value, outputKind) {
|
|
2167
|
+
async function outputConfigSet(key, _value, readOnly, outputKind) {
|
|
2117
2168
|
if (outputKind === 'json') {
|
|
2118
2169
|
logger.logger.log(
|
|
2119
2170
|
JSON.stringify({
|
|
2120
2171
|
success: true,
|
|
2121
|
-
message: `Config key '${key}' was updated
|
|
2172
|
+
message: `Config key '${key}' was updated${readOnly ? ' (Note: since at least one value was overridden from flag/env, the config was not persisted)' : ''}`,
|
|
2173
|
+
readOnly
|
|
2122
2174
|
})
|
|
2123
2175
|
)
|
|
2124
2176
|
} else if (outputKind === 'markdown') {
|
|
2125
2177
|
logger.logger.log(`# Update config`)
|
|
2126
2178
|
logger.logger.log('')
|
|
2127
2179
|
logger.logger.log(`Config key '${key}' was updated`)
|
|
2180
|
+
if (readOnly) {
|
|
2181
|
+
logger.logger.log('')
|
|
2182
|
+
logger.logger.log(
|
|
2183
|
+
'Note: The change was not persisted because the config is in read-only mode,\n meaning at least one key was temporarily overridden from an env var or\n command flag.'
|
|
2184
|
+
)
|
|
2185
|
+
}
|
|
2128
2186
|
} else {
|
|
2129
2187
|
logger.logger.log(`OK`)
|
|
2188
|
+
if (readOnly) {
|
|
2189
|
+
logger.logger.log('')
|
|
2190
|
+
logger.logger.log(
|
|
2191
|
+
'Note: The change was not persisted because the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag.'
|
|
2192
|
+
)
|
|
2193
|
+
}
|
|
2130
2194
|
}
|
|
2131
2195
|
}
|
|
2132
2196
|
|
|
2133
2197
|
async function handleConfigSet({ key, outputKind, value }) {
|
|
2134
2198
|
shadowNpmInject.updateConfigValue(key, value)
|
|
2135
|
-
|
|
2199
|
+
const readOnly = shadowNpmInject.isReadOnlyConfig()
|
|
2200
|
+
await outputConfigSet(key, value, readOnly, outputKind)
|
|
2136
2201
|
}
|
|
2137
2202
|
|
|
2138
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
2203
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$A } = constants
|
|
2139
2204
|
const config$D = {
|
|
2140
2205
|
commandName: 'set',
|
|
2141
2206
|
description: 'Update the value of a local CLI config item',
|
|
@@ -2209,7 +2274,7 @@ async function run$D(argv, importMeta, { parentName }) {
|
|
|
2209
2274
|
return
|
|
2210
2275
|
}
|
|
2211
2276
|
if (cli.flags['dryRun']) {
|
|
2212
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2277
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$A)
|
|
2213
2278
|
return
|
|
2214
2279
|
}
|
|
2215
2280
|
await handleConfigSet({
|
|
@@ -2241,7 +2306,7 @@ async function handleConfigUnset({ key, outputKind }) {
|
|
|
2241
2306
|
await outputConfigUnset(key, outputKind)
|
|
2242
2307
|
}
|
|
2243
2308
|
|
|
2244
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
2309
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$z } = constants
|
|
2245
2310
|
const config$C = {
|
|
2246
2311
|
commandName: 'unset',
|
|
2247
2312
|
description: 'Clear the value of a local CLI config item',
|
|
@@ -2301,7 +2366,7 @@ async function run$C(argv, importMeta, { parentName }) {
|
|
|
2301
2366
|
return
|
|
2302
2367
|
}
|
|
2303
2368
|
if (cli.flags['dryRun']) {
|
|
2304
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2369
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$z)
|
|
2305
2370
|
return
|
|
2306
2371
|
}
|
|
2307
2372
|
await handleConfigUnset({
|
|
@@ -2350,7 +2415,6 @@ async function fetchDependencies({ limit, offset }) {
|
|
|
2350
2415
|
spinner.successAndStop('Received organization dependencies response.')
|
|
2351
2416
|
if (!result.success) {
|
|
2352
2417
|
handleUnsuccessfulApiResponse('searchDependencies', result)
|
|
2353
|
-
return
|
|
2354
2418
|
}
|
|
2355
2419
|
return result.data
|
|
2356
2420
|
}
|
|
@@ -2429,7 +2493,7 @@ async function handleDependencies({ limit, offset, outputKind }) {
|
|
|
2429
2493
|
})
|
|
2430
2494
|
}
|
|
2431
2495
|
|
|
2432
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
2496
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$y } = constants
|
|
2433
2497
|
const config$B = {
|
|
2434
2498
|
commandName: 'dependencies',
|
|
2435
2499
|
description:
|
|
@@ -2455,6 +2519,10 @@ const config$B = {
|
|
|
2455
2519
|
Usage
|
|
2456
2520
|
${command}
|
|
2457
2521
|
|
|
2522
|
+
API Token Requirements
|
|
2523
|
+
- Quota: 1 unit
|
|
2524
|
+
- Permissions: none (does need token with access to target org)
|
|
2525
|
+
|
|
2458
2526
|
Options
|
|
2459
2527
|
${getFlagListOutput(config.flags, 6)}
|
|
2460
2528
|
|
|
@@ -2498,7 +2566,7 @@ async function run$B(argv, importMeta, { parentName }) {
|
|
|
2498
2566
|
return
|
|
2499
2567
|
}
|
|
2500
2568
|
if (cli.flags['dryRun']) {
|
|
2501
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2569
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$y)
|
|
2502
2570
|
return
|
|
2503
2571
|
}
|
|
2504
2572
|
await handleDependencies({
|
|
@@ -2612,7 +2680,7 @@ async function handleDiffScan({
|
|
|
2612
2680
|
})
|
|
2613
2681
|
}
|
|
2614
2682
|
|
|
2615
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
2683
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$x } = constants
|
|
2616
2684
|
const config$A = {
|
|
2617
2685
|
commandName: 'get',
|
|
2618
2686
|
description: 'Get a diff scan for an organization',
|
|
@@ -2656,6 +2724,10 @@ const config$A = {
|
|
|
2656
2724
|
Usage
|
|
2657
2725
|
$ ${command} <org slug> --before=<before> --after=<after>
|
|
2658
2726
|
|
|
2727
|
+
API Token Requirements
|
|
2728
|
+
- Quota: 1 unit
|
|
2729
|
+
- Permissions: full-scans:list
|
|
2730
|
+
|
|
2659
2731
|
This command displays the package changes between two scans. The full output
|
|
2660
2732
|
can be pretty large depending on the size of your repo and time range. It is
|
|
2661
2733
|
best stored to disk to be further analyzed by other tools.
|
|
@@ -2687,7 +2759,7 @@ async function run$A(argv, importMeta, { parentName }) {
|
|
|
2687
2759
|
{
|
|
2688
2760
|
test: !!(before && after),
|
|
2689
2761
|
message:
|
|
2690
|
-
'Specify a before and after scan ID
|
|
2762
|
+
'Specify a before and after scan ID.\nThe args are expecting a full `aaa0aa0a-aaaa-0000-0a0a-0000000a00a0` scan ID.',
|
|
2691
2763
|
pass: 'ok',
|
|
2692
2764
|
fail:
|
|
2693
2765
|
!before && !after
|
|
@@ -2724,7 +2796,7 @@ async function run$A(argv, importMeta, { parentName }) {
|
|
|
2724
2796
|
return
|
|
2725
2797
|
}
|
|
2726
2798
|
if (cli.flags['dryRun']) {
|
|
2727
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
2799
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$x)
|
|
2728
2800
|
return
|
|
2729
2801
|
}
|
|
2730
2802
|
await handleDiffScan({
|
|
@@ -2764,8 +2836,13 @@ const { NPM: NPM$f } = constants
|
|
|
2764
2836
|
function isTopLevel(tree, node) {
|
|
2765
2837
|
return tree.children.get(node.name) === node
|
|
2766
2838
|
}
|
|
2767
|
-
async function npmFix(_pkgEnvDetails,
|
|
2768
|
-
const {
|
|
2839
|
+
async function npmFix(_pkgEnvDetails, options) {
|
|
2840
|
+
const {
|
|
2841
|
+
cwd = process.cwd(),
|
|
2842
|
+
spinner,
|
|
2843
|
+
test = false,
|
|
2844
|
+
testScript = 'test'
|
|
2845
|
+
} = {
|
|
2769
2846
|
__proto__: null,
|
|
2770
2847
|
...options
|
|
2771
2848
|
}
|
|
@@ -2781,7 +2858,8 @@ async function npmFix(_pkgEnvDetails, cwd, options) {
|
|
|
2781
2858
|
existing: true,
|
|
2782
2859
|
unfixable: false,
|
|
2783
2860
|
upgradable: false
|
|
2784
|
-
}
|
|
2861
|
+
},
|
|
2862
|
+
nothrow: true
|
|
2785
2863
|
})
|
|
2786
2864
|
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap)
|
|
2787
2865
|
if (!infoByPkg) {
|
|
@@ -2826,11 +2904,13 @@ async function npmFix(_pkgEnvDetails, cwd, options) {
|
|
|
2826
2904
|
shadowNpmInject.updateNode(node, packument, vulnerableVersionRange)
|
|
2827
2905
|
) {
|
|
2828
2906
|
try {
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2907
|
+
if (test) {
|
|
2908
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2909
|
+
await npm.runScript(testScript, [], {
|
|
2910
|
+
spinner,
|
|
2911
|
+
stdio: 'ignore'
|
|
2912
|
+
})
|
|
2913
|
+
}
|
|
2834
2914
|
spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`)
|
|
2835
2915
|
if (isTopLevel(tree, node)) {
|
|
2836
2916
|
for (const depField of [
|
|
@@ -2866,16 +2946,24 @@ async function npmFix(_pkgEnvDetails, cwd, options) {
|
|
|
2866
2946
|
spinner?.stop()
|
|
2867
2947
|
}
|
|
2868
2948
|
|
|
2869
|
-
async function getAlertsMapFromPnpmLockfile(lockfile,
|
|
2870
|
-
const
|
|
2949
|
+
async function getAlertsMapFromPnpmLockfile(lockfile, options_) {
|
|
2950
|
+
const options = {
|
|
2871
2951
|
__proto__: null,
|
|
2872
|
-
|
|
2952
|
+
consolidate: false,
|
|
2953
|
+
nothrow: false,
|
|
2954
|
+
...options_
|
|
2873
2955
|
}
|
|
2874
2956
|
const include = {
|
|
2875
2957
|
__proto__: null,
|
|
2958
|
+
blocked: true,
|
|
2959
|
+
critical: true,
|
|
2960
|
+
cve: true,
|
|
2961
|
+
existing: false,
|
|
2876
2962
|
unfixable: true,
|
|
2877
|
-
|
|
2963
|
+
upgradable: false,
|
|
2964
|
+
...options.include
|
|
2878
2965
|
}
|
|
2966
|
+
const { spinner } = options
|
|
2879
2967
|
const depTypes = lockfile_detectDepTypes.detectDepTypes(lockfile)
|
|
2880
2968
|
const pkgIds = Object.keys(depTypes)
|
|
2881
2969
|
let { length: remaining } = pkgIds
|
|
@@ -2890,9 +2978,11 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
|
2890
2978
|
)
|
|
2891
2979
|
const toAlertsMapOptions = {
|
|
2892
2980
|
overrides: lockfile.overrides,
|
|
2893
|
-
|
|
2981
|
+
consolidate: options.consolidate,
|
|
2982
|
+
include,
|
|
2983
|
+
spinner
|
|
2894
2984
|
}
|
|
2895
|
-
for await (const
|
|
2985
|
+
for await (const batchResult of sockSdk.batchPackageStream(
|
|
2896
2986
|
{
|
|
2897
2987
|
alerts: 'true',
|
|
2898
2988
|
compact: 'true',
|
|
@@ -2904,12 +2994,18 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
|
2904
2994
|
}))
|
|
2905
2995
|
}
|
|
2906
2996
|
)) {
|
|
2907
|
-
if (
|
|
2997
|
+
if (batchResult.success) {
|
|
2908
2998
|
await shadowNpmInject.addArtifactToAlertsMap(
|
|
2909
|
-
|
|
2999
|
+
batchResult.data,
|
|
2910
3000
|
alertsByPkgId,
|
|
2911
3001
|
toAlertsMapOptions
|
|
2912
3002
|
)
|
|
3003
|
+
} else if (!options.nothrow) {
|
|
3004
|
+
const statusCode = batchResult.status ?? 'unknown'
|
|
3005
|
+
const statusMessage = batchResult.error ?? 'No status message'
|
|
3006
|
+
throw new Error(
|
|
3007
|
+
`Socket API server error (${statusCode}): ${statusMessage}`
|
|
3008
|
+
)
|
|
2913
3009
|
}
|
|
2914
3010
|
remaining -= 1
|
|
2915
3011
|
if (spinner && remaining > 0) {
|
|
@@ -3021,13 +3117,13 @@ function runAgentInstall(pkgEnvDetails, options) {
|
|
|
3021
3117
|
}
|
|
3022
3118
|
return spawn.spawn(agentExecPath, ['install', ...args], {
|
|
3023
3119
|
spinner,
|
|
3024
|
-
stdio: debug.isDebug() ? 'inherit' : '
|
|
3120
|
+
stdio: debug.isDebug() ? 'inherit' : 'inherit',
|
|
3025
3121
|
...spawnOptions,
|
|
3026
3122
|
env: {
|
|
3027
3123
|
...process.env,
|
|
3028
3124
|
NODE_OPTIONS: cmdFlagsToString([
|
|
3029
3125
|
// Lazily access constants.nodeHardenFlags.
|
|
3030
|
-
...constants.nodeHardenFlags,
|
|
3126
|
+
// ...constants.nodeHardenFlags,
|
|
3031
3127
|
// Lazily access constants.nodeNoWarningsFlags.
|
|
3032
3128
|
...constants.nodeNoWarningsFlags
|
|
3033
3129
|
]),
|
|
@@ -3037,12 +3133,99 @@ function runAgentInstall(pkgEnvDetails, options) {
|
|
|
3037
3133
|
}
|
|
3038
3134
|
|
|
3039
3135
|
const { NPM: NPM$c, OVERRIDES: OVERRIDES$2, PNPM: PNPM$9 } = constants
|
|
3040
|
-
async function
|
|
3041
|
-
|
|
3136
|
+
async function branchExists(branchName, cwd) {
|
|
3137
|
+
try {
|
|
3138
|
+
await spawn.spawn('git', ['rev-parse', '--verify', branchName], {
|
|
3139
|
+
cwd,
|
|
3140
|
+
stdio: 'ignore'
|
|
3141
|
+
})
|
|
3142
|
+
return true
|
|
3143
|
+
} catch {
|
|
3144
|
+
return false
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
async function remoteBranchExists(branchName, cwd) {
|
|
3148
|
+
try {
|
|
3149
|
+
const result = await spawn.spawn(
|
|
3150
|
+
'git',
|
|
3151
|
+
['ls-remote', '--heads', 'origin', branchName],
|
|
3152
|
+
{
|
|
3153
|
+
cwd,
|
|
3154
|
+
stdio: 'pipe'
|
|
3155
|
+
}
|
|
3156
|
+
)
|
|
3157
|
+
return !!result.stdout.trim()
|
|
3158
|
+
} catch {
|
|
3159
|
+
return false
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
async function commitAndPushFix(branchName, commitMsg, cwd) {
|
|
3163
|
+
const localExists = await branchExists(branchName, cwd)
|
|
3164
|
+
const remoteExists = await remoteBranchExists(branchName, cwd)
|
|
3165
|
+
if (localExists || remoteExists) {
|
|
3166
|
+
logger.logger.warn(
|
|
3167
|
+
`Branch "${branchName}" already exists. Skipping creation.`
|
|
3168
|
+
)
|
|
3169
|
+
return
|
|
3170
|
+
}
|
|
3171
|
+
await spawn.spawn('git', ['checkout', '-b', branchName], {
|
|
3172
|
+
cwd
|
|
3173
|
+
})
|
|
3174
|
+
await spawn.spawn('git', ['add', 'package.json', 'pnpm-lock.yaml'], {
|
|
3175
|
+
cwd
|
|
3176
|
+
})
|
|
3177
|
+
await spawn.spawn('git', ['commit', '-m', commitMsg], {
|
|
3178
|
+
cwd
|
|
3179
|
+
})
|
|
3180
|
+
await spawn.spawn('git', ['push', '--set-upstream', 'origin', branchName], {
|
|
3181
|
+
cwd
|
|
3182
|
+
})
|
|
3183
|
+
}
|
|
3184
|
+
async function createPullRequest({
|
|
3185
|
+
base = 'main',
|
|
3186
|
+
body,
|
|
3187
|
+
head,
|
|
3188
|
+
owner,
|
|
3189
|
+
repo,
|
|
3190
|
+
title
|
|
3191
|
+
}) {
|
|
3192
|
+
const octokit = new vendor.Octokit({
|
|
3193
|
+
auth: process.env['GITHUB_TOKEN']
|
|
3194
|
+
})
|
|
3195
|
+
await octokit.pulls.create({
|
|
3196
|
+
owner,
|
|
3197
|
+
repo,
|
|
3198
|
+
title,
|
|
3199
|
+
head,
|
|
3200
|
+
base,
|
|
3201
|
+
...(body
|
|
3202
|
+
? {
|
|
3203
|
+
body
|
|
3204
|
+
}
|
|
3205
|
+
: {})
|
|
3206
|
+
})
|
|
3207
|
+
}
|
|
3208
|
+
function getRepoInfo() {
|
|
3209
|
+
const repoString = process.env['GITHUB_REPOSITORY']
|
|
3210
|
+
if (!repoString || !repoString.includes('/')) {
|
|
3211
|
+
throw new Error('GITHUB_REPOSITORY is not set or invalid')
|
|
3212
|
+
}
|
|
3213
|
+
const { 0: owner, 1: repo } = repoString.split('/')
|
|
3214
|
+
return {
|
|
3215
|
+
owner,
|
|
3216
|
+
repo
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
async function pnpmFix(pkgEnvDetails, options) {
|
|
3220
|
+
const {
|
|
3221
|
+
cwd = process.cwd(),
|
|
3222
|
+
spinner,
|
|
3223
|
+
test = false,
|
|
3224
|
+
testScript = 'test'
|
|
3225
|
+
} = {
|
|
3042
3226
|
__proto__: null,
|
|
3043
3227
|
...options
|
|
3044
3228
|
}
|
|
3045
|
-
spinner?.start()
|
|
3046
3229
|
const lockfile = await lockfile_fs.readWantedLockfile(cwd, {
|
|
3047
3230
|
ignoreIncompatible: false
|
|
3048
3231
|
})
|
|
@@ -3056,7 +3239,8 @@ async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
|
3056
3239
|
existing: true,
|
|
3057
3240
|
unfixable: false,
|
|
3058
3241
|
upgradable: false
|
|
3059
|
-
}
|
|
3242
|
+
},
|
|
3243
|
+
nothrow: true
|
|
3060
3244
|
})
|
|
3061
3245
|
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap)
|
|
3062
3246
|
if (!infoByPkg) {
|
|
@@ -3072,11 +3256,12 @@ async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
|
3072
3256
|
editable: true
|
|
3073
3257
|
})
|
|
3074
3258
|
const { content: pkgJson } = editablePkgJson
|
|
3259
|
+
spinner?.stop()
|
|
3075
3260
|
for (const { 0: name, 1: infos } of infoByPkg) {
|
|
3076
3261
|
const tree = arb.actualTree
|
|
3077
3262
|
const hasUpgrade = !!registry.getManifestData(NPM$c, name)
|
|
3078
3263
|
if (hasUpgrade) {
|
|
3079
|
-
|
|
3264
|
+
logger.logger.info(`Skipping ${name}. Socket Optimize package exists.`)
|
|
3080
3265
|
continue
|
|
3081
3266
|
}
|
|
3082
3267
|
const nodes = shadowNpmInject.findPackageNodes(tree, name)
|
|
@@ -3098,6 +3283,7 @@ async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
|
3098
3283
|
const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
|
|
3099
3284
|
infos[j]
|
|
3100
3285
|
const { version: oldVersion } = node
|
|
3286
|
+
const oldSpec = `${name}@${oldVersion}`
|
|
3101
3287
|
const availableVersions = Object.keys(packument.versions)
|
|
3102
3288
|
// Find the highest non-vulnerable version within the same major range
|
|
3103
3289
|
const targetVersion = shadowNpmInject.findBestPatchVersion(
|
|
@@ -3108,20 +3294,28 @@ async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
|
3108
3294
|
const targetPackument = targetVersion
|
|
3109
3295
|
? packument.versions[targetVersion]
|
|
3110
3296
|
: undefined
|
|
3111
|
-
|
|
3297
|
+
spinner?.stop()
|
|
3298
|
+
|
|
3299
|
+
// Check targetVersion to make TypeScript happy.
|
|
3300
|
+
if (targetVersion && targetPackument) {
|
|
3112
3301
|
const oldPnpm = pkgJson[PNPM$9]
|
|
3113
3302
|
const oldOverrides = oldPnpm?.[OVERRIDES$2]
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3303
|
+
const overrideKey = `${node.name}@${vulnerableVersionRange}`
|
|
3304
|
+
const overrideRange = `^${targetVersion}`
|
|
3305
|
+
const fixSpec = `${name}@${overrideRange}`
|
|
3306
|
+
const data = {
|
|
3307
|
+
[PNPM$9]: {
|
|
3308
|
+
...oldPnpm,
|
|
3309
|
+
[OVERRIDES$2]: {
|
|
3310
|
+
[overrideKey]: overrideRange,
|
|
3311
|
+
...oldOverrides
|
|
3122
3312
|
}
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
try {
|
|
3316
|
+
editablePkgJson.update(data)
|
|
3317
|
+
spinner?.start()
|
|
3318
|
+
spinner?.info(`Installing ${fixSpec}`)
|
|
3125
3319
|
|
|
3126
3320
|
// eslint-disable-next-line no-await-in-loop
|
|
3127
3321
|
await editablePkgJson.save()
|
|
@@ -3129,11 +3323,70 @@ async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
|
3129
3323
|
await runAgentInstall(pkgEnvDetails, {
|
|
3130
3324
|
spinner
|
|
3131
3325
|
})
|
|
3326
|
+
if (test) {
|
|
3327
|
+
spinner?.info(`Testing ${fixSpec}`)
|
|
3328
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3329
|
+
await npm.runScript(testScript, [], {
|
|
3330
|
+
spinner,
|
|
3331
|
+
stdio: 'ignore'
|
|
3332
|
+
})
|
|
3333
|
+
}
|
|
3334
|
+
try {
|
|
3335
|
+
const branchName = `fix-${name}-${targetVersion.replace(/\./g, '-')}`
|
|
3336
|
+
const commitMsg = `fix: upgrade ${name} to ${targetVersion}`
|
|
3337
|
+
const { owner, repo } = getRepoInfo()
|
|
3338
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3339
|
+
await commitAndPushFix(branchName, commitMsg, cwd)
|
|
3340
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3341
|
+
await createPullRequest({
|
|
3342
|
+
owner,
|
|
3343
|
+
repo,
|
|
3344
|
+
title: commitMsg,
|
|
3345
|
+
head: branchName,
|
|
3346
|
+
base: process.env['GITHUB_REF_NAME'] ?? 'master',
|
|
3347
|
+
body: `This PR fixes a security issue in \`${name}\` by upgrading to \`${targetVersion}\`.`
|
|
3348
|
+
})
|
|
3349
|
+
} catch (e) {
|
|
3350
|
+
console.log(e)
|
|
3351
|
+
}
|
|
3352
|
+
logger.logger.success(`Fixed ${name}`)
|
|
3132
3353
|
} catch {
|
|
3133
|
-
spinner?.error(`Reverting ${
|
|
3354
|
+
spinner?.error(`Reverting ${fixSpec}`)
|
|
3355
|
+
const pnpmKeyCount = Object.keys(data[PNPM$9]).length
|
|
3356
|
+
const pnpmOverridesKeyCount = Object.keys(
|
|
3357
|
+
data[PNPM$9][OVERRIDES$2]
|
|
3358
|
+
).length
|
|
3359
|
+
if (pnpmKeyCount === 1 && pnpmOverridesKeyCount === 1) {
|
|
3360
|
+
editablePkgJson.update({
|
|
3361
|
+
// Setting to `undefined` will remove the property.
|
|
3362
|
+
[PNPM$9]: undefined
|
|
3363
|
+
})
|
|
3364
|
+
} else {
|
|
3365
|
+
editablePkgJson.update({
|
|
3366
|
+
[PNPM$9]: {
|
|
3367
|
+
...oldPnpm,
|
|
3368
|
+
[OVERRIDES$2]:
|
|
3369
|
+
pnpmOverridesKeyCount === 1
|
|
3370
|
+
? undefined
|
|
3371
|
+
: {
|
|
3372
|
+
[overrideKey]: undefined,
|
|
3373
|
+
...oldOverrides
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
})
|
|
3377
|
+
}
|
|
3378
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3379
|
+
await editablePkgJson.save()
|
|
3380
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3381
|
+
await runAgentInstall(pkgEnvDetails, {
|
|
3382
|
+
spinner
|
|
3383
|
+
})
|
|
3384
|
+
spinner?.stop()
|
|
3385
|
+
logger.logger.error(`Failed to fix ${oldSpec}`)
|
|
3134
3386
|
}
|
|
3135
3387
|
} else {
|
|
3136
|
-
spinner?.
|
|
3388
|
+
spinner?.stop()
|
|
3389
|
+
logger.logger.error(`Could not patch ${oldSpec}`)
|
|
3137
3390
|
}
|
|
3138
3391
|
}
|
|
3139
3392
|
}
|
|
@@ -3539,39 +3792,59 @@ async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
|
3539
3792
|
|
|
3540
3793
|
const { NPM: NPM$a, PNPM: PNPM$7 } = constants
|
|
3541
3794
|
const CMD_NAME$2 = 'socket fix'
|
|
3542
|
-
async function runFix(
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3795
|
+
async function runFix({
|
|
3796
|
+
cwd = process.cwd(),
|
|
3797
|
+
spinner,
|
|
3798
|
+
test = false,
|
|
3799
|
+
testScript = 'test'
|
|
3800
|
+
}) {
|
|
3547
3801
|
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
3548
3802
|
cmdName: CMD_NAME$2,
|
|
3549
3803
|
logger: logger.logger
|
|
3550
3804
|
})
|
|
3551
3805
|
if (!pkgEnvDetails) {
|
|
3552
|
-
spinner
|
|
3806
|
+
spinner?.stop()
|
|
3553
3807
|
return
|
|
3554
3808
|
}
|
|
3809
|
+
logger.logger.info(`Fixing packages for ${pkgEnvDetails.agent}`)
|
|
3555
3810
|
switch (pkgEnvDetails.agent) {
|
|
3556
3811
|
case NPM$a: {
|
|
3557
|
-
await npmFix(pkgEnvDetails,
|
|
3812
|
+
await npmFix(pkgEnvDetails, {
|
|
3813
|
+
spinner,
|
|
3814
|
+
test,
|
|
3815
|
+
testScript
|
|
3816
|
+
})
|
|
3558
3817
|
break
|
|
3559
3818
|
}
|
|
3560
3819
|
case PNPM$7: {
|
|
3561
|
-
await pnpmFix(pkgEnvDetails,
|
|
3820
|
+
await pnpmFix(pkgEnvDetails, {
|
|
3821
|
+
spinner,
|
|
3822
|
+
test,
|
|
3823
|
+
testScript
|
|
3824
|
+
})
|
|
3562
3825
|
break
|
|
3563
3826
|
}
|
|
3564
3827
|
}
|
|
3565
|
-
spinner.successAndStop('Socket.dev fix successful')
|
|
3828
|
+
// spinner.successAndStop('Socket.dev fix successful')
|
|
3566
3829
|
}
|
|
3567
3830
|
|
|
3568
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
3831
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$w } = constants
|
|
3569
3832
|
const config$z = {
|
|
3570
3833
|
commandName: 'fix',
|
|
3571
3834
|
description: 'Fix "fixable" Socket alerts',
|
|
3572
3835
|
hidden: true,
|
|
3573
3836
|
flags: {
|
|
3574
|
-
...commonFlags
|
|
3837
|
+
...commonFlags,
|
|
3838
|
+
test: {
|
|
3839
|
+
type: 'boolean',
|
|
3840
|
+
default: true,
|
|
3841
|
+
description: 'Very the fix by running unit tests'
|
|
3842
|
+
},
|
|
3843
|
+
testScript: {
|
|
3844
|
+
type: 'string',
|
|
3845
|
+
default: 'test',
|
|
3846
|
+
description: 'The test script to run for each fix attempt'
|
|
3847
|
+
}
|
|
3575
3848
|
},
|
|
3576
3849
|
help: (command, config) => `
|
|
3577
3850
|
Usage
|
|
@@ -3594,10 +3867,17 @@ async function run$z(argv, importMeta, { parentName }) {
|
|
|
3594
3867
|
parentName
|
|
3595
3868
|
})
|
|
3596
3869
|
if (cli.flags['dryRun']) {
|
|
3597
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
3870
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$w)
|
|
3598
3871
|
return
|
|
3599
3872
|
}
|
|
3600
|
-
|
|
3873
|
+
|
|
3874
|
+
// Lazily access constants.spinner.
|
|
3875
|
+
const { spinner } = constants
|
|
3876
|
+
await runFix({
|
|
3877
|
+
spinner,
|
|
3878
|
+
test: Boolean(cli.flags['test']),
|
|
3879
|
+
testScript: cli.flags['testScript']
|
|
3880
|
+
})
|
|
3601
3881
|
}
|
|
3602
3882
|
|
|
3603
3883
|
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
@@ -3622,10 +3902,10 @@ async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
|
3622
3902
|
)
|
|
3623
3903
|
spinner.successAndStop('Data fetched')
|
|
3624
3904
|
if (result.success === false) {
|
|
3625
|
-
|
|
3905
|
+
handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result)
|
|
3626
3906
|
}
|
|
3627
3907
|
if (scoreResult.success === false) {
|
|
3628
|
-
|
|
3908
|
+
handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult)
|
|
3629
3909
|
}
|
|
3630
3910
|
const severityCount = shadowNpmInject.getSeverityCount(
|
|
3631
3911
|
result.data,
|
|
@@ -3786,7 +4066,7 @@ async function handlePackageInfo({
|
|
|
3786
4066
|
}
|
|
3787
4067
|
}
|
|
3788
4068
|
|
|
3789
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4069
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$v } = constants
|
|
3790
4070
|
const config$y = {
|
|
3791
4071
|
commandName: 'info',
|
|
3792
4072
|
description: 'Look up info regarding a package',
|
|
@@ -3854,7 +4134,7 @@ async function run$y(argv, importMeta, { parentName }) {
|
|
|
3854
4134
|
const pkgVersion =
|
|
3855
4135
|
versionSeparator < 1 ? 'latest' : rawPkgName.slice(versionSeparator + 1)
|
|
3856
4136
|
if (cli.flags['dryRun']) {
|
|
3857
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4137
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$v)
|
|
3858
4138
|
return
|
|
3859
4139
|
}
|
|
3860
4140
|
await handlePackageInfo({
|
|
@@ -3891,7 +4171,6 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
3891
4171
|
if (!result.success) {
|
|
3892
4172
|
logger.logger.fail('Authentication failed...')
|
|
3893
4173
|
handleUnsuccessfulApiResponse('getOrganizations', result)
|
|
3894
|
-
return
|
|
3895
4174
|
}
|
|
3896
4175
|
logger.logger.success('API key verified')
|
|
3897
4176
|
const orgs = result.data
|
|
@@ -3929,16 +4208,24 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
3929
4208
|
}
|
|
3930
4209
|
}
|
|
3931
4210
|
spinner.stop()
|
|
3932
|
-
const
|
|
4211
|
+
const previousPersistedToken = shadowNpmInject.getConfigValue('apiToken')
|
|
3933
4212
|
try {
|
|
3934
4213
|
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy)
|
|
3935
|
-
logger.logger.success(
|
|
4214
|
+
logger.logger.success(
|
|
4215
|
+
`API credentials ${previousPersistedToken === apiToken ? 'refreshed' : previousPersistedToken ? 'updated' : 'set'}`
|
|
4216
|
+
)
|
|
4217
|
+
if (!shadowNpmInject.isReadOnlyConfig()) {
|
|
4218
|
+
logger.logger.log('')
|
|
4219
|
+
logger.logger.warn(
|
|
4220
|
+
'Note: config is in read-only mode, at least one key was overridden through flag/env, so the login was not persisted!'
|
|
4221
|
+
)
|
|
4222
|
+
}
|
|
3936
4223
|
} catch {
|
|
3937
4224
|
logger.logger.fail(`API login failed`)
|
|
3938
4225
|
}
|
|
3939
4226
|
}
|
|
3940
4227
|
|
|
3941
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4228
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$u } = constants
|
|
3942
4229
|
const config$x = {
|
|
3943
4230
|
commandName: 'login',
|
|
3944
4231
|
description: 'Socket API login',
|
|
@@ -3958,6 +4245,9 @@ const config$x = {
|
|
|
3958
4245
|
Usage
|
|
3959
4246
|
$ ${command}
|
|
3960
4247
|
|
|
4248
|
+
API Token Requirements
|
|
4249
|
+
- Quota: 1 unit
|
|
4250
|
+
|
|
3961
4251
|
Logs into the Socket API by prompting for an API key
|
|
3962
4252
|
|
|
3963
4253
|
Options
|
|
@@ -3983,7 +4273,7 @@ async function run$x(argv, importMeta, { parentName }) {
|
|
|
3983
4273
|
const apiBaseUrl = cli.flags['apiBaseUrl']
|
|
3984
4274
|
const apiProxy = cli.flags['apiProxy']
|
|
3985
4275
|
if (cli.flags['dryRun']) {
|
|
3986
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4276
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$u)
|
|
3987
4277
|
return
|
|
3988
4278
|
}
|
|
3989
4279
|
if (!isInteractive()) {
|
|
@@ -4005,12 +4295,18 @@ function attemptLogout() {
|
|
|
4005
4295
|
try {
|
|
4006
4296
|
applyLogout()
|
|
4007
4297
|
logger.logger.success('Successfully logged out')
|
|
4298
|
+
if (!shadowNpmInject.isReadOnlyConfig()) {
|
|
4299
|
+
logger.logger.log('')
|
|
4300
|
+
logger.logger.warn(
|
|
4301
|
+
'Note: config is in read-only mode, at least one key was overridden through flag/env, so the logout was not persisted!'
|
|
4302
|
+
)
|
|
4303
|
+
}
|
|
4008
4304
|
} catch {
|
|
4009
4305
|
logger.logger.fail('Failed to complete logout steps')
|
|
4010
4306
|
}
|
|
4011
4307
|
}
|
|
4012
4308
|
|
|
4013
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4309
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$t } = constants
|
|
4014
4310
|
const config$w = {
|
|
4015
4311
|
commandName: 'logout',
|
|
4016
4312
|
description: 'Socket API logout',
|
|
@@ -4038,7 +4334,7 @@ async function run$w(argv, importMeta, { parentName }) {
|
|
|
4038
4334
|
parentName
|
|
4039
4335
|
})
|
|
4040
4336
|
if (cli.flags['dryRun']) {
|
|
4041
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4337
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$t)
|
|
4042
4338
|
return
|
|
4043
4339
|
}
|
|
4044
4340
|
attemptLogout()
|
|
@@ -4146,7 +4442,7 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
|
|
|
4146
4442
|
}
|
|
4147
4443
|
}
|
|
4148
4444
|
|
|
4149
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4445
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$s } = constants
|
|
4150
4446
|
const config$v = {
|
|
4151
4447
|
commandName: 'gradle',
|
|
4152
4448
|
description:
|
|
@@ -4293,7 +4589,7 @@ async function run$v(argv, importMeta, { parentName }) {
|
|
|
4293
4589
|
.filter(Boolean)
|
|
4294
4590
|
}
|
|
4295
4591
|
if (cli.flags['dryRun']) {
|
|
4296
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4592
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$s)
|
|
4297
4593
|
return
|
|
4298
4594
|
}
|
|
4299
4595
|
await convertGradleToMaven(target, bin, out, verbose, gradleOpts)
|
|
@@ -4402,7 +4698,7 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
|
|
|
4402
4698
|
}
|
|
4403
4699
|
}
|
|
4404
4700
|
|
|
4405
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4701
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$r } = constants
|
|
4406
4702
|
const config$u = {
|
|
4407
4703
|
commandName: 'scala',
|
|
4408
4704
|
description:
|
|
@@ -4547,13 +4843,13 @@ async function run$u(argv, importMeta, { parentName }) {
|
|
|
4547
4843
|
.filter(Boolean)
|
|
4548
4844
|
}
|
|
4549
4845
|
if (cli.flags['dryRun']) {
|
|
4550
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4846
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$r)
|
|
4551
4847
|
return
|
|
4552
4848
|
}
|
|
4553
4849
|
await convertSbtToMaven(target, bin, out, verbose, sbtOpts)
|
|
4554
4850
|
}
|
|
4555
4851
|
|
|
4556
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4852
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$q } = constants
|
|
4557
4853
|
const config$t = {
|
|
4558
4854
|
commandName: 'auto',
|
|
4559
4855
|
description: 'Auto-detect build and attempt to generate manifest file',
|
|
@@ -4619,7 +4915,7 @@ async function run$t(argv, importMeta, { parentName }) {
|
|
|
4619
4915
|
}
|
|
4620
4916
|
subArgs.push(dir)
|
|
4621
4917
|
if (cli.flags['dryRun']) {
|
|
4622
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4918
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$q)
|
|
4623
4919
|
return
|
|
4624
4920
|
}
|
|
4625
4921
|
await cmdManifestScala.run(subArgs, importMeta, {
|
|
@@ -4636,7 +4932,7 @@ async function run$t(argv, importMeta, { parentName }) {
|
|
|
4636
4932
|
subArgs.push(cwd)
|
|
4637
4933
|
}
|
|
4638
4934
|
if (cli.flags['dryRun']) {
|
|
4639
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4935
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$q)
|
|
4640
4936
|
return
|
|
4641
4937
|
}
|
|
4642
4938
|
await cmdManifestGradle.run(subArgs, importMeta, {
|
|
@@ -4645,7 +4941,7 @@ async function run$t(argv, importMeta, { parentName }) {
|
|
|
4645
4941
|
return
|
|
4646
4942
|
}
|
|
4647
4943
|
if (cli.flags['dryRun']) {
|
|
4648
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
4944
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$q)
|
|
4649
4945
|
return
|
|
4650
4946
|
}
|
|
4651
4947
|
|
|
@@ -4674,7 +4970,7 @@ async function run$t(argv, importMeta, { parentName }) {
|
|
|
4674
4970
|
.showHelp()
|
|
4675
4971
|
}
|
|
4676
4972
|
|
|
4677
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
4973
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$p } = constants
|
|
4678
4974
|
|
|
4679
4975
|
// TODO: we may want to dedupe some pieces for all gradle languages. I think it
|
|
4680
4976
|
// makes sense to have separate commands for them and I think it makes
|
|
@@ -4827,7 +5123,7 @@ async function run$s(argv, importMeta, { parentName }) {
|
|
|
4827
5123
|
.filter(Boolean)
|
|
4828
5124
|
}
|
|
4829
5125
|
if (cli.flags['dryRun']) {
|
|
4830
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
5126
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$p)
|
|
4831
5127
|
return
|
|
4832
5128
|
}
|
|
4833
5129
|
await convertGradleToMaven(target, bin, out, verbose, gradleOpts)
|
|
@@ -4878,7 +5174,7 @@ async function wrapNpm(argv) {
|
|
|
4878
5174
|
await shadowBin(NPM$8, argv)
|
|
4879
5175
|
}
|
|
4880
5176
|
|
|
4881
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
5177
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$o, NPM: NPM$7 } = constants
|
|
4882
5178
|
const config$q = {
|
|
4883
5179
|
commandName: 'npm',
|
|
4884
5180
|
description: `${NPM$7} wrapper functionality`,
|
|
@@ -4905,7 +5201,7 @@ async function run$q(argv, importMeta, { parentName }) {
|
|
|
4905
5201
|
parentName
|
|
4906
5202
|
})
|
|
4907
5203
|
if (cli.flags['dryRun']) {
|
|
4908
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
5204
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$o)
|
|
4909
5205
|
return
|
|
4910
5206
|
}
|
|
4911
5207
|
await wrapNpm(argv)
|
|
@@ -4918,7 +5214,7 @@ async function wrapNpx(argv) {
|
|
|
4918
5214
|
await shadowBin(NPX$2, argv)
|
|
4919
5215
|
}
|
|
4920
5216
|
|
|
4921
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
5217
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$n, NPX: NPX$1 } = constants
|
|
4922
5218
|
const config$p = {
|
|
4923
5219
|
commandName: 'npx',
|
|
4924
5220
|
description: `${NPX$1} wrapper functionality`,
|
|
@@ -4945,13 +5241,13 @@ async function run$p(argv, importMeta, { parentName }) {
|
|
|
4945
5241
|
parentName
|
|
4946
5242
|
})
|
|
4947
5243
|
if (cli.flags['dryRun']) {
|
|
4948
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
5244
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$n)
|
|
4949
5245
|
return
|
|
4950
5246
|
}
|
|
4951
5247
|
await wrapNpx(argv)
|
|
4952
5248
|
}
|
|
4953
5249
|
|
|
4954
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
5250
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$m } = constants
|
|
4955
5251
|
const config$o = {
|
|
4956
5252
|
commandName: 'oops',
|
|
4957
5253
|
description: 'Trigger an intentional error (for development)',
|
|
@@ -4979,7 +5275,7 @@ async function run$o(argv, importMeta, { parentName }) {
|
|
|
4979
5275
|
parentName
|
|
4980
5276
|
})
|
|
4981
5277
|
if (cli.flags['dryRun']) {
|
|
4982
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
5278
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$m)
|
|
4983
5279
|
return
|
|
4984
5280
|
}
|
|
4985
5281
|
throw new Error('This error was intentionally left blank')
|
|
@@ -5868,7 +6164,7 @@ async function applyOptimization(cwd, pin, prod) {
|
|
|
5868
6164
|
}
|
|
5869
6165
|
}
|
|
5870
6166
|
|
|
5871
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
6167
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$l } = constants
|
|
5872
6168
|
const config$n = {
|
|
5873
6169
|
commandName: 'optimize',
|
|
5874
6170
|
description: 'Optimize dependencies with @socketregistry overrides',
|
|
@@ -5912,7 +6208,7 @@ async function run$n(argv, importMeta, { parentName }) {
|
|
|
5912
6208
|
})
|
|
5913
6209
|
const cwd = process.cwd()
|
|
5914
6210
|
if (cli.flags['dryRun']) {
|
|
5915
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
6211
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$l)
|
|
5916
6212
|
return
|
|
5917
6213
|
}
|
|
5918
6214
|
await applyOptimization(
|
|
@@ -5935,7 +6231,6 @@ async function fetchOrganization() {
|
|
|
5935
6231
|
spinner.successAndStop('Received organization list response.')
|
|
5936
6232
|
if (!result.success) {
|
|
5937
6233
|
handleUnsuccessfulApiResponse('getOrganizations', result)
|
|
5938
|
-
return
|
|
5939
6234
|
}
|
|
5940
6235
|
return result.data
|
|
5941
6236
|
}
|
|
@@ -6014,7 +6309,7 @@ async function handleOrganizationList(outputKind = 'text') {
|
|
|
6014
6309
|
await outputOrganizationList(data, outputKind)
|
|
6015
6310
|
}
|
|
6016
6311
|
|
|
6017
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
6312
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$k } = constants
|
|
6018
6313
|
const config$m = {
|
|
6019
6314
|
commandName: 'list',
|
|
6020
6315
|
description: 'List organizations associated with the API key used',
|
|
@@ -6027,6 +6322,10 @@ const config$m = {
|
|
|
6027
6322
|
Usage
|
|
6028
6323
|
$ ${command}
|
|
6029
6324
|
|
|
6325
|
+
API Token Requirements
|
|
6326
|
+
- Quota: 1 unit
|
|
6327
|
+
- Permissions: none (does need a token)
|
|
6328
|
+
|
|
6030
6329
|
Options
|
|
6031
6330
|
${getFlagListOutput(config$m.flags, 6)}
|
|
6032
6331
|
`
|
|
@@ -6067,7 +6366,7 @@ async function run$m(argv, importMeta, { parentName }) {
|
|
|
6067
6366
|
return
|
|
6068
6367
|
}
|
|
6069
6368
|
if (cli.flags['dryRun']) {
|
|
6070
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
6369
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$k)
|
|
6071
6370
|
return
|
|
6072
6371
|
}
|
|
6073
6372
|
await handleOrganizationList(json ? 'json' : markdown ? 'markdown' : 'text')
|
|
@@ -6086,7 +6385,6 @@ async function fetchLicensePolicy(orgSlug) {
|
|
|
6086
6385
|
spinner.successAndStop('Received organization license policy response.')
|
|
6087
6386
|
if (!result.success) {
|
|
6088
6387
|
handleUnsuccessfulApiResponse('getOrgLicensePolicy', result)
|
|
6089
|
-
return
|
|
6090
6388
|
}
|
|
6091
6389
|
return result.data
|
|
6092
6390
|
}
|
|
@@ -6131,7 +6429,7 @@ async function handleLicensePolicy(orgSlug, outputKind) {
|
|
|
6131
6429
|
await outputLicensePolicy(data, outputKind)
|
|
6132
6430
|
}
|
|
6133
6431
|
|
|
6134
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
6432
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$j } = constants
|
|
6135
6433
|
|
|
6136
6434
|
// TODO: secret toplevel alias `socket license policy`?
|
|
6137
6435
|
const config$l = {
|
|
@@ -6146,6 +6444,10 @@ const config$l = {
|
|
|
6146
6444
|
Usage
|
|
6147
6445
|
$ ${command} <org slug>
|
|
6148
6446
|
|
|
6447
|
+
API Token Requirements
|
|
6448
|
+
- Quota: 1 unit
|
|
6449
|
+
- Permissions: license-policy:read
|
|
6450
|
+
|
|
6149
6451
|
Options
|
|
6150
6452
|
${getFlagListOutput(config$l.flags, 6)}
|
|
6151
6453
|
|
|
@@ -6202,7 +6504,7 @@ async function run$l(argv, importMeta, { parentName }) {
|
|
|
6202
6504
|
return
|
|
6203
6505
|
}
|
|
6204
6506
|
if (cli.flags['dryRun']) {
|
|
6205
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
6507
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$j)
|
|
6206
6508
|
return
|
|
6207
6509
|
}
|
|
6208
6510
|
await handleLicensePolicy(
|
|
@@ -6224,7 +6526,6 @@ async function fetchSecurityPolicy(orgSlug) {
|
|
|
6224
6526
|
spinner.successAndStop('Received organization security policy response.')
|
|
6225
6527
|
if (!result.success) {
|
|
6226
6528
|
handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result)
|
|
6227
|
-
return
|
|
6228
6529
|
}
|
|
6229
6530
|
return result.data
|
|
6230
6531
|
}
|
|
@@ -6270,7 +6571,7 @@ async function handleSecurityPolicy(orgSlug, outputKind) {
|
|
|
6270
6571
|
await outputSecurityPolicy(data, outputKind)
|
|
6271
6572
|
}
|
|
6272
6573
|
|
|
6273
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
6574
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$i } = constants
|
|
6274
6575
|
|
|
6275
6576
|
// TODO: secret toplevel alias `socket security policy`?
|
|
6276
6577
|
const config$k = {
|
|
@@ -6285,6 +6586,10 @@ const config$k = {
|
|
|
6285
6586
|
Usage
|
|
6286
6587
|
$ ${command} <org slug>
|
|
6287
6588
|
|
|
6589
|
+
API Token Requirements
|
|
6590
|
+
- Quota: 1 unit
|
|
6591
|
+
- Permissions: security-policy:read
|
|
6592
|
+
|
|
6288
6593
|
Options
|
|
6289
6594
|
${getFlagListOutput(config$k.flags, 6)}
|
|
6290
6595
|
|
|
@@ -6341,7 +6646,7 @@ async function run$k(argv, importMeta, { parentName }) {
|
|
|
6341
6646
|
return
|
|
6342
6647
|
}
|
|
6343
6648
|
if (cli.flags['dryRun']) {
|
|
6344
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
6649
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$i)
|
|
6345
6650
|
return
|
|
6346
6651
|
}
|
|
6347
6652
|
await handleSecurityPolicy(
|
|
@@ -6389,7 +6694,6 @@ async function fetchQuota() {
|
|
|
6389
6694
|
spinner.successAndStop('Received organization quota response.')
|
|
6390
6695
|
if (!result.success) {
|
|
6391
6696
|
handleUnsuccessfulApiResponse('getQuota', result)
|
|
6392
|
-
return
|
|
6393
6697
|
}
|
|
6394
6698
|
return result.data
|
|
6395
6699
|
}
|
|
@@ -6428,7 +6732,7 @@ async function handleQuota(outputKind = 'text') {
|
|
|
6428
6732
|
await outputQuota(data, outputKind)
|
|
6429
6733
|
}
|
|
6430
6734
|
|
|
6431
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
6735
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$h } = constants
|
|
6432
6736
|
const config$j = {
|
|
6433
6737
|
commandName: 'quota',
|
|
6434
6738
|
description: 'List organizations associated with the API key used',
|
|
@@ -6481,7 +6785,7 @@ async function run$j(argv, importMeta, { parentName }) {
|
|
|
6481
6785
|
return
|
|
6482
6786
|
}
|
|
6483
6787
|
if (cli.flags['dryRun']) {
|
|
6484
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
6788
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$h)
|
|
6485
6789
|
return
|
|
6486
6790
|
}
|
|
6487
6791
|
await handleQuota(json ? 'json' : markdown ? 'markdown' : 'text')
|
|
@@ -6514,6 +6818,7 @@ const cmdOrganization = {
|
|
|
6514
6818
|
}
|
|
6515
6819
|
}
|
|
6516
6820
|
|
|
6821
|
+
const { SOCKET_CLI_ISSUES_URL } = constants
|
|
6517
6822
|
async function fetchPurlDeepScore(purl) {
|
|
6518
6823
|
const apiToken = shadowNpmInject.getDefaultToken()
|
|
6519
6824
|
if (!apiToken) {
|
|
@@ -6555,7 +6860,7 @@ async function fetchPurlDeepScore(purl) {
|
|
|
6555
6860
|
return JSON.parse(data)
|
|
6556
6861
|
} catch (e) {
|
|
6557
6862
|
throw new Error(
|
|
6558
|
-
|
|
6863
|
+
`Unable to parse JSON response from the Socket API.\nPlease report to ${SOCKET_CLI_ISSUES_URL}`
|
|
6559
6864
|
)
|
|
6560
6865
|
}
|
|
6561
6866
|
}
|
|
@@ -6748,7 +7053,7 @@ async function outputPurlScore(purl, data, outputKind) {
|
|
|
6748
7053
|
)
|
|
6749
7054
|
} else {
|
|
6750
7055
|
logger.logger.log(
|
|
6751
|
-
'This package had no alerts and neither did any of its direct/transitive dependencies
|
|
7056
|
+
'This package had no alerts and neither did any of its direct/transitive dependencies'
|
|
6752
7057
|
)
|
|
6753
7058
|
}
|
|
6754
7059
|
logger.logger.log('')
|
|
@@ -6823,7 +7128,7 @@ function parsePackageSpecifiers(ecosystem, pkgs) {
|
|
|
6823
7128
|
}
|
|
6824
7129
|
}
|
|
6825
7130
|
|
|
6826
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
7131
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$g } = constants
|
|
6827
7132
|
const config$i = {
|
|
6828
7133
|
commandName: 'score',
|
|
6829
7134
|
description:
|
|
@@ -6837,13 +7142,13 @@ const config$i = {
|
|
|
6837
7142
|
Usage
|
|
6838
7143
|
$ ${command} <<ecosystem> <name> | <purl>>
|
|
6839
7144
|
|
|
7145
|
+
API Token Requirements
|
|
7146
|
+
- Quota: 100 units
|
|
7147
|
+
- Permissions: packages:list
|
|
7148
|
+
|
|
6840
7149
|
Options
|
|
6841
7150
|
${getFlagListOutput(config.flags, 6)}
|
|
6842
7151
|
|
|
6843
|
-
Requirements
|
|
6844
|
-
- quota: 100
|
|
6845
|
-
- scope: \`packages:list\`
|
|
6846
|
-
|
|
6847
7152
|
Show deep scoring details for one package. The score will reflect the package
|
|
6848
7153
|
itself, any of its dependencies, and any of its transitive dependencies.
|
|
6849
7154
|
|
|
@@ -6915,7 +7220,7 @@ async function run$i(argv, importMeta, { parentName }) {
|
|
|
6915
7220
|
return
|
|
6916
7221
|
}
|
|
6917
7222
|
if (cli.flags['dryRun']) {
|
|
6918
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
7223
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$g)
|
|
6919
7224
|
return
|
|
6920
7225
|
}
|
|
6921
7226
|
await handlePurlDeepScore(
|
|
@@ -6939,10 +7244,6 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
6939
7244
|
sockSdk.batchPackageFetch(
|
|
6940
7245
|
{
|
|
6941
7246
|
alerts: 'true'
|
|
6942
|
-
// compact: false,
|
|
6943
|
-
// fixable: false,
|
|
6944
|
-
// licenseattrib: false,
|
|
6945
|
-
// licensedetails: false
|
|
6946
7247
|
},
|
|
6947
7248
|
{
|
|
6948
7249
|
components: purls.map(purl => ({
|
|
@@ -6955,7 +7256,6 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
6955
7256
|
spinner.successAndStop('Request completed')
|
|
6956
7257
|
if (!result.success) {
|
|
6957
7258
|
handleUnsuccessfulApiResponse('batchPackageFetch', result)
|
|
6958
|
-
return
|
|
6959
7259
|
}
|
|
6960
7260
|
return result
|
|
6961
7261
|
}
|
|
@@ -7112,7 +7412,7 @@ async function handlePurlsShallowScore({ outputKind, purls }) {
|
|
|
7112
7412
|
outputPurlsShallowScore(purls, packageData.data, outputKind)
|
|
7113
7413
|
}
|
|
7114
7414
|
|
|
7115
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
7415
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$f } = constants
|
|
7116
7416
|
const config$h = {
|
|
7117
7417
|
commandName: 'shallow',
|
|
7118
7418
|
description:
|
|
@@ -7126,13 +7426,13 @@ const config$h = {
|
|
|
7126
7426
|
Usage
|
|
7127
7427
|
$ ${command} <<ecosystem> <name> [<name> ...] | <purl> [<purl> ...]>
|
|
7128
7428
|
|
|
7429
|
+
API Token Requirements
|
|
7430
|
+
- Quota: 100 units
|
|
7431
|
+
- Permissions: packages:list
|
|
7432
|
+
|
|
7129
7433
|
Options
|
|
7130
7434
|
${getFlagListOutput(config.flags, 6)}
|
|
7131
7435
|
|
|
7132
|
-
Requirements
|
|
7133
|
-
- quota: 100
|
|
7134
|
-
- scope: \`packages:list\`
|
|
7135
|
-
|
|
7136
7436
|
Show scoring details for one or more packages purely based on their own package.
|
|
7137
7437
|
This means that any dependency scores are not reflected by the score. You can
|
|
7138
7438
|
use the \`socket package score <pkg>\` command to get its full transitive score.
|
|
@@ -7203,7 +7503,7 @@ async function run$h(argv, importMeta, { parentName }) {
|
|
|
7203
7503
|
return
|
|
7204
7504
|
}
|
|
7205
7505
|
if (cli.flags['dryRun']) {
|
|
7206
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
7506
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$f)
|
|
7207
7507
|
return
|
|
7208
7508
|
}
|
|
7209
7509
|
await handlePurlsShallowScore({
|
|
@@ -7256,7 +7556,7 @@ async function runRawNpm(argv) {
|
|
|
7256
7556
|
await spawnPromise
|
|
7257
7557
|
}
|
|
7258
7558
|
|
|
7259
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
7559
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$e, NPM } = constants
|
|
7260
7560
|
const config$g = {
|
|
7261
7561
|
commandName: 'raw-npm',
|
|
7262
7562
|
description: `Temporarily disable the Socket ${NPM} wrapper`,
|
|
@@ -7284,7 +7584,7 @@ async function run$g(argv, importMeta, { parentName }) {
|
|
|
7284
7584
|
parentName
|
|
7285
7585
|
})
|
|
7286
7586
|
if (cli.flags['dryRun']) {
|
|
7287
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
7587
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$e)
|
|
7288
7588
|
return
|
|
7289
7589
|
}
|
|
7290
7590
|
await runRawNpm(argv)
|
|
@@ -7306,7 +7606,7 @@ async function runRawNpx(argv) {
|
|
|
7306
7606
|
await spawnPromise
|
|
7307
7607
|
}
|
|
7308
7608
|
|
|
7309
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
7609
|
+
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$d, NPX } = constants
|
|
7310
7610
|
const config$f = {
|
|
7311
7611
|
commandName: 'raw-npx',
|
|
7312
7612
|
description: `Temporarily disable the Socket ${NPX} wrapper`,
|
|
@@ -7334,242 +7634,12 @@ async function run$f(argv, importMeta, { parentName }) {
|
|
|
7334
7634
|
parentName
|
|
7335
7635
|
})
|
|
7336
7636
|
if (cli.flags['dryRun']) {
|
|
7337
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
7637
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$d)
|
|
7338
7638
|
return
|
|
7339
7639
|
}
|
|
7340
7640
|
await runRawNpx(argv)
|
|
7341
7641
|
}
|
|
7342
7642
|
|
|
7343
|
-
const { DRY_RUN_LABEL } = constants
|
|
7344
|
-
async function createReport(socketConfig, inputPaths, { cwd, dryRun }) {
|
|
7345
|
-
// Lazily access constants.spinner.
|
|
7346
|
-
const { spinner } = constants
|
|
7347
|
-
const sockSdk = await shadowNpmInject.setupSdk()
|
|
7348
|
-
const supportedFiles = await sockSdk
|
|
7349
|
-
.getReportSupportedFiles()
|
|
7350
|
-
.then(res => {
|
|
7351
|
-
if (!res.success) {
|
|
7352
|
-
handleUnsuccessfulApiResponse('getReportSupportedFiles', res)
|
|
7353
|
-
}
|
|
7354
|
-
return res.data
|
|
7355
|
-
})
|
|
7356
|
-
.catch(cause => {
|
|
7357
|
-
throw new Error('Failed getting supported files for report', {
|
|
7358
|
-
cause
|
|
7359
|
-
})
|
|
7360
|
-
})
|
|
7361
|
-
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(
|
|
7362
|
-
cwd,
|
|
7363
|
-
inputPaths,
|
|
7364
|
-
supportedFiles,
|
|
7365
|
-
socketConfig
|
|
7366
|
-
)
|
|
7367
|
-
const packagePathsCount = packagePaths.length
|
|
7368
|
-
if (packagePathsCount && debug.isDebug()) {
|
|
7369
|
-
for (const pkgPath of packagePaths) {
|
|
7370
|
-
debug.debugLog(`Uploading: ${pkgPath}`)
|
|
7371
|
-
}
|
|
7372
|
-
}
|
|
7373
|
-
if (dryRun) {
|
|
7374
|
-
debug.debugLog(`${DRY_RUN_LABEL}: Skipped actual upload`)
|
|
7375
|
-
return undefined
|
|
7376
|
-
}
|
|
7377
|
-
spinner.start(
|
|
7378
|
-
`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`
|
|
7379
|
-
)
|
|
7380
|
-
const apiCall = sockSdk.createReportFromFilePaths(
|
|
7381
|
-
packagePaths,
|
|
7382
|
-
cwd,
|
|
7383
|
-
socketConfig?.issueRules
|
|
7384
|
-
)
|
|
7385
|
-
const result = await handleApiCall(apiCall, 'creating report')
|
|
7386
|
-
if (!result.success) {
|
|
7387
|
-
handleUnsuccessfulApiResponse('createReport', result)
|
|
7388
|
-
return undefined
|
|
7389
|
-
}
|
|
7390
|
-
spinner.successAndStop()
|
|
7391
|
-
return result
|
|
7392
|
-
}
|
|
7393
|
-
|
|
7394
|
-
async function getSocketConfig(absoluteConfigPath) {
|
|
7395
|
-
const socketConfig = await config$K
|
|
7396
|
-
.readSocketConfig(absoluteConfigPath)
|
|
7397
|
-
.catch(cause => {
|
|
7398
|
-
if (
|
|
7399
|
-
cause &&
|
|
7400
|
-
typeof cause === 'object' &&
|
|
7401
|
-
cause instanceof config$K.SocketValidationError
|
|
7402
|
-
) {
|
|
7403
|
-
// Inspired by workbox-build:
|
|
7404
|
-
// https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
|
|
7405
|
-
const betterErrors = betterAjvErrors.betterAjvErrors({
|
|
7406
|
-
basePath: 'config',
|
|
7407
|
-
data: cause.data,
|
|
7408
|
-
errors: cause.validationErrors,
|
|
7409
|
-
schema: cause.schema
|
|
7410
|
-
})
|
|
7411
|
-
throw new shadowNpmInject.InputError(
|
|
7412
|
-
'The socket.yml config is not valid',
|
|
7413
|
-
betterErrors
|
|
7414
|
-
.map(
|
|
7415
|
-
err =>
|
|
7416
|
-
`[${err.path}] ${err.message}.${err.suggestion ? err.suggestion : ''}`
|
|
7417
|
-
)
|
|
7418
|
-
.join('\n')
|
|
7419
|
-
)
|
|
7420
|
-
} else {
|
|
7421
|
-
throw new Error('Failed to read socket.yml config', {
|
|
7422
|
-
cause
|
|
7423
|
-
})
|
|
7424
|
-
}
|
|
7425
|
-
})
|
|
7426
|
-
return socketConfig
|
|
7427
|
-
}
|
|
7428
|
-
|
|
7429
|
-
const MAX_TIMEOUT_RETRY = 5
|
|
7430
|
-
const HTTP_CODE_TIMEOUT = 524
|
|
7431
|
-
async function fetchReportData$1(reportId, includeAllIssues, strict) {
|
|
7432
|
-
// Lazily access constants.spinner.
|
|
7433
|
-
const { spinner } = constants
|
|
7434
|
-
spinner.log('Fetching report with ID ${reportId} (this could take a while)')
|
|
7435
|
-
spinner.start(`Fetch started... (this could take a while)`)
|
|
7436
|
-
const sockSdk = await shadowNpmInject.setupSdk()
|
|
7437
|
-
let result
|
|
7438
|
-
for (let retry = 1; !result; ++retry) {
|
|
7439
|
-
try {
|
|
7440
|
-
// eslint-disable-next-line no-await-in-loop
|
|
7441
|
-
result = await handleApiCall(
|
|
7442
|
-
sockSdk.getReport(reportId),
|
|
7443
|
-
'fetching report'
|
|
7444
|
-
)
|
|
7445
|
-
} catch (err) {
|
|
7446
|
-
if (
|
|
7447
|
-
retry >= MAX_TIMEOUT_RETRY ||
|
|
7448
|
-
!(err instanceof Error) ||
|
|
7449
|
-
err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT
|
|
7450
|
-
) {
|
|
7451
|
-
spinner.stop(`Failed to fetch report`)
|
|
7452
|
-
throw err
|
|
7453
|
-
}
|
|
7454
|
-
spinner.fail(`Retrying report fetch ${retry} / ${MAX_TIMEOUT_RETRY}`)
|
|
7455
|
-
}
|
|
7456
|
-
}
|
|
7457
|
-
if (!result.success) {
|
|
7458
|
-
return handleUnsuccessfulApiResponse('getReport', result)
|
|
7459
|
-
}
|
|
7460
|
-
|
|
7461
|
-
// Conclude the status of the API call.
|
|
7462
|
-
if (strict) {
|
|
7463
|
-
if (result.data.healthy) {
|
|
7464
|
-
spinner.success('Report result is healthy and great!')
|
|
7465
|
-
} else {
|
|
7466
|
-
spinner.error('Report result deemed unhealthy for project')
|
|
7467
|
-
}
|
|
7468
|
-
} else if (!result.data.healthy) {
|
|
7469
|
-
const severityCount = shadowNpmInject.getSeverityCount(
|
|
7470
|
-
result.data.issues,
|
|
7471
|
-
includeAllIssues ? undefined : 'high'
|
|
7472
|
-
)
|
|
7473
|
-
const issueSummary = shadowNpmInject.formatSeverityCount(severityCount)
|
|
7474
|
-
spinner.success(`Report has these issues: ${issueSummary}`)
|
|
7475
|
-
} else {
|
|
7476
|
-
spinner.success('Report has no issues')
|
|
7477
|
-
}
|
|
7478
|
-
spinner.stop()
|
|
7479
|
-
return result.data
|
|
7480
|
-
}
|
|
7481
|
-
|
|
7482
|
-
function formatReportDataOutput(
|
|
7483
|
-
reportId,
|
|
7484
|
-
data,
|
|
7485
|
-
commandName,
|
|
7486
|
-
outputKind,
|
|
7487
|
-
strict,
|
|
7488
|
-
artifacts
|
|
7489
|
-
) {
|
|
7490
|
-
if (outputKind === 'json') {
|
|
7491
|
-
logger.logger.log(JSON.stringify(data, undefined, 2))
|
|
7492
|
-
} else {
|
|
7493
|
-
const format = new shadowNpmInject.ColorOrMarkdown(
|
|
7494
|
-
outputKind === 'markdown'
|
|
7495
|
-
)
|
|
7496
|
-
logger.logger.log(commonTags.stripIndents`
|
|
7497
|
-
Detailed info on socket.dev: ${format.hyperlink(reportId, data.url, {
|
|
7498
|
-
fallbackToUrl: true
|
|
7499
|
-
})}`)
|
|
7500
|
-
if (outputKind === 'print') {
|
|
7501
|
-
logger.logger.log(data)
|
|
7502
|
-
logger.logger.log(
|
|
7503
|
-
colors.dim(
|
|
7504
|
-
`Or rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`
|
|
7505
|
-
)
|
|
7506
|
-
)
|
|
7507
|
-
logger.logger.log('The scan:')
|
|
7508
|
-
logger.logger.log(artifacts)
|
|
7509
|
-
}
|
|
7510
|
-
}
|
|
7511
|
-
if (strict && !data.healthy) {
|
|
7512
|
-
|
|
7513
|
-
process$1.exit(1)
|
|
7514
|
-
}
|
|
7515
|
-
}
|
|
7516
|
-
|
|
7517
|
-
async function fetchScan(orgSlug, scanId) {
|
|
7518
|
-
const apiToken = shadowNpmInject.getDefaultToken()
|
|
7519
|
-
if (!apiToken) {
|
|
7520
|
-
throw new shadowNpmInject.AuthError(
|
|
7521
|
-
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
|
|
7522
|
-
)
|
|
7523
|
-
}
|
|
7524
|
-
|
|
7525
|
-
// Lazily access constants.spinner.
|
|
7526
|
-
const { spinner } = constants
|
|
7527
|
-
spinner.start('Fetching scan data...')
|
|
7528
|
-
const response = await queryApi(
|
|
7529
|
-
`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`,
|
|
7530
|
-
apiToken
|
|
7531
|
-
)
|
|
7532
|
-
spinner.successAndStop('Received response while fetching scan data.')
|
|
7533
|
-
if (!response.ok) {
|
|
7534
|
-
const err = await handleApiError(response.status)
|
|
7535
|
-
logger.logger.fail(
|
|
7536
|
-
failMsgWithBadge(response.statusText, `Fetch error: ${err}`)
|
|
7537
|
-
)
|
|
7538
|
-
return
|
|
7539
|
-
}
|
|
7540
|
-
|
|
7541
|
-
// This is nd-json; each line is a json object
|
|
7542
|
-
const jsons = await response.text()
|
|
7543
|
-
const lines = jsons.split('\n').filter(Boolean)
|
|
7544
|
-
const data = lines.map(line => {
|
|
7545
|
-
try {
|
|
7546
|
-
return JSON.parse(line)
|
|
7547
|
-
} catch {
|
|
7548
|
-
console.error(
|
|
7549
|
-
'At least one line item was returned that could not be parsed as JSON...'
|
|
7550
|
-
)
|
|
7551
|
-
return {}
|
|
7552
|
-
}
|
|
7553
|
-
})
|
|
7554
|
-
return data
|
|
7555
|
-
}
|
|
7556
|
-
|
|
7557
|
-
async function viewReport(reportId, { all, commandName, outputKind, strict }) {
|
|
7558
|
-
const result = await fetchReportData$1(reportId, all, strict)
|
|
7559
|
-
const artifacts = await fetchScan('socketdev', reportId)
|
|
7560
|
-
if (result) {
|
|
7561
|
-
formatReportDataOutput(
|
|
7562
|
-
reportId,
|
|
7563
|
-
result,
|
|
7564
|
-
commandName,
|
|
7565
|
-
outputKind,
|
|
7566
|
-
strict,
|
|
7567
|
-
artifacts
|
|
7568
|
-
)
|
|
7569
|
-
}
|
|
7570
|
-
}
|
|
7571
|
-
|
|
7572
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$e } = constants
|
|
7573
7643
|
const config$e = {
|
|
7574
7644
|
commandName: 'create',
|
|
7575
7645
|
description: '[Deprecated] Create a project report',
|
|
@@ -7601,57 +7671,17 @@ const cmdReportCreate = {
|
|
|
7601
7671
|
run: run$e
|
|
7602
7672
|
}
|
|
7603
7673
|
async function run$e(argv, importMeta, { parentName }) {
|
|
7604
|
-
|
|
7674
|
+
meowOrExit({
|
|
7605
7675
|
argv,
|
|
7606
7676
|
config: config$e,
|
|
7607
7677
|
importMeta,
|
|
7608
7678
|
parentName
|
|
7609
7679
|
})
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
const absoluteConfigPath = path$1.join(cwd, 'socket.yml')
|
|
7614
|
-
const dryRun = Boolean(cli.flags['dryRun'])
|
|
7615
|
-
const json = Boolean(cli.flags['json'])
|
|
7616
|
-
const markdown = Boolean(cli.flags['markdown'])
|
|
7617
|
-
const strict = Boolean(cli.flags['strict'])
|
|
7618
|
-
const includeAllIssues = Boolean(cli.flags['all'])
|
|
7619
|
-
const view = Boolean(cli.flags['view'])
|
|
7620
|
-
|
|
7621
|
-
// Note exiting earlier to skirt a hidden auth requirement
|
|
7622
|
-
if (cli.flags['dryRun']) {
|
|
7623
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$e)
|
|
7624
|
-
return
|
|
7625
|
-
}
|
|
7626
|
-
const socketConfig = await getSocketConfig(absoluteConfigPath)
|
|
7627
|
-
const result = await createReport(socketConfig, cli.input, {
|
|
7628
|
-
cwd,
|
|
7629
|
-
dryRun
|
|
7630
|
-
})
|
|
7631
|
-
const commandName = `${parentName} ${config$e.commandName}`
|
|
7632
|
-
if (result?.success) {
|
|
7633
|
-
if (view) {
|
|
7634
|
-
const reportId = result.data.id
|
|
7635
|
-
await viewReport(reportId, {
|
|
7636
|
-
all: includeAllIssues,
|
|
7637
|
-
commandName,
|
|
7638
|
-
outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
|
|
7639
|
-
strict
|
|
7640
|
-
})
|
|
7641
|
-
} else if (json) {
|
|
7642
|
-
logger.logger.log(JSON.stringify(result.data, undefined, 2))
|
|
7643
|
-
} else {
|
|
7644
|
-
const format = new shadowNpmInject.ColorOrMarkdown(markdown)
|
|
7645
|
-
logger.logger.log(
|
|
7646
|
-
`New report: ${format.hyperlink(result.data.id, result.data.url, {
|
|
7647
|
-
fallbackToUrl: true
|
|
7648
|
-
})}`
|
|
7649
|
-
)
|
|
7650
|
-
}
|
|
7651
|
-
}
|
|
7680
|
+
logger.logger.fail(
|
|
7681
|
+
'This command has been sunset. Instead, please look at `socket scan create` to create scans and `socket scan report` to view a report of your scans.'
|
|
7682
|
+
)
|
|
7652
7683
|
}
|
|
7653
7684
|
|
|
7654
|
-
const { DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$d } = constants
|
|
7655
7685
|
const config$d = {
|
|
7656
7686
|
commandName: 'view',
|
|
7657
7687
|
description: '[Deprecated] View a project report',
|
|
@@ -7672,49 +7702,15 @@ const cmdReportView = {
|
|
|
7672
7702
|
run: run$d
|
|
7673
7703
|
}
|
|
7674
7704
|
async function run$d(argv, importMeta, { parentName }) {
|
|
7675
|
-
|
|
7705
|
+
meowOrExit({
|
|
7676
7706
|
argv,
|
|
7677
7707
|
config: config$d,
|
|
7678
7708
|
importMeta,
|
|
7679
7709
|
parentName
|
|
7680
7710
|
})
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
const wasBadInput = handleBadInput(
|
|
7684
|
-
{
|
|
7685
|
-
test: reportId,
|
|
7686
|
-
message: 'Need at least one report ID',
|
|
7687
|
-
pass: 'ok',
|
|
7688
|
-
fail: 'missing'
|
|
7689
|
-
},
|
|
7690
|
-
{
|
|
7691
|
-
nook: true,
|
|
7692
|
-
test: extraInput.length === 0,
|
|
7693
|
-
message: 'Can only handle a single report ID',
|
|
7694
|
-
pass: 'ok',
|
|
7695
|
-
fail: 'received ' + (extraInput.length + 1)
|
|
7696
|
-
},
|
|
7697
|
-
{
|
|
7698
|
-
nook: true,
|
|
7699
|
-
test: !json || !markdown,
|
|
7700
|
-
message: 'The json and markdown flags cannot be both set, pick one',
|
|
7701
|
-
pass: 'ok',
|
|
7702
|
-
fail: 'omit one'
|
|
7703
|
-
}
|
|
7711
|
+
logger.logger.fail(
|
|
7712
|
+
'This command has been sunset. Instead, please look at `socket scan create` to create scans and `socket scan report` to view a report of your scans.'
|
|
7704
7713
|
)
|
|
7705
|
-
if (wasBadInput) {
|
|
7706
|
-
return
|
|
7707
|
-
}
|
|
7708
|
-
if (cli.flags['dryRun']) {
|
|
7709
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$d)
|
|
7710
|
-
return
|
|
7711
|
-
}
|
|
7712
|
-
await viewReport(reportId, {
|
|
7713
|
-
all: Boolean(cli.flags['all']),
|
|
7714
|
-
commandName: `${parentName} ${config$d.commandName}`,
|
|
7715
|
-
outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
|
|
7716
|
-
strict: Boolean(cli.flags['strict'])
|
|
7717
|
-
})
|
|
7718
7714
|
}
|
|
7719
7715
|
|
|
7720
7716
|
const description$2 = '[Deprecated] Project report related commands'
|
|
@@ -7764,7 +7760,6 @@ async function fetchCreateRepo({
|
|
|
7764
7760
|
spinner.successAndStop('Received response requesting to create a repository.')
|
|
7765
7761
|
if (!result.success) {
|
|
7766
7762
|
handleUnsuccessfulApiResponse('createOrgRepo', result)
|
|
7767
|
-
return
|
|
7768
7763
|
}
|
|
7769
7764
|
return result.data
|
|
7770
7765
|
}
|
|
@@ -7837,6 +7832,10 @@ const config$c = {
|
|
|
7837
7832
|
Usage
|
|
7838
7833
|
$ ${command} <org slug>
|
|
7839
7834
|
|
|
7835
|
+
API Token Requirements
|
|
7836
|
+
- Quota: 1 unit
|
|
7837
|
+
- Permissions: repo:create
|
|
7838
|
+
|
|
7840
7839
|
Options
|
|
7841
7840
|
${getFlagListOutput(config.flags, 6)}
|
|
7842
7841
|
|
|
@@ -7912,7 +7911,6 @@ async function handleDeleteRepo(orgSlug, repoName) {
|
|
|
7912
7911
|
)
|
|
7913
7912
|
if (!result.success) {
|
|
7914
7913
|
handleUnsuccessfulApiResponse('deleteOrgRepo', result)
|
|
7915
|
-
return
|
|
7916
7914
|
}
|
|
7917
7915
|
spinner.successAndStop('Repository deleted successfully')
|
|
7918
7916
|
}
|
|
@@ -7929,6 +7927,10 @@ const config$b = {
|
|
|
7929
7927
|
Usage
|
|
7930
7928
|
$ ${command} <org slug> <repo slug>
|
|
7931
7929
|
|
|
7930
|
+
API Token Requirements
|
|
7931
|
+
- Quota: 1 unit
|
|
7932
|
+
- Permissions: repo:delete
|
|
7933
|
+
|
|
7932
7934
|
Options
|
|
7933
7935
|
${getFlagListOutput(config.flags, 6)}
|
|
7934
7936
|
|
|
@@ -8003,7 +8005,6 @@ async function fetchListRepos({ direction, orgSlug, page, per_page, sort }) {
|
|
|
8003
8005
|
spinner.successAndStop('Received response for repository list.')
|
|
8004
8006
|
if (!result.success) {
|
|
8005
8007
|
handleUnsuccessfulApiResponse('getOrgRepoList', result)
|
|
8006
|
-
return
|
|
8007
8008
|
}
|
|
8008
8009
|
return result.data
|
|
8009
8010
|
}
|
|
@@ -8105,6 +8106,10 @@ const config$a = {
|
|
|
8105
8106
|
Usage
|
|
8106
8107
|
$ ${command} <org slug>
|
|
8107
8108
|
|
|
8109
|
+
API Token Requirements
|
|
8110
|
+
- Quota: 1 unit
|
|
8111
|
+
- Permissions: repo:list
|
|
8112
|
+
|
|
8108
8113
|
Options
|
|
8109
8114
|
${getFlagListOutput(config.flags, 6)}
|
|
8110
8115
|
|
|
@@ -8197,7 +8202,6 @@ async function fetchUpdateRepo({
|
|
|
8197
8202
|
spinner.successAndStop('Received response trying to update a repository')
|
|
8198
8203
|
if (!result.success) {
|
|
8199
8204
|
handleUnsuccessfulApiResponse('updateOrgRepo', result)
|
|
8200
|
-
return
|
|
8201
8205
|
}
|
|
8202
8206
|
return result.data
|
|
8203
8207
|
}
|
|
@@ -8270,6 +8274,10 @@ const config$9 = {
|
|
|
8270
8274
|
Usage
|
|
8271
8275
|
$ ${command} <org slug>
|
|
8272
8276
|
|
|
8277
|
+
API Token Requirements
|
|
8278
|
+
- Quota: 1 unit
|
|
8279
|
+
- Permissions: repo:update
|
|
8280
|
+
|
|
8273
8281
|
Options
|
|
8274
8282
|
${getFlagListOutput(config.flags, 6)}
|
|
8275
8283
|
|
|
@@ -8346,7 +8354,6 @@ async function fetchViewRepo(orgSlug, repoName) {
|
|
|
8346
8354
|
spinner.successAndStop('Received response while fetched repository data.')
|
|
8347
8355
|
if (!result.success) {
|
|
8348
8356
|
handleUnsuccessfulApiResponse('getOrgRepo', result)
|
|
8349
|
-
return
|
|
8350
8357
|
}
|
|
8351
8358
|
return result.data
|
|
8352
8359
|
}
|
|
@@ -8441,6 +8448,10 @@ const config$8 = {
|
|
|
8441
8448
|
Usage
|
|
8442
8449
|
$ ${command} <org slug>
|
|
8443
8450
|
|
|
8451
|
+
API Token Requirements
|
|
8452
|
+
- Quota: 1 unit
|
|
8453
|
+
- Permissions: repo:list
|
|
8454
|
+
|
|
8444
8455
|
Options
|
|
8445
8456
|
${getFlagListOutput(config.flags, 6)}
|
|
8446
8457
|
|
|
@@ -8546,7 +8557,9 @@ async function fetchCreateOrgFullScan(
|
|
|
8546
8557
|
|
|
8547
8558
|
// Lazily access constants.spinner.
|
|
8548
8559
|
const { spinner } = constants
|
|
8549
|
-
spinner.start(
|
|
8560
|
+
spinner.start(
|
|
8561
|
+
`Sending request to create a scan with ${packagePaths.length} packages...`
|
|
8562
|
+
)
|
|
8550
8563
|
const result = await handleApiCall(
|
|
8551
8564
|
sockSdk.createOrgFullScan(
|
|
8552
8565
|
orgSlug,
|
|
@@ -8563,10 +8576,9 @@ async function fetchCreateOrgFullScan(
|
|
|
8563
8576
|
),
|
|
8564
8577
|
'Creating scan'
|
|
8565
8578
|
)
|
|
8566
|
-
spinner.successAndStop('
|
|
8579
|
+
spinner.successAndStop('Completed request to create a new scan.')
|
|
8567
8580
|
if (!result.success) {
|
|
8568
8581
|
handleUnsuccessfulApiResponse('CreateOrgFullScan', result)
|
|
8569
|
-
return
|
|
8570
8582
|
}
|
|
8571
8583
|
return result.data
|
|
8572
8584
|
}
|
|
@@ -8581,12 +8593,12 @@ async function fetchSupportedScanFileNames() {
|
|
|
8581
8593
|
sockSdk.getReportSupportedFiles(),
|
|
8582
8594
|
'fetching supported scan file types'
|
|
8583
8595
|
)
|
|
8584
|
-
spinner.
|
|
8596
|
+
spinner.stop()
|
|
8597
|
+
logger.logger.success(
|
|
8585
8598
|
'Received response while fetched supported scan file types.'
|
|
8586
8599
|
)
|
|
8587
8600
|
if (!result.success) {
|
|
8588
8601
|
handleUnsuccessfulApiResponse('getReportSupportedFiles', result)
|
|
8589
|
-
return
|
|
8590
8602
|
}
|
|
8591
8603
|
return result.data
|
|
8592
8604
|
}
|
|
@@ -8624,7 +8636,6 @@ async function handleCreateNewScan({
|
|
|
8624
8636
|
cwd,
|
|
8625
8637
|
targets,
|
|
8626
8638
|
supportedFileNames
|
|
8627
|
-
// socketConfig
|
|
8628
8639
|
)
|
|
8629
8640
|
handleBadInput({
|
|
8630
8641
|
nook: true,
|
|
@@ -8688,7 +8699,7 @@ async function suggestOrgSlug() {
|
|
|
8688
8699
|
}
|
|
8689
8700
|
} else {
|
|
8690
8701
|
logger.logger.fail(
|
|
8691
|
-
'Failed to lookup organization list from API, unable to suggest
|
|
8702
|
+
'Failed to lookup organization list from API, unable to suggest'
|
|
8692
8703
|
)
|
|
8693
8704
|
}
|
|
8694
8705
|
}
|
|
@@ -8943,6 +8954,10 @@ const config$7 = {
|
|
|
8943
8954
|
Usage
|
|
8944
8955
|
$ ${command} [...options] <org> <TARGET> [TARGET...]
|
|
8945
8956
|
|
|
8957
|
+
API Token Requirements
|
|
8958
|
+
- Quota: 1 unit
|
|
8959
|
+
- Permissions: full-scans:create
|
|
8960
|
+
|
|
8946
8961
|
Uploads the specified "package.json" and lock files for JavaScript, Python,
|
|
8947
8962
|
Go, Scala, Gradle, and Kotlin dependency manifests.
|
|
8948
8963
|
If any folder is specified, the ones found in there recursively are uploaded.
|
|
@@ -8984,7 +8999,7 @@ async function run$7(argv, importMeta, { parentName }) {
|
|
|
8984
8999
|
cwdOverride && cwdOverride !== 'process.cwd()'
|
|
8985
9000
|
? String(cwdOverride)
|
|
8986
9001
|
: process.cwd()
|
|
8987
|
-
let { branch: branchName, repo: repoName } = cli.flags
|
|
9002
|
+
let { branch: branchName = '', repo: repoName = '' } = cli.flags
|
|
8988
9003
|
|
|
8989
9004
|
// We're going to need an api token to suggest data because those suggestions
|
|
8990
9005
|
// must come from data we already know. Don't error on missing api token yet.
|
|
@@ -9112,7 +9127,6 @@ async function fetchDeleteOrgFullScan(orgSlug, scanId) {
|
|
|
9112
9127
|
spinner.successAndStop('Received response for deleting a scan.')
|
|
9113
9128
|
if (!result.success) {
|
|
9114
9129
|
handleUnsuccessfulApiResponse('deleteOrgFullScan', result)
|
|
9115
|
-
return
|
|
9116
9130
|
}
|
|
9117
9131
|
return result.data
|
|
9118
9132
|
}
|
|
@@ -9142,6 +9156,10 @@ const config$6 = {
|
|
|
9142
9156
|
Usage
|
|
9143
9157
|
$ ${command} <org slug> <scan ID>
|
|
9144
9158
|
|
|
9159
|
+
API Token Requirements
|
|
9160
|
+
- Quota: 1 unit
|
|
9161
|
+
- Permissions: full-scans:delete
|
|
9162
|
+
|
|
9145
9163
|
Options
|
|
9146
9164
|
${getFlagListOutput(config.flags, 6)}
|
|
9147
9165
|
|
|
@@ -9224,7 +9242,6 @@ async function fetchListScans({
|
|
|
9224
9242
|
spinner.successAndStop(`Received response for list of scans.`)
|
|
9225
9243
|
if (!result.success) {
|
|
9226
9244
|
handleUnsuccessfulApiResponse('getOrgFullScanList', result)
|
|
9227
|
-
return
|
|
9228
9245
|
}
|
|
9229
9246
|
return result.data
|
|
9230
9247
|
}
|
|
@@ -9345,6 +9362,10 @@ const config$5 = {
|
|
|
9345
9362
|
Usage
|
|
9346
9363
|
$ ${command} <org slug>
|
|
9347
9364
|
|
|
9365
|
+
API Token Requirements
|
|
9366
|
+
- Quota: 1 unit
|
|
9367
|
+
- Permissions: full-scans:list
|
|
9368
|
+
|
|
9348
9369
|
Options
|
|
9349
9370
|
${getFlagListOutput(config.flags, 6)}
|
|
9350
9371
|
|
|
@@ -9423,7 +9444,6 @@ async function fetchScanMetadata(orgSlug, scanId) {
|
|
|
9423
9444
|
spinner.successAndStop('Received response for scan meta data.')
|
|
9424
9445
|
if (!result.success) {
|
|
9425
9446
|
handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result)
|
|
9426
|
-
return
|
|
9427
9447
|
}
|
|
9428
9448
|
return result.data
|
|
9429
9449
|
}
|
|
@@ -9485,6 +9505,10 @@ const config$4 = {
|
|
|
9485
9505
|
Usage
|
|
9486
9506
|
$ ${command} <org slug> <scan id>
|
|
9487
9507
|
|
|
9508
|
+
API Token Requirements
|
|
9509
|
+
- Quota: 1 unit
|
|
9510
|
+
- Permissions: full-scans:list
|
|
9511
|
+
|
|
9488
9512
|
Options
|
|
9489
9513
|
${getFlagListOutput(config.flags, 6)}
|
|
9490
9514
|
|
|
@@ -9556,14 +9580,8 @@ async function run$4(argv, importMeta, { parentName }) {
|
|
|
9556
9580
|
/**
|
|
9557
9581
|
* This fetches all the relevant pieces of data to generate a report, given a
|
|
9558
9582
|
* full scan ID.
|
|
9559
|
-
* It can optionally only fetch the security or license side of things.
|
|
9560
9583
|
*/
|
|
9561
|
-
async function fetchReportData(
|
|
9562
|
-
orgSlug,
|
|
9563
|
-
scanId,
|
|
9564
|
-
// includeLicensePolicy: boolean,
|
|
9565
|
-
includeSecurityPolicy
|
|
9566
|
-
) {
|
|
9584
|
+
async function fetchReportData(orgSlug, scanId, includeLicensePolicy) {
|
|
9567
9585
|
const apiToken = shadowNpmInject.getDefaultToken()
|
|
9568
9586
|
if (!apiToken) {
|
|
9569
9587
|
throw new shadowNpmInject.AuthError(
|
|
@@ -9572,7 +9590,6 @@ async function fetchReportData(
|
|
|
9572
9590
|
}
|
|
9573
9591
|
const sockSdk = await shadowNpmInject.setupSdk(apiToken)
|
|
9574
9592
|
let haveScan = false
|
|
9575
|
-
// let haveLicensePolicy = false
|
|
9576
9593
|
let haveSecurityPolicy = false
|
|
9577
9594
|
|
|
9578
9595
|
// Lazily access constants.spinner.
|
|
@@ -9580,48 +9597,26 @@ async function fetchReportData(
|
|
|
9580
9597
|
function updateProgress() {
|
|
9581
9598
|
const needs = [
|
|
9582
9599
|
!haveScan ? 'scan' : undefined,
|
|
9583
|
-
|
|
9584
|
-
includeSecurityPolicy && !haveSecurityPolicy
|
|
9585
|
-
? 'security policy'
|
|
9586
|
-
: undefined
|
|
9600
|
+
!haveSecurityPolicy ? 'security policy' : undefined
|
|
9587
9601
|
].filter(Boolean)
|
|
9588
|
-
if (needs.length > 2) {
|
|
9589
|
-
// .toOxford()
|
|
9590
|
-
needs[needs.length - 1] = `and ${needs[needs.length - 1]}`
|
|
9591
|
-
}
|
|
9592
9602
|
const haves = [
|
|
9593
9603
|
haveScan ? 'scan' : undefined,
|
|
9594
|
-
|
|
9595
|
-
includeSecurityPolicy && haveSecurityPolicy
|
|
9596
|
-
? 'security policy'
|
|
9597
|
-
: undefined
|
|
9604
|
+
haveSecurityPolicy ? 'security policy' : undefined
|
|
9598
9605
|
].filter(Boolean)
|
|
9599
|
-
if (haves.length > 2) {
|
|
9600
|
-
// .toOxford()
|
|
9601
|
-
haves[haves.length - 1] = `and ${haves[haves.length - 1]}`
|
|
9602
|
-
}
|
|
9603
9606
|
if (needs.length) {
|
|
9604
9607
|
spinner.start(
|
|
9605
|
-
`Fetching ${needs.join(
|
|
9608
|
+
`Fetching ${needs.join(' and ')}...${haves.length ? ` Completed fetching ${haves.join(' and ')}.` : ''}`
|
|
9606
9609
|
)
|
|
9607
9610
|
} else {
|
|
9608
|
-
spinner.successAndStop(
|
|
9609
|
-
`Completed fetching ${haves.join(haves.length > 2 ? ', ' : ' and ')}.`
|
|
9610
|
-
)
|
|
9611
|
+
spinner.successAndStop(`Completed fetching ${haves.join(' and ')}.`)
|
|
9611
9612
|
}
|
|
9612
9613
|
}
|
|
9613
9614
|
updateProgress()
|
|
9614
|
-
|
|
9615
|
-
// @ts-ignore
|
|
9616
|
-
const [
|
|
9617
|
-
scan,
|
|
9618
|
-
// licensePolicyMaybe,
|
|
9619
|
-
securityPolicyMaybe
|
|
9620
|
-
] = await Promise.all([
|
|
9615
|
+
const [scan, securityPolicyMaybe] = await Promise.all([
|
|
9621
9616
|
(async () => {
|
|
9622
9617
|
try {
|
|
9623
9618
|
const response = await queryApi(
|
|
9624
|
-
`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`,
|
|
9619
|
+
`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}${includeLicensePolicy ? '?include_license_details=true' : ''}`,
|
|
9625
9620
|
apiToken
|
|
9626
9621
|
)
|
|
9627
9622
|
haveScan = true
|
|
@@ -9647,32 +9642,16 @@ async function fetchReportData(
|
|
|
9647
9642
|
})
|
|
9648
9643
|
return data
|
|
9649
9644
|
} catch (e) {
|
|
9650
|
-
spinner.errorAndStop(
|
|
9651
|
-
'There was an issue while fetching full scan data.'
|
|
9652
|
-
)
|
|
9645
|
+
spinner.errorAndStop('There was an issue while fetching full scan data')
|
|
9653
9646
|
throw e
|
|
9654
9647
|
}
|
|
9655
9648
|
})(),
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
// r,
|
|
9663
|
-
// "looking up organization's license policy"
|
|
9664
|
-
// )
|
|
9665
|
-
// })(),
|
|
9666
|
-
includeSecurityPolicy &&
|
|
9667
|
-
(async () => {
|
|
9668
|
-
const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
9669
|
-
haveSecurityPolicy = true
|
|
9670
|
-
updateProgress()
|
|
9671
|
-
return await handleApiCall(
|
|
9672
|
-
r,
|
|
9673
|
-
"looking up organization's security policy"
|
|
9674
|
-
)
|
|
9675
|
-
})()
|
|
9649
|
+
(async () => {
|
|
9650
|
+
const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
9651
|
+
haveSecurityPolicy = true
|
|
9652
|
+
updateProgress()
|
|
9653
|
+
return await handleApiCall(r, "looking up organization's security policy")
|
|
9654
|
+
})()
|
|
9676
9655
|
]).finally(() => spinner.stop())
|
|
9677
9656
|
if (!Array.isArray(scan)) {
|
|
9678
9657
|
logger.logger.error('Was unable to fetch scan, bailing')
|
|
@@ -9680,55 +9659,30 @@ async function fetchReportData(
|
|
|
9680
9659
|
return {
|
|
9681
9660
|
ok: false,
|
|
9682
9661
|
scan: undefined,
|
|
9683
|
-
// licensePolicy: undefined,
|
|
9684
9662
|
securityPolicy: undefined
|
|
9685
9663
|
}
|
|
9686
9664
|
}
|
|
9687
|
-
|
|
9688
|
-
// // Note: security->license once the api ships in the sdk
|
|
9689
|
-
// let licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'> =
|
|
9690
|
-
// undefined
|
|
9691
|
-
// if (includeLicensePolicy) {
|
|
9692
|
-
// if (licensePolicyMaybe && licensePolicyMaybe.success) {
|
|
9693
|
-
// licensePolicy = licensePolicyMaybe
|
|
9694
|
-
// } else {
|
|
9695
|
-
// logger.error('Was unable to fetch license policy, bailing')
|
|
9696
|
-
// process.exitCode = 1
|
|
9697
|
-
// return {
|
|
9698
|
-
// ok: false,
|
|
9699
|
-
// scan: undefined,
|
|
9700
|
-
// licensePolicy: undefined,
|
|
9701
|
-
// securityPolicy: undefined
|
|
9702
|
-
// }
|
|
9703
|
-
// }
|
|
9704
|
-
// }
|
|
9705
|
-
|
|
9706
9665
|
let securityPolicy = undefined
|
|
9707
|
-
if (
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
// licensePolicy: undefined,
|
|
9717
|
-
securityPolicy: undefined
|
|
9718
|
-
}
|
|
9666
|
+
if (securityPolicyMaybe && securityPolicyMaybe.success) {
|
|
9667
|
+
securityPolicy = securityPolicyMaybe
|
|
9668
|
+
} else {
|
|
9669
|
+
logger.logger.error('Was unable to fetch security policy, bailing')
|
|
9670
|
+
process.exitCode = 1
|
|
9671
|
+
return {
|
|
9672
|
+
ok: false,
|
|
9673
|
+
scan: undefined,
|
|
9674
|
+
securityPolicy: undefined
|
|
9719
9675
|
}
|
|
9720
9676
|
}
|
|
9721
9677
|
return {
|
|
9722
9678
|
ok: true,
|
|
9723
9679
|
scan,
|
|
9724
|
-
// licensePolicy,
|
|
9725
9680
|
securityPolicy
|
|
9726
9681
|
}
|
|
9727
9682
|
}
|
|
9728
9683
|
|
|
9729
9684
|
function generateReport(
|
|
9730
9685
|
scan,
|
|
9731
|
-
_licensePolicy,
|
|
9732
9686
|
securityPolicy,
|
|
9733
9687
|
{ fold, orgSlug, reportLevel, scanId, short, spinner }
|
|
9734
9688
|
) {
|
|
@@ -9754,6 +9708,14 @@ function generateReport(
|
|
|
9754
9708
|
// - monitor/ignore: no action
|
|
9755
9709
|
// - defer: unknown (no action)
|
|
9756
9710
|
|
|
9711
|
+
// Note: the server will emit alerts for license policy violations but
|
|
9712
|
+
// those are only included if you set the flag when requesting the scan
|
|
9713
|
+
// data. The alerts map to a single security policy key that determines
|
|
9714
|
+
// what to do with any violation, regardless of the concrete license.
|
|
9715
|
+
// That rule is called "License Policy Violation".
|
|
9716
|
+
// The license policy part is implicitly handled here. Either they are
|
|
9717
|
+
// included and may show up, or they are not and won't show up.
|
|
9718
|
+
|
|
9757
9719
|
const violations = new Map()
|
|
9758
9720
|
let healthy = true
|
|
9759
9721
|
const securityRules = securityPolicy?.data.securityPolicyRules
|
|
@@ -10000,13 +9962,11 @@ function* walkNestedMap(map, keys = []) {
|
|
|
10000
9962
|
|
|
10001
9963
|
async function outputScanReport(
|
|
10002
9964
|
scan,
|
|
10003
|
-
// licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
|
|
10004
9965
|
securityPolicy,
|
|
10005
9966
|
{
|
|
10006
9967
|
filePath,
|
|
10007
9968
|
fold,
|
|
10008
9969
|
includeLicensePolicy,
|
|
10009
|
-
includeSecurityPolicy,
|
|
10010
9970
|
orgSlug,
|
|
10011
9971
|
outputKind,
|
|
10012
9972
|
reportLevel,
|
|
@@ -10014,25 +9974,15 @@ async function outputScanReport(
|
|
|
10014
9974
|
short
|
|
10015
9975
|
}
|
|
10016
9976
|
) {
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
{
|
|
10027
|
-
orgSlug,
|
|
10028
|
-
scanId,
|
|
10029
|
-
fold,
|
|
10030
|
-
reportLevel,
|
|
10031
|
-
short,
|
|
10032
|
-
// Lazily access constants.spinner.
|
|
10033
|
-
spinner: constants.spinner
|
|
10034
|
-
}
|
|
10035
|
-
)
|
|
9977
|
+
const scanReport = generateReport(scan, securityPolicy, {
|
|
9978
|
+
orgSlug,
|
|
9979
|
+
scanId,
|
|
9980
|
+
fold,
|
|
9981
|
+
reportLevel,
|
|
9982
|
+
short,
|
|
9983
|
+
// Lazily access constants.spinner.
|
|
9984
|
+
spinner: constants.spinner
|
|
9985
|
+
})
|
|
10036
9986
|
if (!scanReport.healthy) {
|
|
10037
9987
|
process.exitCode = 1
|
|
10038
9988
|
}
|
|
@@ -10040,7 +9990,9 @@ async function outputScanReport(
|
|
|
10040
9990
|
outputKind === 'json' ||
|
|
10041
9991
|
(outputKind === 'text' && filePath && filePath.endsWith('.json'))
|
|
10042
9992
|
) {
|
|
10043
|
-
const json = short
|
|
9993
|
+
const json = short
|
|
9994
|
+
? JSON.stringify(scanReport)
|
|
9995
|
+
: toJsonReport(scanReport, includeLicensePolicy)
|
|
10044
9996
|
if (filePath !== '-') {
|
|
10045
9997
|
logger.logger.log('Writing json report to', filePath)
|
|
10046
9998
|
return await fs.writeFile(filePath, json)
|
|
@@ -10051,7 +10003,7 @@ async function outputScanReport(
|
|
|
10051
10003
|
if (outputKind === 'markdown' || filePath.endsWith('.md')) {
|
|
10052
10004
|
const md = short
|
|
10053
10005
|
? `healthy = ${scanReport.healthy}`
|
|
10054
|
-
: toMarkdownReport(scanReport)
|
|
10006
|
+
: toMarkdownReport(scanReport, includeLicensePolicy)
|
|
10055
10007
|
if (filePath !== '-') {
|
|
10056
10008
|
logger.logger.log('Writing markdown report to', filePath)
|
|
10057
10009
|
return await fs.writeFile(filePath, md)
|
|
@@ -10067,10 +10019,11 @@ async function outputScanReport(
|
|
|
10067
10019
|
})
|
|
10068
10020
|
}
|
|
10069
10021
|
}
|
|
10070
|
-
function toJsonReport(report) {
|
|
10022
|
+
function toJsonReport(report, includeLicensePolicy) {
|
|
10071
10023
|
const obj = mapToObject(report.alerts)
|
|
10072
10024
|
const json = JSON.stringify(
|
|
10073
10025
|
{
|
|
10026
|
+
includeLicensePolicy,
|
|
10074
10027
|
...report,
|
|
10075
10028
|
alerts: obj
|
|
10076
10029
|
},
|
|
@@ -10079,7 +10032,7 @@ function toJsonReport(report) {
|
|
|
10079
10032
|
)
|
|
10080
10033
|
return json
|
|
10081
10034
|
}
|
|
10082
|
-
function toMarkdownReport(report) {
|
|
10035
|
+
function toMarkdownReport(report, includeLicensePolicy) {
|
|
10083
10036
|
const flatData = Array.from(walkNestedMap(report.alerts)).map(
|
|
10084
10037
|
({ keys, value }) => {
|
|
10085
10038
|
const { manifest, policy, type, url } = value
|
|
@@ -10098,11 +10051,11 @@ function toMarkdownReport(report) {
|
|
|
10098
10051
|
# Scan Policy Report
|
|
10099
10052
|
|
|
10100
10053
|
This report tells you whether the results of a Socket scan results violate the
|
|
10101
|
-
security or license policy set by your organization.
|
|
10054
|
+
security${includeLicensePolicy ? ' or license' : ''} policy set by your organization.
|
|
10102
10055
|
|
|
10103
10056
|
## Health status
|
|
10104
10057
|
|
|
10105
|
-
${report.healthy ?
|
|
10058
|
+
${report.healthy ? `The scan *PASSES* all requirements set by your security${includeLicensePolicy ? ' and license' : ''} policy.` : 'The scan *VIOLATES* one or more policies set to the "error" level.'}
|
|
10106
10059
|
|
|
10107
10060
|
## Settings
|
|
10108
10061
|
|
|
@@ -10112,6 +10065,7 @@ Configuration used to generate this report:
|
|
|
10112
10065
|
- Scan ID: ${report.scanId}
|
|
10113
10066
|
- Alert folding: ${report.options.fold === 'none' ? 'none' : `up to ${report.options.fold}`}
|
|
10114
10067
|
- Minimal policy level for alert to be included in report: ${report.options.reportLevel === 'defer' ? 'everything' : report.options.reportLevel}
|
|
10068
|
+
- Include license alerts: ${includeLicensePolicy ? 'yes' : 'no'}
|
|
10115
10069
|
|
|
10116
10070
|
## Alerts
|
|
10117
10071
|
|
|
@@ -10126,27 +10080,16 @@ async function handleScanReport({
|
|
|
10126
10080
|
filePath,
|
|
10127
10081
|
fold,
|
|
10128
10082
|
includeLicensePolicy,
|
|
10129
|
-
includeSecurityPolicy,
|
|
10130
10083
|
orgSlug,
|
|
10131
10084
|
outputKind,
|
|
10132
10085
|
reportLevel,
|
|
10133
10086
|
scanId,
|
|
10134
10087
|
short
|
|
10135
10088
|
}) {
|
|
10136
|
-
|
|
10137
|
-
process.exitCode = 1
|
|
10138
|
-
return // caller should assert
|
|
10139
|
-
}
|
|
10140
|
-
const {
|
|
10141
|
-
// licensePolicy,
|
|
10142
|
-
ok,
|
|
10143
|
-
scan,
|
|
10144
|
-
securityPolicy
|
|
10145
|
-
} = await fetchReportData(
|
|
10089
|
+
const { ok, scan, securityPolicy } = await fetchReportData(
|
|
10146
10090
|
orgSlug,
|
|
10147
10091
|
scanId,
|
|
10148
|
-
|
|
10149
|
-
includeSecurityPolicy
|
|
10092
|
+
includeLicensePolicy
|
|
10150
10093
|
)
|
|
10151
10094
|
if (!ok) {
|
|
10152
10095
|
return
|
|
@@ -10156,7 +10099,6 @@ async function handleScanReport({
|
|
|
10156
10099
|
fold,
|
|
10157
10100
|
scanId: scanId,
|
|
10158
10101
|
includeLicensePolicy,
|
|
10159
|
-
includeSecurityPolicy,
|
|
10160
10102
|
orgSlug,
|
|
10161
10103
|
outputKind,
|
|
10162
10104
|
reportLevel,
|
|
@@ -10169,8 +10111,7 @@ const config$3 = {
|
|
|
10169
10111
|
commandName: 'report',
|
|
10170
10112
|
description:
|
|
10171
10113
|
'Check whether a scan result passes the organizational policies (security, license)',
|
|
10172
|
-
hidden:
|
|
10173
|
-
// [beta]
|
|
10114
|
+
hidden: false,
|
|
10174
10115
|
flags: {
|
|
10175
10116
|
...commonFlags,
|
|
10176
10117
|
...outputFlags,
|
|
@@ -10189,31 +10130,23 @@ const config$3 = {
|
|
|
10189
10130
|
default: false,
|
|
10190
10131
|
description: 'Report only the healthy status'
|
|
10191
10132
|
},
|
|
10192
|
-
|
|
10193
|
-
// type: 'boolean',
|
|
10194
|
-
// default: true,
|
|
10195
|
-
// description: 'Report the license policy status. Default: true'
|
|
10196
|
-
// },
|
|
10197
|
-
security: {
|
|
10133
|
+
license: {
|
|
10198
10134
|
type: 'boolean',
|
|
10199
|
-
default:
|
|
10200
|
-
description: '
|
|
10135
|
+
default: false,
|
|
10136
|
+
description: 'Also report the license policy status. Default: false'
|
|
10201
10137
|
}
|
|
10202
10138
|
},
|
|
10203
10139
|
help: (command, config) => `
|
|
10204
10140
|
Usage
|
|
10205
10141
|
$ ${command} <org slug> <scan ID> [path to output file]
|
|
10206
10142
|
|
|
10143
|
+
API Token Requirements
|
|
10144
|
+
- Quota: 2 units
|
|
10145
|
+
- Permissions: full-scans:list security-policy:read
|
|
10146
|
+
|
|
10207
10147
|
Options
|
|
10208
10148
|
${getFlagListOutput(config.flags, 6)}
|
|
10209
10149
|
|
|
10210
|
-
This consumes 1 quota unit plus 1 for each of the requested policy types.
|
|
10211
|
-
|
|
10212
|
-
Note: By default it reports both so by default it consumes 3 quota units.
|
|
10213
|
-
|
|
10214
|
-
Your API token will need the \`full-scans:list\` scope regardless. Additionally
|
|
10215
|
-
it needs \`security-policy:read\` to report on the security policy.
|
|
10216
|
-
|
|
10217
10150
|
By default the result is a nested object that looks like this:
|
|
10218
10151
|
\`{[ecosystem]: {[pkgName]: {[version]: {[file]: {[type:loc]: policy}}}}\`
|
|
10219
10152
|
You can fold this up to given level: 'pkg', 'version', 'file', and 'none'.
|
|
@@ -10225,6 +10158,7 @@ const config$3 = {
|
|
|
10225
10158
|
|
|
10226
10159
|
Examples
|
|
10227
10160
|
$ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0 --json --fold=version
|
|
10161
|
+
$ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0 --license --markdown --short
|
|
10228
10162
|
`
|
|
10229
10163
|
}
|
|
10230
10164
|
const cmdScanReport = {
|
|
@@ -10242,10 +10176,9 @@ async function run$3(argv, importMeta, { parentName }) {
|
|
|
10242
10176
|
const {
|
|
10243
10177
|
fold = 'none',
|
|
10244
10178
|
json,
|
|
10245
|
-
|
|
10179
|
+
license,
|
|
10246
10180
|
markdown,
|
|
10247
|
-
reportLevel = 'warn'
|
|
10248
|
-
security
|
|
10181
|
+
reportLevel = 'warn'
|
|
10249
10182
|
} = cli.flags
|
|
10250
10183
|
const defaultOrgSlug = shadowNpmInject.getConfigValue('defaultOrg')
|
|
10251
10184
|
const orgSlug = defaultOrgSlug || cli.input[0] || ''
|
|
@@ -10292,9 +10225,7 @@ async function run$3(argv, importMeta, { parentName }) {
|
|
|
10292
10225
|
await handleScanReport({
|
|
10293
10226
|
orgSlug,
|
|
10294
10227
|
scanId: scanId,
|
|
10295
|
-
includeLicensePolicy:
|
|
10296
|
-
// !!license,
|
|
10297
|
-
includeSecurityPolicy: typeof security === 'boolean' ? security : true,
|
|
10228
|
+
includeLicensePolicy: !!license,
|
|
10298
10229
|
outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
|
|
10299
10230
|
filePath: file,
|
|
10300
10231
|
fold: fold,
|
|
@@ -10303,6 +10234,46 @@ async function run$3(argv, importMeta, { parentName }) {
|
|
|
10303
10234
|
})
|
|
10304
10235
|
}
|
|
10305
10236
|
|
|
10237
|
+
async function fetchScan(orgSlug, scanId) {
|
|
10238
|
+
const apiToken = shadowNpmInject.getDefaultToken()
|
|
10239
|
+
if (!apiToken) {
|
|
10240
|
+
throw new shadowNpmInject.AuthError(
|
|
10241
|
+
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
|
|
10242
|
+
)
|
|
10243
|
+
}
|
|
10244
|
+
|
|
10245
|
+
// Lazily access constants.spinner.
|
|
10246
|
+
const { spinner } = constants
|
|
10247
|
+
spinner.start('Fetching scan data...')
|
|
10248
|
+
const response = await queryApi(
|
|
10249
|
+
`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`,
|
|
10250
|
+
apiToken
|
|
10251
|
+
)
|
|
10252
|
+
spinner.successAndStop('Received response while fetching scan data.')
|
|
10253
|
+
if (!response.ok) {
|
|
10254
|
+
const err = await handleApiError(response.status)
|
|
10255
|
+
logger.logger.fail(
|
|
10256
|
+
failMsgWithBadge(response.statusText, `Fetch error: ${err}`)
|
|
10257
|
+
)
|
|
10258
|
+
return
|
|
10259
|
+
}
|
|
10260
|
+
|
|
10261
|
+
// This is nd-json; each line is a json object
|
|
10262
|
+
const jsons = await response.text()
|
|
10263
|
+
const lines = jsons.split('\n').filter(Boolean)
|
|
10264
|
+
const data = lines.map(line => {
|
|
10265
|
+
try {
|
|
10266
|
+
return JSON.parse(line)
|
|
10267
|
+
} catch {
|
|
10268
|
+
console.error(
|
|
10269
|
+
'At least one line item was returned that could not be parsed as JSON...'
|
|
10270
|
+
)
|
|
10271
|
+
return {}
|
|
10272
|
+
}
|
|
10273
|
+
})
|
|
10274
|
+
return data
|
|
10275
|
+
}
|
|
10276
|
+
|
|
10306
10277
|
async function outputScanView(artifacts, orgSlug, scanId, filePath) {
|
|
10307
10278
|
const display = artifacts.map(art => {
|
|
10308
10279
|
const author = Array.isArray(art.author)
|
|
@@ -10363,7 +10334,6 @@ async function streamScan(orgSlug, scanId, file) {
|
|
|
10363
10334
|
spinner.successAndStop(`Full scan details written to ${file}`)
|
|
10364
10335
|
if (!data?.success) {
|
|
10365
10336
|
handleUnsuccessfulApiResponse('getOrgFullScan', data)
|
|
10366
|
-
return
|
|
10367
10337
|
}
|
|
10368
10338
|
return data
|
|
10369
10339
|
}
|
|
@@ -10381,6 +10351,10 @@ const config$2 = {
|
|
|
10381
10351
|
Usage
|
|
10382
10352
|
$ ${command} <org slug> <scan ID> [path to output file]
|
|
10383
10353
|
|
|
10354
|
+
API Token Requirements
|
|
10355
|
+
- Quota: 1 unit
|
|
10356
|
+
- Permissions: full-scans:list
|
|
10357
|
+
|
|
10384
10358
|
When no output path is given the contents is sent to stdout.
|
|
10385
10359
|
|
|
10386
10360
|
Options
|
|
@@ -10730,6 +10704,11 @@ const config$1 = {
|
|
|
10730
10704
|
Usage
|
|
10731
10705
|
$ ${command}
|
|
10732
10706
|
|
|
10707
|
+
API Token Requirements
|
|
10708
|
+
- Quota: 1 unit
|
|
10709
|
+
- Permissions: threat-feed:list
|
|
10710
|
+
- Special access
|
|
10711
|
+
|
|
10733
10712
|
This feature requires a Threat Feed license. Please contact
|
|
10734
10713
|
sales@socket.dev if you are interested in purchasing this access.
|
|
10735
10714
|
|
|
@@ -10848,7 +10827,7 @@ function checkSocketWrapperSetup(file) {
|
|
|
10848
10827
|
)
|
|
10849
10828
|
if (linesWithSocketAlias.length) {
|
|
10850
10829
|
logger.logger.log(
|
|
10851
|
-
`The Socket npm/npx wrapper is set up in your bash profile (${file})
|
|
10830
|
+
`The Socket npm/npx wrapper is set up in your bash profile (${file})`
|
|
10852
10831
|
)
|
|
10853
10832
|
return true
|
|
10854
10833
|
}
|
|
@@ -11030,7 +11009,7 @@ void (async () => {
|
|
|
11030
11009
|
await vendor.updater({
|
|
11031
11010
|
name: SOCKET_CLI_BIN_NAME,
|
|
11032
11011
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
11033
|
-
version: '0.14.
|
|
11012
|
+
version: '0.14.70',
|
|
11034
11013
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
11035
11014
|
})
|
|
11036
11015
|
try {
|
|
@@ -11101,5 +11080,5 @@ void (async () => {
|
|
|
11101
11080
|
await shadowNpmInject.captureException(e)
|
|
11102
11081
|
}
|
|
11103
11082
|
})()
|
|
11104
|
-
//# debugId=
|
|
11083
|
+
//# debugId=f17b556c-de1f-4885-9463-ba44d3fdf9c
|
|
11105
11084
|
//# sourceMappingURL=cli.js.map
|