@socketsecurity/cli-with-sentry 1.14.0 → 1.15.0
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/CHANGELOG.md +18 -0
- package/README.md +31 -6
- package/dist/cli.js +355 -206
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +7 -4
- package/dist/constants.js.map +1 -1
- package/dist/manifest-scripts/dotnet-tool/socket-facts-dotnet.dll +0 -0
- package/dist/manifest-scripts/maven-extension/coana-maven-extension.jar +0 -0
- package/dist/shadow-npm-bin2.js +5 -2
- package/dist/shadow-npm-bin2.js.map +1 -1
- package/dist/shadow-pnpm-bin2.js +3 -2
- package/dist/shadow-pnpm-bin2.js.map +1 -1
- package/dist/shadow-yarn-bin.js +4 -2
- package/dist/shadow-yarn-bin.js.map +1 -1
- package/dist/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/types/commands/config/handle-config-set.d.mts.map +1 -1
- package/dist/types/commands/login/apply-login.d.mts.map +1 -1
- package/dist/types/commands/login/attempt-login.d.mts +5 -1
- package/dist/types/commands/login/attempt-login.d.mts.map +1 -1
- package/dist/types/commands/login/cmd-login.d.mts.map +1 -1
- package/dist/types/commands/logout/apply-logout.d.mts.map +1 -1
- package/dist/types/commands/logout/attempt-logout.d.mts +1 -1
- package/dist/types/commands/logout/attempt-logout.d.mts.map +1 -1
- package/dist/types/commands/manifest/bazel/bazel-socket-json-trust.d.mts +35 -0
- package/dist/types/commands/manifest/bazel/bazel-socket-json-trust.d.mts.map +1 -0
- package/dist/types/commands/manifest/bazel/cmd-manifest-bazel.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-report-data.d.mts +1 -8
- package/dist/types/commands/scan/fetch-report-data.d.mts.map +1 -1
- package/dist/types/commands/scan/generate-report.d.mts +1 -2
- package/dist/types/commands/scan/generate-report.d.mts.map +1 -1
- package/dist/types/commands/scan/output-scan-report.d.mts +0 -2
- package/dist/types/commands/scan/output-scan-report.d.mts.map +1 -1
- package/dist/types/constants.d.mts +4 -2
- package/dist/types/constants.d.mts.map +1 -1
- package/dist/types/shadow/npm-base.d.mts.map +1 -1
- package/dist/types/shadow/pnpm/bin.d.mts.map +1 -1
- package/dist/types/shadow/yarn/bin.d.mts.map +1 -1
- package/dist/types/utils/api-transport.d.mts +4 -0
- package/dist/types/utils/api-transport.d.mts.map +1 -0
- package/dist/types/utils/api.d.mts +2 -1
- package/dist/types/utils/api.d.mts.map +1 -1
- package/dist/types/utils/cmd.d.mts.map +1 -1
- package/dist/types/utils/coana-release.d.mts.map +1 -1
- package/dist/types/utils/config.d.mts +1 -0
- package/dist/types/utils/config.d.mts.map +1 -1
- package/dist/types/utils/oauth.d.mts +33 -0
- package/dist/types/utils/oauth.d.mts.map +1 -0
- package/dist/types/utils/package-manager.d.mts +2 -2
- package/dist/types/utils/package-manager.d.mts.map +1 -1
- package/dist/types/utils/sdk.d.mts +14 -6
- package/dist/types/utils/sdk.d.mts.map +1 -1
- package/dist/utils.js +809 -128
- package/dist/utils.js.map +1 -1
- package/dist/vendor.js +567 -567
- package/package.json +2 -2
- package/requirements.json +2 -2
package/dist/utils.js
CHANGED
|
@@ -26,7 +26,7 @@ var require$$11 = require('node:zlib');
|
|
|
26
26
|
var fs = require('../external/@socketsecurity/registry/lib/fs');
|
|
27
27
|
var url = require('../external/@socketsecurity/registry/lib/url');
|
|
28
28
|
var require$$1 = require('node:module');
|
|
29
|
-
var agent = require('../external/@socketsecurity/registry/lib/agent');
|
|
29
|
+
var agent$1 = require('../external/@socketsecurity/registry/lib/agent');
|
|
30
30
|
var bin = require('../external/@socketsecurity/registry/lib/bin');
|
|
31
31
|
var packages = require('../external/@socketsecurity/registry/lib/packages');
|
|
32
32
|
var os = require('node:os');
|
|
@@ -674,7 +674,7 @@ function normalizeConfigKey(key) {
|
|
|
674
674
|
// property apiKey, we'll copy that to apiToken and delete the old property.
|
|
675
675
|
// We added `org` as a convenience alias for `defaultOrg`
|
|
676
676
|
const normalizedKey = key === 'apiKey' ? constants.CONFIG_KEY_API_TOKEN : key === constants.CONFIG_KEY_ORG ? constants.CONFIG_KEY_DEFAULT_ORG : key;
|
|
677
|
-
if (!isSupportedConfigKey(normalizedKey)) {
|
|
677
|
+
if (normalizedKey !== constants.CONFIG_KEY_AUTH_TYPE && !isSupportedConfigKey(normalizedKey)) {
|
|
678
678
|
return {
|
|
679
679
|
ok: false,
|
|
680
680
|
message: `Invalid config key: ${normalizedKey}`,
|
|
@@ -969,6 +969,610 @@ function getRequirementsKey(cmdPath) {
|
|
|
969
969
|
return cmdPath.replace(/^socket[: ]/, '').replace(/ +/g, ':');
|
|
970
970
|
}
|
|
971
971
|
|
|
972
|
+
// Cached extra CA certificates for SSL_CERT_FILE support.
|
|
973
|
+
let extraCaCerts;
|
|
974
|
+
let extraCaCertsResolved = false;
|
|
975
|
+
|
|
976
|
+
// Node reads NODE_EXTRA_CA_CERTS only at process start. If only SSL_CERT_FILE
|
|
977
|
+
// is set, pass the extra certificates to each outbound TLS agent explicitly.
|
|
978
|
+
function getExtraCaCerts() {
|
|
979
|
+
if (extraCaCertsResolved) {
|
|
980
|
+
return extraCaCerts;
|
|
981
|
+
}
|
|
982
|
+
extraCaCertsResolved = true;
|
|
983
|
+
if (process.env['NODE_EXTRA_CA_CERTS']) {
|
|
984
|
+
return undefined;
|
|
985
|
+
}
|
|
986
|
+
const certPath = constants.default.ENV.NODE_EXTRA_CA_CERTS;
|
|
987
|
+
if (!certPath) {
|
|
988
|
+
return undefined;
|
|
989
|
+
}
|
|
990
|
+
try {
|
|
991
|
+
const extraCerts = u.readFileSync(certPath, 'utf-8');
|
|
992
|
+
extraCaCerts = [...node_tls.rootCertificates, extraCerts];
|
|
993
|
+
return extraCaCerts;
|
|
994
|
+
} catch (error) {
|
|
995
|
+
debug$2.debugFn('warn', `Failed to read certificate file: ${certPath}`, error);
|
|
996
|
+
return undefined;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
const OAUTH_ISSUER = 'https://api.socket.dev';
|
|
1001
|
+
const OAUTH_RESOURCE = 'https://mcp.socket.dev/';
|
|
1002
|
+
const RESOURCE_METADATA = `${OAUTH_RESOURCE}.well-known/oauth-protected-resource`;
|
|
1003
|
+
const ISSUER_METADATA = `${OAUTH_ISSUER}/.well-known/oauth-authorization-server`;
|
|
1004
|
+
const REQUIRED_SCOPES = ['packages:list', 'alerts:list', 'threat-feed:list'];
|
|
1005
|
+
const FLOW_TIMEOUT = 5 * 60_000;
|
|
1006
|
+
const REQUEST_TIMEOUT = 20_000;
|
|
1007
|
+
const MAX_RESPONSE = 256 * 1024;
|
|
1008
|
+
const LOCK_TIMEOUT = 60_000;
|
|
1009
|
+
const FILE = 'oauth.json';
|
|
1010
|
+
const error = message => new Error(`Socket browser sign-in: ${message}`);
|
|
1011
|
+
const random = (n = 32) => require$$0.randomBytes(n).toString('base64url');
|
|
1012
|
+
const form = data => new URLSearchParams(data).toString();
|
|
1013
|
+
function trustedEndpoint(value) {
|
|
1014
|
+
if (typeof value !== 'string') {
|
|
1015
|
+
throw error('OAuth metadata is invalid.');
|
|
1016
|
+
}
|
|
1017
|
+
let u;
|
|
1018
|
+
try {
|
|
1019
|
+
u = new URL(value);
|
|
1020
|
+
} catch {
|
|
1021
|
+
throw error('OAuth metadata is invalid.');
|
|
1022
|
+
}
|
|
1023
|
+
if (u.protocol !== 'https:' || u.origin !== OAUTH_ISSUER || u.username || u.password || u.search || u.hash) {
|
|
1024
|
+
throw error('OAuth metadata contains an untrusted endpoint.');
|
|
1025
|
+
}
|
|
1026
|
+
return u.href;
|
|
1027
|
+
}
|
|
1028
|
+
function agent(proxy, timeoutMs = REQUEST_TIMEOUT) {
|
|
1029
|
+
const ca = getExtraCaCerts();
|
|
1030
|
+
return proxy ? new vendor.HttpsProxyAgent({
|
|
1031
|
+
proxy,
|
|
1032
|
+
timeout: timeoutMs,
|
|
1033
|
+
...(ca ? {
|
|
1034
|
+
ca,
|
|
1035
|
+
proxyRequestOptions: {
|
|
1036
|
+
ca
|
|
1037
|
+
}
|
|
1038
|
+
} : {})
|
|
1039
|
+
}) : ca ? new require$$13.Agent({
|
|
1040
|
+
ca
|
|
1041
|
+
}) : undefined;
|
|
1042
|
+
}
|
|
1043
|
+
function oauthCancellationError(signal) {
|
|
1044
|
+
return signal?.reason instanceof Error ? signal.reason : error('Sign-in was cancelled.');
|
|
1045
|
+
}
|
|
1046
|
+
function http(url, opts = {}) {
|
|
1047
|
+
const target = new URL(url);
|
|
1048
|
+
if (target.protocol !== 'https:' || target.origin !== OAUTH_ISSUER && target.origin !== new URL(OAUTH_RESOURCE).origin) {
|
|
1049
|
+
throw error('Refusing to contact an untrusted OAuth endpoint.');
|
|
1050
|
+
}
|
|
1051
|
+
return new Promise((resolve, reject) => {
|
|
1052
|
+
if (opts.signal?.aborted) {
|
|
1053
|
+
reject(opts.signal.reason ?? error('Sign-in was cancelled.'));
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
let done = false;
|
|
1057
|
+
const finish = fn => {
|
|
1058
|
+
if (!done) {
|
|
1059
|
+
done = true;
|
|
1060
|
+
clearTimeout(deadline);
|
|
1061
|
+
opts.signal?.removeEventListener('abort', abort);
|
|
1062
|
+
requestAgent?.destroy();
|
|
1063
|
+
fn();
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
const timeoutMs = Math.min(opts.timeoutMs ?? REQUEST_TIMEOUT, REQUEST_TIMEOUT);
|
|
1067
|
+
const requestAgent = agent(opts.proxy, timeoutMs);
|
|
1068
|
+
const req = require$$13.request(target, {
|
|
1069
|
+
method: opts.method ?? 'GET',
|
|
1070
|
+
timeout: timeoutMs,
|
|
1071
|
+
...(requestAgent ? {
|
|
1072
|
+
agent: requestAgent
|
|
1073
|
+
} : {}),
|
|
1074
|
+
headers: {
|
|
1075
|
+
accept: 'application/json',
|
|
1076
|
+
...opts.headers,
|
|
1077
|
+
...(opts.body ? {
|
|
1078
|
+
'content-length': String(Buffer.byteLength(opts.body))
|
|
1079
|
+
} : {})
|
|
1080
|
+
}
|
|
1081
|
+
}, res => {
|
|
1082
|
+
const chunks = [];
|
|
1083
|
+
let size = 0;
|
|
1084
|
+
res.on('data', chunk => {
|
|
1085
|
+
size += chunk.length;
|
|
1086
|
+
if (size > MAX_RESPONSE) {
|
|
1087
|
+
req.destroy(error('OAuth response was too large.'));
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
chunks.push(Buffer.from(chunk));
|
|
1091
|
+
});
|
|
1092
|
+
res.on('error', () => finish(() => reject(error('OAuth response could not be read.'))));
|
|
1093
|
+
res.on('aborted', () => finish(() => reject(error('OAuth response ended unexpectedly.'))));
|
|
1094
|
+
res.on('end', () => {
|
|
1095
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
1096
|
+
if (!text && opts.allowEmpty) {
|
|
1097
|
+
finish(() => resolve({
|
|
1098
|
+
status: res.statusCode ?? 0,
|
|
1099
|
+
body: {}
|
|
1100
|
+
}));
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
try {
|
|
1104
|
+
const body = JSON.parse(text);
|
|
1105
|
+
finish(() => resolve({
|
|
1106
|
+
status: res.statusCode ?? 0,
|
|
1107
|
+
body
|
|
1108
|
+
}));
|
|
1109
|
+
} catch {
|
|
1110
|
+
finish(() => reject(error('OAuth server returned an invalid response.')));
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
});
|
|
1114
|
+
const abort = () => {
|
|
1115
|
+
finish(() => reject(error('Sign-in was cancelled.')));
|
|
1116
|
+
req.destroy();
|
|
1117
|
+
};
|
|
1118
|
+
const deadline = setTimeout(() => {
|
|
1119
|
+
finish(() => reject(error('OAuth request timed out.')));
|
|
1120
|
+
req.destroy();
|
|
1121
|
+
}, timeoutMs);
|
|
1122
|
+
opts.signal?.addEventListener('abort', abort, {
|
|
1123
|
+
once: true
|
|
1124
|
+
});
|
|
1125
|
+
req.on('error', () => finish(() => reject(error('OAuth request failed.'))));
|
|
1126
|
+
if (opts.body) {
|
|
1127
|
+
req.write(opts.body);
|
|
1128
|
+
}
|
|
1129
|
+
req.end();
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
async function discover(opts) {
|
|
1133
|
+
const r = await http(RESOURCE_METADATA, {
|
|
1134
|
+
signal: opts.signal,
|
|
1135
|
+
proxy: opts.apiProxy
|
|
1136
|
+
});
|
|
1137
|
+
const rb = r.body;
|
|
1138
|
+
if (r.status !== 200 || !objects.isObjectObject(rb) || rb['resource'] !== OAUTH_RESOURCE || !Array.isArray(rb['authorization_servers']) || !rb['authorization_servers'].some(server => server === OAUTH_ISSUER) || !Array.isArray(rb['scopes_supported']) || rb['scopes_supported'].length !== REQUIRED_SCOPES.length || REQUIRED_SCOPES.some(s => !rb['scopes_supported'].includes(s))) {
|
|
1139
|
+
throw error('Socket OAuth resource metadata could not be verified.');
|
|
1140
|
+
}
|
|
1141
|
+
const ir = await http(ISSUER_METADATA, {
|
|
1142
|
+
signal: opts.signal,
|
|
1143
|
+
proxy: opts.apiProxy
|
|
1144
|
+
});
|
|
1145
|
+
const m = ir.body;
|
|
1146
|
+
if (ir.status !== 200 || !objects.isObjectObject(m) || m['issuer'] !== OAUTH_ISSUER || !Array.isArray(m['grant_types_supported']) || !m['grant_types_supported'].includes('authorization_code') || !m['grant_types_supported'].includes('refresh_token') || !Array.isArray(m['code_challenge_methods_supported']) || !m['code_challenge_methods_supported'].includes('S256') || !Array.isArray(m['token_endpoint_auth_methods_supported']) || !m['token_endpoint_auth_methods_supported'].includes('none')) {
|
|
1147
|
+
throw error('Socket OAuth issuer metadata is invalid.');
|
|
1148
|
+
}
|
|
1149
|
+
return {
|
|
1150
|
+
authorize: trustedEndpoint(m['authorization_endpoint']),
|
|
1151
|
+
register: trustedEndpoint(m['registration_endpoint']),
|
|
1152
|
+
token: trustedEndpoint(m['token_endpoint']),
|
|
1153
|
+
...(m['revocation_endpoint'] ? {
|
|
1154
|
+
revoke: trustedEndpoint(m['revocation_endpoint'])
|
|
1155
|
+
} : {})
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
function parseToken(r, fallback, meta) {
|
|
1159
|
+
const b = r.body;
|
|
1160
|
+
if (r.status < 200 || r.status >= 300 || !objects.isObjectObject(b) || typeof b['access_token'] !== 'string' || !b['access_token'].trim() || typeof b['token_type'] !== 'string' || b['token_type'].toLowerCase() !== 'bearer' || typeof b['expires_in'] !== 'number' || !Number.isFinite(b['expires_in']) || b['expires_in'] <= 0 || !Number.isSafeInteger(Date.now() + b['expires_in'] * 1000) || b['refresh_token'] !== undefined && (typeof b['refresh_token'] !== 'string' || !b['refresh_token'])) {
|
|
1161
|
+
const code = objects.isObjectObject(b) && b['error'] === 'invalid_grant';
|
|
1162
|
+
throw error(code ? 'The saved session expired or was revoked. Run `socket login` again.' : 'Token exchange failed. Run `socket login` again if the problem continues.');
|
|
1163
|
+
}
|
|
1164
|
+
if (b['scope'] !== undefined && typeof b['scope'] !== 'string') {
|
|
1165
|
+
throw error('The authorization server returned invalid permissions.');
|
|
1166
|
+
}
|
|
1167
|
+
const scopes = typeof b['scope'] === 'string' ? b['scope'].split(/\s+/).filter(Boolean) : fallback;
|
|
1168
|
+
if (scopes.some(s => !REQUIRED_SCOPES.includes(s))) {
|
|
1169
|
+
throw error('The authorization server returned unsupported permissions.');
|
|
1170
|
+
}
|
|
1171
|
+
if (REQUIRED_SCOPES.some(scope => !scopes.includes(scope))) {
|
|
1172
|
+
throw error('The authorization server did not grant the required read-only permissions.');
|
|
1173
|
+
}
|
|
1174
|
+
return {
|
|
1175
|
+
version: 1,
|
|
1176
|
+
issuer: OAUTH_ISSUER,
|
|
1177
|
+
resource: OAUTH_RESOURCE,
|
|
1178
|
+
apiOrigin: OAUTH_ISSUER,
|
|
1179
|
+
clientId: meta.clientId,
|
|
1180
|
+
accessToken: b['access_token'],
|
|
1181
|
+
...(typeof b['refresh_token'] === 'string' ? {
|
|
1182
|
+
refreshToken: b['refresh_token']
|
|
1183
|
+
} : {}),
|
|
1184
|
+
expiresAt: Date.now() + b['expires_in'] * 1000,
|
|
1185
|
+
scopes,
|
|
1186
|
+
tokenEndpoint: meta.tokenEndpoint,
|
|
1187
|
+
...(meta.revocationEndpoint ? {
|
|
1188
|
+
revocationEndpoint: meta.revocationEndpoint
|
|
1189
|
+
} : {})
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
function same(a, b) {
|
|
1193
|
+
const x = Buffer.from(a);
|
|
1194
|
+
const y = Buffer.from(b);
|
|
1195
|
+
return x.length === y.length && require$$0.timingSafeEqual(x, y);
|
|
1196
|
+
}
|
|
1197
|
+
async function beginOAuthLogin(options) {
|
|
1198
|
+
const controller = new AbortController();
|
|
1199
|
+
const abort = () => controller.abort(options.signal?.reason);
|
|
1200
|
+
if (options.signal?.aborted) {
|
|
1201
|
+
abort();
|
|
1202
|
+
}
|
|
1203
|
+
options.signal?.addEventListener('abort', abort, {
|
|
1204
|
+
once: true
|
|
1205
|
+
});
|
|
1206
|
+
const timeout = setTimeout(() => controller.abort(error('Sign-in timed out. Run `socket login` to try again.')), FLOW_TIMEOUT);
|
|
1207
|
+
const signal = controller.signal;
|
|
1208
|
+
let server;
|
|
1209
|
+
try {
|
|
1210
|
+
const meta = await discover({
|
|
1211
|
+
signal,
|
|
1212
|
+
apiProxy: options.apiProxy
|
|
1213
|
+
});
|
|
1214
|
+
const state = random();
|
|
1215
|
+
const verifier = random(48);
|
|
1216
|
+
const challenge = require$$0.createHash('sha256').update(verifier).digest('base64url');
|
|
1217
|
+
let resolveCode;
|
|
1218
|
+
let rejectCode;
|
|
1219
|
+
let settled = false;
|
|
1220
|
+
const codePromise = new Promise((resolve, reject) => {
|
|
1221
|
+
resolveCode = resolve;
|
|
1222
|
+
rejectCode = reject;
|
|
1223
|
+
});
|
|
1224
|
+
// Attach a rejection observer immediately: an OAuth error callback can arrive while DCR is pending.
|
|
1225
|
+
void codePromise.catch(() => {});
|
|
1226
|
+
server = require$$12.createServer((req, res) => {
|
|
1227
|
+
let u;
|
|
1228
|
+
try {
|
|
1229
|
+
u = new URL(req.url ?? '/', 'http://127.0.0.1');
|
|
1230
|
+
} catch {
|
|
1231
|
+
res.writeHead(400).end('Invalid callback request.');
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
if (req.method !== 'GET' || u.pathname !== '/oauth/callback') {
|
|
1235
|
+
res.writeHead(404).end();
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
if (settled) {
|
|
1239
|
+
res.writeHead(410).end();
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
if (!same(u.searchParams.get('state') ?? '', state)) {
|
|
1243
|
+
res.writeHead(400).end('Sign-in state did not match.');
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
if (u.searchParams.has('error') || !u.searchParams.get('code')) {
|
|
1247
|
+
settled = true;
|
|
1248
|
+
res.writeHead(400).end('Sign-in was not completed.');
|
|
1249
|
+
rejectCode(error('Authorization was declined.'));
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
settled = true;
|
|
1253
|
+
res.writeHead(200, {
|
|
1254
|
+
'content-type': 'text/html; charset=utf-8',
|
|
1255
|
+
'cache-control': 'no-store'
|
|
1256
|
+
}).end('<!doctype html><title>Socket CLI</title><p>Sign-in complete. Return to your terminal.</p>');
|
|
1257
|
+
resolveCode(u.searchParams.get('code'));
|
|
1258
|
+
});
|
|
1259
|
+
signal.addEventListener('abort', () => {
|
|
1260
|
+
if (!settled) {
|
|
1261
|
+
settled = true;
|
|
1262
|
+
rejectCode(oauthCancellationError(signal));
|
|
1263
|
+
}
|
|
1264
|
+
}, {
|
|
1265
|
+
once: true
|
|
1266
|
+
});
|
|
1267
|
+
if (signal.aborted && !settled) {
|
|
1268
|
+
settled = true;
|
|
1269
|
+
rejectCode(oauthCancellationError(signal));
|
|
1270
|
+
}
|
|
1271
|
+
const redirectUri = await new Promise((resolve, reject) => {
|
|
1272
|
+
server.once('error', () => reject(error('Could not start the local callback listener.')));
|
|
1273
|
+
server.listen(0, '127.0.0.1', () => {
|
|
1274
|
+
const a = server.address();
|
|
1275
|
+
if (!a || typeof a === 'string') {
|
|
1276
|
+
reject(error('Could not start the local callback listener.'));
|
|
1277
|
+
} else {
|
|
1278
|
+
resolve(`http://127.0.0.1:${a.port}/oauth/callback`);
|
|
1279
|
+
}
|
|
1280
|
+
});
|
|
1281
|
+
});
|
|
1282
|
+
const registration = await http(meta.register, {
|
|
1283
|
+
method: 'POST',
|
|
1284
|
+
signal,
|
|
1285
|
+
proxy: options.apiProxy,
|
|
1286
|
+
headers: {
|
|
1287
|
+
'content-type': 'application/json'
|
|
1288
|
+
},
|
|
1289
|
+
body: JSON.stringify({
|
|
1290
|
+
client_name: 'Socket CLI',
|
|
1291
|
+
redirect_uris: [redirectUri],
|
|
1292
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
1293
|
+
response_types: ['code'],
|
|
1294
|
+
token_endpoint_auth_method: 'none'
|
|
1295
|
+
})
|
|
1296
|
+
});
|
|
1297
|
+
const reg = registration.body;
|
|
1298
|
+
if (registration.status < 200 || registration.status >= 300 || !objects.isObjectObject(reg) || typeof reg['client_id'] !== 'string' || !reg['client_id'].trim() || reg['token_endpoint_auth_method'] !== undefined && reg['token_endpoint_auth_method'] !== 'none' || reg['redirect_uris'] !== undefined && (!Array.isArray(reg['redirect_uris']) || !reg['redirect_uris'].some(value => value === redirectUri)) || reg['grant_types'] !== undefined && (!Array.isArray(reg['grant_types']) || !['authorization_code', 'refresh_token'].every(grant => reg['grant_types'].some(value => value === grant))) || reg['response_types'] !== undefined && (!Array.isArray(reg['response_types']) || !reg['response_types'].some(value => value === 'code'))) {
|
|
1299
|
+
throw error('The OAuth client could not be registered.');
|
|
1300
|
+
}
|
|
1301
|
+
const clientId = reg['client_id'];
|
|
1302
|
+
const url = new URL(meta.authorize);
|
|
1303
|
+
url.search = form({
|
|
1304
|
+
response_type: 'code',
|
|
1305
|
+
client_id: clientId,
|
|
1306
|
+
redirect_uri: redirectUri,
|
|
1307
|
+
scope: REQUIRED_SCOPES.join(' '),
|
|
1308
|
+
state,
|
|
1309
|
+
code_challenge: challenge,
|
|
1310
|
+
code_challenge_method: 'S256',
|
|
1311
|
+
resource: OAUTH_RESOURCE
|
|
1312
|
+
});
|
|
1313
|
+
options.onAuthorizationUrl(url.href);
|
|
1314
|
+
if (options.openBrowser !== false) {
|
|
1315
|
+
try {
|
|
1316
|
+
await vendor.open(url.href);
|
|
1317
|
+
} catch {
|
|
1318
|
+
/* URL was printed; manual browser completion remains available. */
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
const code = await codePromise;
|
|
1322
|
+
const token = await http(meta.token, {
|
|
1323
|
+
method: 'POST',
|
|
1324
|
+
signal,
|
|
1325
|
+
proxy: options.apiProxy,
|
|
1326
|
+
headers: {
|
|
1327
|
+
'content-type': 'application/x-www-form-urlencoded'
|
|
1328
|
+
},
|
|
1329
|
+
body: form({
|
|
1330
|
+
grant_type: 'authorization_code',
|
|
1331
|
+
code,
|
|
1332
|
+
client_id: clientId,
|
|
1333
|
+
redirect_uri: redirectUri,
|
|
1334
|
+
code_verifier: verifier,
|
|
1335
|
+
resource: OAUTH_RESOURCE
|
|
1336
|
+
})
|
|
1337
|
+
});
|
|
1338
|
+
return parseToken(token, REQUIRED_SCOPES, {
|
|
1339
|
+
clientId,
|
|
1340
|
+
tokenEndpoint: meta.token,
|
|
1341
|
+
...(meta.revoke ? {
|
|
1342
|
+
revocationEndpoint: meta.revoke
|
|
1343
|
+
} : {})
|
|
1344
|
+
});
|
|
1345
|
+
} finally {
|
|
1346
|
+
clearTimeout(timeout);
|
|
1347
|
+
options.signal?.removeEventListener('abort', abort);
|
|
1348
|
+
server?.close();
|
|
1349
|
+
server?.closeAllConnections();
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
const filePath = dir => path.join(dir, FILE);
|
|
1353
|
+
function validCredentials(value) {
|
|
1354
|
+
if (!objects.isObjectObject(value) || value['version'] !== 1 || value['issuer'] !== OAUTH_ISSUER || value['resource'] !== OAUTH_RESOURCE || value['apiOrigin'] !== OAUTH_ISSUER || typeof value['clientId'] !== 'string' || !value['clientId'] || typeof value['accessToken'] !== 'string' || !value['accessToken'] || typeof value['expiresAt'] !== 'number' || !Number.isFinite(value['expiresAt']) || value['expiresAt'] <= 0 || !Array.isArray(value['scopes']) || value['scopes'].some(s => typeof s !== 'string' || !REQUIRED_SCOPES.includes(s)) || value['refreshToken'] !== undefined && (typeof value['refreshToken'] !== 'string' || !value['refreshToken'])) {
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1357
|
+
try {
|
|
1358
|
+
trustedEndpoint(value['tokenEndpoint']);
|
|
1359
|
+
if (value['revocationEndpoint'] !== undefined) {
|
|
1360
|
+
trustedEndpoint(value['revocationEndpoint']);
|
|
1361
|
+
}
|
|
1362
|
+
return true;
|
|
1363
|
+
} catch {
|
|
1364
|
+
return false;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
function readOAuthCredentials(directory) {
|
|
1368
|
+
try {
|
|
1369
|
+
const x = JSON.parse(u.readFileSync(filePath(directory), 'utf8'));
|
|
1370
|
+
if (!validCredentials(x)) {
|
|
1371
|
+
throw error('Saved OAuth credentials are invalid. Run `socket login` again.');
|
|
1372
|
+
}
|
|
1373
|
+
return x;
|
|
1374
|
+
} catch (e) {
|
|
1375
|
+
if (e.code === 'ENOENT') {
|
|
1376
|
+
return undefined;
|
|
1377
|
+
}
|
|
1378
|
+
if (e instanceof SyntaxError) {
|
|
1379
|
+
throw error('Saved OAuth credentials are corrupt. Run `socket login` again.');
|
|
1380
|
+
}
|
|
1381
|
+
throw e;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
async function locked(directory, action, signal) {
|
|
1385
|
+
if (signal?.aborted) {
|
|
1386
|
+
throw oauthCancellationError(signal);
|
|
1387
|
+
}
|
|
1388
|
+
await u.promises.mkdir(directory, {
|
|
1389
|
+
recursive: true,
|
|
1390
|
+
mode: 0o700
|
|
1391
|
+
});
|
|
1392
|
+
const lock = `${filePath(directory)}.lock`;
|
|
1393
|
+
const until = Date.now() + LOCK_TIMEOUT;
|
|
1394
|
+
while (true) {
|
|
1395
|
+
try {
|
|
1396
|
+
// This await performs the inter-process mutex acquisition.
|
|
1397
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1398
|
+
await u.promises.mkdir(lock, {
|
|
1399
|
+
mode: 0o700
|
|
1400
|
+
});
|
|
1401
|
+
break;
|
|
1402
|
+
} catch (e) {
|
|
1403
|
+
if (e.code !== 'EEXIST') {
|
|
1404
|
+
throw e;
|
|
1405
|
+
}
|
|
1406
|
+
if (Date.now() >= until) {
|
|
1407
|
+
throw error(`Could not acquire sign-in lock ${lock}. After confirming no other Socket CLI process is running, remove this lock directory and retry.`);
|
|
1408
|
+
}
|
|
1409
|
+
if (signal?.aborted) {
|
|
1410
|
+
throw oauthCancellationError(signal);
|
|
1411
|
+
}
|
|
1412
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1413
|
+
await new Promise((resolve, reject) => {
|
|
1414
|
+
const timer = setTimeout(() => {
|
|
1415
|
+
signal?.removeEventListener('abort', onAbort);
|
|
1416
|
+
resolve();
|
|
1417
|
+
}, 100);
|
|
1418
|
+
const onAbort = () => {
|
|
1419
|
+
clearTimeout(timer);
|
|
1420
|
+
reject(oauthCancellationError(signal));
|
|
1421
|
+
};
|
|
1422
|
+
signal?.addEventListener('abort', onAbort, {
|
|
1423
|
+
once: true
|
|
1424
|
+
});
|
|
1425
|
+
if (signal?.aborted) {
|
|
1426
|
+
onAbort();
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
try {
|
|
1432
|
+
return await action();
|
|
1433
|
+
} finally {
|
|
1434
|
+
await u.promises.rm(lock, {
|
|
1435
|
+
recursive: true,
|
|
1436
|
+
force: true
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
async function writeAtomic(directory, credentials) {
|
|
1441
|
+
await u.promises.chmod(directory, 0o700).catch(() => {});
|
|
1442
|
+
const target = filePath(directory);
|
|
1443
|
+
const tmp = `${target}.${process.pid}.${random(6)}.tmp`;
|
|
1444
|
+
try {
|
|
1445
|
+
await u.promises.writeFile(tmp, `${JSON.stringify(credentials, null, 2)}\n`, {
|
|
1446
|
+
mode: 0o600,
|
|
1447
|
+
flag: 'wx'
|
|
1448
|
+
});
|
|
1449
|
+
await u.promises.chmod(tmp, 0o600);
|
|
1450
|
+
await u.promises.rename(tmp, target);
|
|
1451
|
+
} finally {
|
|
1452
|
+
await u.promises.rm(tmp, {
|
|
1453
|
+
force: true
|
|
1454
|
+
}).catch(() => {});
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
async function saveOAuthCredentials(directory, credentials) {
|
|
1458
|
+
if (!validCredentials(credentials)) {
|
|
1459
|
+
throw error('Refusing to save invalid OAuth credentials.');
|
|
1460
|
+
}
|
|
1461
|
+
await locked(directory, () => writeAtomic(directory, credentials));
|
|
1462
|
+
}
|
|
1463
|
+
async function resolveOAuthAccessToken(directory, options = {}) {
|
|
1464
|
+
if (options.signal?.aborted) {
|
|
1465
|
+
throw oauthCancellationError(options.signal);
|
|
1466
|
+
}
|
|
1467
|
+
const current = readOAuthCredentials(directory);
|
|
1468
|
+
if (!current) {
|
|
1469
|
+
return undefined;
|
|
1470
|
+
}
|
|
1471
|
+
if (current.expiresAt > Date.now() + 30_000) {
|
|
1472
|
+
return current.accessToken;
|
|
1473
|
+
}
|
|
1474
|
+
return await locked(directory, async () => {
|
|
1475
|
+
if (options.signal?.aborted) {
|
|
1476
|
+
throw oauthCancellationError(options.signal);
|
|
1477
|
+
}
|
|
1478
|
+
const latest = readOAuthCredentials(directory);
|
|
1479
|
+
if (!latest) {
|
|
1480
|
+
throw error('The saved session was removed. Run `socket login` again.');
|
|
1481
|
+
}
|
|
1482
|
+
if (latest.expiresAt > Date.now() + 30_000) {
|
|
1483
|
+
return latest.accessToken;
|
|
1484
|
+
}
|
|
1485
|
+
if (!latest.refreshToken) {
|
|
1486
|
+
throw error('The saved session expired. Run `socket login` again.');
|
|
1487
|
+
}
|
|
1488
|
+
if (options.signal?.aborted) {
|
|
1489
|
+
throw oauthCancellationError(options.signal);
|
|
1490
|
+
}
|
|
1491
|
+
// Durably discard the rotating token before sending it. A timeout/crash can
|
|
1492
|
+
// never cause another process to replay a token the server may have used.
|
|
1493
|
+
const refreshToken = latest.refreshToken;
|
|
1494
|
+
await writeAtomic(directory, {
|
|
1495
|
+
...latest,
|
|
1496
|
+
refreshToken: undefined
|
|
1497
|
+
});
|
|
1498
|
+
const result = await http(latest.tokenEndpoint, {
|
|
1499
|
+
method: 'POST',
|
|
1500
|
+
signal: options.signal,
|
|
1501
|
+
proxy: options.apiProxy,
|
|
1502
|
+
timeoutMs: options.requestTimeoutMs,
|
|
1503
|
+
headers: {
|
|
1504
|
+
'content-type': 'application/x-www-form-urlencoded'
|
|
1505
|
+
},
|
|
1506
|
+
body: form({
|
|
1507
|
+
grant_type: 'refresh_token',
|
|
1508
|
+
client_id: latest.clientId,
|
|
1509
|
+
refresh_token: refreshToken,
|
|
1510
|
+
resource: OAUTH_RESOURCE
|
|
1511
|
+
})
|
|
1512
|
+
});
|
|
1513
|
+
const fresh = parseToken(result, latest.scopes, {
|
|
1514
|
+
clientId: latest.clientId,
|
|
1515
|
+
tokenEndpoint: latest.tokenEndpoint,
|
|
1516
|
+
...(latest.revocationEndpoint ? {
|
|
1517
|
+
revocationEndpoint: latest.revocationEndpoint
|
|
1518
|
+
} : {})
|
|
1519
|
+
});
|
|
1520
|
+
await writeAtomic(directory, fresh);
|
|
1521
|
+
return fresh.accessToken;
|
|
1522
|
+
}, options.signal);
|
|
1523
|
+
}
|
|
1524
|
+
async function logoutOAuth(directory, options = {}) {
|
|
1525
|
+
return await locked(directory, async () => {
|
|
1526
|
+
let creds;
|
|
1527
|
+
let warning;
|
|
1528
|
+
try {
|
|
1529
|
+
creds = readOAuthCredentials(directory);
|
|
1530
|
+
} catch {
|
|
1531
|
+
warning = 'Saved credentials were invalid; local sign-in data was removed.';
|
|
1532
|
+
}
|
|
1533
|
+
let revoked = false;
|
|
1534
|
+
if (creds) {
|
|
1535
|
+
if (!creds.revocationEndpoint) {
|
|
1536
|
+
warning = 'Remote session revocation was not confirmed.';
|
|
1537
|
+
} else {
|
|
1538
|
+
try {
|
|
1539
|
+
const token = creds.refreshToken ?? creds.accessToken;
|
|
1540
|
+
const hint = creds.refreshToken ? 'refresh_token' : 'access_token';
|
|
1541
|
+
const r = await http(creds.revocationEndpoint, {
|
|
1542
|
+
method: 'POST',
|
|
1543
|
+
signal: options.signal,
|
|
1544
|
+
proxy: options.apiProxy,
|
|
1545
|
+
allowEmpty: true,
|
|
1546
|
+
headers: {
|
|
1547
|
+
'content-type': 'application/x-www-form-urlencoded'
|
|
1548
|
+
},
|
|
1549
|
+
body: form({
|
|
1550
|
+
client_id: creds.clientId,
|
|
1551
|
+
token,
|
|
1552
|
+
token_type_hint: hint
|
|
1553
|
+
})
|
|
1554
|
+
});
|
|
1555
|
+
revoked = r.status >= 200 && r.status < 300;
|
|
1556
|
+
if (!revoked) {
|
|
1557
|
+
warning = 'Remote session revocation was not confirmed.';
|
|
1558
|
+
}
|
|
1559
|
+
} catch {
|
|
1560
|
+
warning = 'Remote session revocation was not confirmed.';
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
await u.promises.rm(filePath(directory), {
|
|
1565
|
+
force: true
|
|
1566
|
+
});
|
|
1567
|
+
return {
|
|
1568
|
+
revoked,
|
|
1569
|
+
...(warning ? {
|
|
1570
|
+
warning
|
|
1571
|
+
} : {})
|
|
1572
|
+
};
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
|
|
972
1576
|
/**
|
|
973
1577
|
* Telemetry service for Socket CLI.
|
|
974
1578
|
* Manages event collection, batching, and submission to Socket API.
|
|
@@ -1879,76 +2483,117 @@ function getDefaultProxyUrl() {
|
|
|
1879
2483
|
const apiProxy = constants.default.ENV.SOCKET_CLI_API_PROXY || getConfigValueOrUndef(constants.CONFIG_KEY_API_PROXY);
|
|
1880
2484
|
return url.isUrl(apiProxy) ? apiProxy : undefined;
|
|
1881
2485
|
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
let _extraCaCerts;
|
|
1885
|
-
let _extraCaCertsResolved = false;
|
|
1886
|
-
|
|
1887
|
-
// Returns combined root and extra CA certificates when SSL_CERT_FILE is set
|
|
1888
|
-
// but NODE_EXTRA_CA_CERTS is not. Node.js loads NODE_EXTRA_CA_CERTS at process
|
|
1889
|
-
// startup, so setting SSL_CERT_FILE alone does not affect the current process.
|
|
1890
|
-
// This function reads the certificate file manually and combines it with the
|
|
1891
|
-
// default root certificates for use in HTTPS agents.
|
|
1892
|
-
function getExtraCaCerts() {
|
|
1893
|
-
if (_extraCaCertsResolved) {
|
|
1894
|
-
return _extraCaCerts;
|
|
1895
|
-
}
|
|
1896
|
-
_extraCaCertsResolved = true;
|
|
1897
|
-
// Node.js already loaded extra CA certs at startup.
|
|
1898
|
-
if (process.env['NODE_EXTRA_CA_CERTS']) {
|
|
2486
|
+
function getDefaultApiToken() {
|
|
2487
|
+
if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
1899
2488
|
return undefined;
|
|
1900
2489
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
return undefined;
|
|
2490
|
+
const environmentToken = constants.default.ENV.SOCKET_CLI_API_TOKEN;
|
|
2491
|
+
if (strings.isNonEmptyString(environmentToken)) {
|
|
2492
|
+
return environmentToken;
|
|
1905
2493
|
}
|
|
1906
|
-
|
|
1907
|
-
const extraCerts = u.readFileSync(certPath, 'utf-8');
|
|
1908
|
-
// Combine default root certificates with extra certificates. Specifying ca
|
|
1909
|
-
// in an agent replaces the default trust store, so both must be included.
|
|
1910
|
-
_extraCaCerts = [...node_tls.rootCertificates, extraCerts];
|
|
1911
|
-
return _extraCaCerts;
|
|
1912
|
-
} catch (e) {
|
|
1913
|
-
debug$2.debugFn('warn', `Failed to read certificate file: ${certPath}`, e);
|
|
2494
|
+
if (getConfigValueOrUndef(constants.CONFIG_KEY_AUTH_TYPE) === 'oauth') {
|
|
1914
2495
|
return undefined;
|
|
1915
2496
|
}
|
|
2497
|
+
const key = getConfigValueOrUndef(constants.CONFIG_KEY_API_TOKEN);
|
|
2498
|
+
return strings.isNonEmptyString(key) ? key : undefined;
|
|
1916
2499
|
}
|
|
1917
2500
|
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
1922
|
-
_defaultToken = undefined;
|
|
1923
|
-
return _defaultToken;
|
|
1924
|
-
}
|
|
1925
|
-
const key = constants.default.ENV.SOCKET_CLI_API_TOKEN || getConfigValueOrUndef(constants.CONFIG_KEY_API_TOKEN) || _defaultToken;
|
|
1926
|
-
_defaultToken = strings.isNonEmptyString(key) ? key : undefined;
|
|
1927
|
-
return _defaultToken;
|
|
2501
|
+
/** Whether saved OAuth auth is active instead of a flag or explicit token. */
|
|
2502
|
+
function isOAuthLoginActive() {
|
|
2503
|
+
return !isConfigFromFlag() && !constants.default.ENV.SOCKET_CLI_NO_API_TOKEN && !constants.default.ENV.SOCKET_CLI_API_TOKEN && getConfigValueOrUndef(constants.CONFIG_KEY_AUTH_TYPE) === 'oauth';
|
|
1928
2504
|
}
|
|
1929
|
-
function
|
|
1930
|
-
|
|
2505
|
+
async function resolvePublicApiToken(options) {
|
|
2506
|
+
const token = await resolveDefaultApiToken(options);
|
|
2507
|
+
if (token) {
|
|
2508
|
+
return token;
|
|
2509
|
+
}
|
|
2510
|
+
if (!constants.default.ENV.SOCKET_CLI_NO_API_TOKEN && getConfigValueOrUndef(constants.CONFIG_KEY_AUTH_TYPE) === 'oauth') {
|
|
2511
|
+
throw new Error('Browser sign-in has no usable access token. Run `socket login` to sign in again.');
|
|
2512
|
+
}
|
|
2513
|
+
return constants.default.SOCKET_PUBLIC_API_TOKEN;
|
|
1931
2514
|
}
|
|
1932
2515
|
function getVisibleTokenPrefix() {
|
|
2516
|
+
if (!constants.default.ENV.SOCKET_CLI_NO_API_TOKEN && getConfigValueOrUndef(constants.CONFIG_KEY_AUTH_TYPE) === 'oauth' && !constants.default.ENV.SOCKET_CLI_API_TOKEN) {
|
|
2517
|
+
return 'oauth';
|
|
2518
|
+
}
|
|
1933
2519
|
const apiToken = getDefaultApiToken();
|
|
1934
2520
|
return apiToken ? apiToken.slice(TOKEN_PREFIX_LENGTH, TOKEN_PREFIX_LENGTH + TOKEN_VISIBLE_LENGTH) : '';
|
|
1935
2521
|
}
|
|
1936
2522
|
function hasDefaultApiToken() {
|
|
1937
|
-
|
|
2523
|
+
if (getDefaultApiToken()) {
|
|
2524
|
+
return true;
|
|
2525
|
+
}
|
|
2526
|
+
const directory = constants.default.socketAppDataPath;
|
|
2527
|
+
return Boolean(isOAuthLoginActive() && directory && hasOAuthCredentialFile(directory));
|
|
2528
|
+
}
|
|
2529
|
+
function hasOAuthCredentialFile(directory) {
|
|
2530
|
+
try {
|
|
2531
|
+
return Boolean(readOAuthCredentials(directory));
|
|
2532
|
+
} catch {
|
|
2533
|
+
// Keep preflight from crashing; async token resolution reports a useful
|
|
2534
|
+
// error and must not fall back to another credential.
|
|
2535
|
+
return true;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
async function resolveDefaultApiToken(options) {
|
|
2539
|
+
if (constants.default.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
2540
|
+
return undefined;
|
|
2541
|
+
}
|
|
2542
|
+
const environmentToken = constants.default.ENV.SOCKET_CLI_API_TOKEN;
|
|
2543
|
+
if (strings.isNonEmptyString(environmentToken)) {
|
|
2544
|
+
return environmentToken;
|
|
2545
|
+
}
|
|
2546
|
+
if (getConfigValueOrUndef(constants.CONFIG_KEY_AUTH_TYPE) !== 'oauth') {
|
|
2547
|
+
const configured = getConfigValueOrUndef(constants.CONFIG_KEY_API_TOKEN);
|
|
2548
|
+
return strings.isNonEmptyString(configured) ? configured : undefined;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
// Explicit config is read-only and must never consult persisted OAuth state.
|
|
2552
|
+
if (isConfigFromFlag()) {
|
|
2553
|
+
return undefined;
|
|
2554
|
+
}
|
|
2555
|
+
const directory = constants.default.socketAppDataPath;
|
|
2556
|
+
if (!directory) {
|
|
2557
|
+
throw new Error('OAuth credentials are unavailable in this environment. Run `socket login` in a supported user session.');
|
|
2558
|
+
}
|
|
2559
|
+
const credentials = readOAuthCredentials(directory);
|
|
2560
|
+
if (!credentials) {
|
|
2561
|
+
throw new Error('Browser sign-in is selected but its credentials are missing or invalid. Run `socket login` to sign in again.');
|
|
2562
|
+
}
|
|
2563
|
+
const apiBaseUrl = options?.apiBaseUrl ?? getDefaultApiBaseUrl$1();
|
|
2564
|
+
if (apiBaseUrl) {
|
|
2565
|
+
let origin;
|
|
2566
|
+
try {
|
|
2567
|
+
origin = new URL(apiBaseUrl).origin;
|
|
2568
|
+
} catch {
|
|
2569
|
+
throw new Error('The configured Socket API URL is invalid for OAuth.');
|
|
2570
|
+
}
|
|
2571
|
+
if (origin !== credentials.apiOrigin) {
|
|
2572
|
+
throw new Error('Browser sign-in can only be used with Socket’s trusted API origin. Use `socket login --api-token` for a custom API URL.');
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
return await resolveOAuthAccessToken(directory, {
|
|
2576
|
+
apiProxy: options?.apiProxy ?? getDefaultProxyUrl(),
|
|
2577
|
+
signal: options?.signal
|
|
2578
|
+
});
|
|
1938
2579
|
}
|
|
1939
2580
|
async function setupSdk(options) {
|
|
1940
2581
|
const opts = {
|
|
1941
2582
|
__proto__: null,
|
|
1942
2583
|
...options
|
|
1943
2584
|
};
|
|
1944
|
-
let
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
2585
|
+
let apiToken;
|
|
2586
|
+
try {
|
|
2587
|
+
apiToken = opts.apiToken ?? (await resolveDefaultApiToken({
|
|
2588
|
+
apiBaseUrl: opts.apiBaseUrl,
|
|
2589
|
+
apiProxy: opts.apiProxy
|
|
2590
|
+
}));
|
|
2591
|
+
} catch (error) {
|
|
2592
|
+
return {
|
|
2593
|
+
ok: false,
|
|
2594
|
+
message: 'Auth Error',
|
|
2595
|
+
cause: getErrorCause(error)
|
|
2596
|
+
};
|
|
1952
2597
|
}
|
|
1953
2598
|
if (!apiToken) {
|
|
1954
2599
|
return {
|
|
@@ -2095,6 +2740,18 @@ async function setupSdk(options) {
|
|
|
2095
2740
|
|
|
2096
2741
|
const MAX_REDIRECTS = 20;
|
|
2097
2742
|
const NO_ERROR_MESSAGE = 'No error message returned';
|
|
2743
|
+
function getApiErrorText(value) {
|
|
2744
|
+
if (typeof value === 'string') {
|
|
2745
|
+
return value;
|
|
2746
|
+
}
|
|
2747
|
+
if (!value || typeof value !== 'object') {
|
|
2748
|
+
return '';
|
|
2749
|
+
}
|
|
2750
|
+
const record = value;
|
|
2751
|
+
const details = record['details'];
|
|
2752
|
+
const nestedCode = details && typeof details === 'object' ? details['code'] : undefined;
|
|
2753
|
+
return [record['code'], nestedCode, record['message'], record['error']].filter(part => typeof part === 'string').join(' ');
|
|
2754
|
+
}
|
|
2098
2755
|
|
|
2099
2756
|
// Cached HTTPS agent for direct API calls. Undefined only until the first
|
|
2100
2757
|
// getHttpsAgent() call lazily creates it.
|
|
@@ -2243,14 +2900,18 @@ function _httpsRequestFetch(url, init, agent, redirectCount) {
|
|
|
2243
2900
|
* API gives in its `{ error: { message } }` body when there is one.
|
|
2244
2901
|
*/
|
|
2245
2902
|
async function describeApiFailure(response, path) {
|
|
2246
|
-
let serverMessage;
|
|
2903
|
+
let serverMessage = '';
|
|
2904
|
+
let serverCode = '';
|
|
2247
2905
|
try {
|
|
2248
|
-
|
|
2906
|
+
const payload = JSON.parse(await response.text());
|
|
2907
|
+
const serverError = payload?.error;
|
|
2908
|
+
serverMessage = getApiErrorText(serverError);
|
|
2909
|
+
serverCode = [payload?.code, serverError?.code, serverError?.details?.code].filter(part => typeof part === 'string').join(' ');
|
|
2249
2910
|
} catch {
|
|
2250
2911
|
// A body that isn't JSON carries no message.
|
|
2251
2912
|
}
|
|
2252
|
-
const reason = await getErrorMessageForHttpStatusCode(response.status);
|
|
2253
|
-
return
|
|
2913
|
+
const reason = await getErrorMessageForHttpStatusCode(response.status, [serverCode, serverMessage].filter(Boolean).join(' '));
|
|
2914
|
+
return serverMessage ? `${response.statusText}: ${serverMessage} (reason: ${reason}) (path: ${path})` : `${response.statusText} (reason: ${reason}) (path: ${path})`;
|
|
2254
2915
|
}
|
|
2255
2916
|
async function apiFetch(url, init = {}) {
|
|
2256
2917
|
return await _httpsRequestFetch(url, init, getHttpsAgent(), 0);
|
|
@@ -2270,7 +2931,13 @@ function getCommandRequirements(cmdPath) {
|
|
|
2270
2931
|
/**
|
|
2271
2932
|
* Log required permissions for a command when encountering 403 errors.
|
|
2272
2933
|
*/
|
|
2273
|
-
function logPermissionsFor403(cmdPath) {
|
|
2934
|
+
function logPermissionsFor403(cmdPath, apiError) {
|
|
2935
|
+
if (isOAuthLoginActive()) {
|
|
2936
|
+
const guidance = getOAuth403Guidance(apiError);
|
|
2937
|
+
if (guidance) {
|
|
2938
|
+
logger.logger.error(guidance);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2274
2941
|
const requirements = getCommandRequirements(cmdPath);
|
|
2275
2942
|
if (!requirements?.permissions?.length) {
|
|
2276
2943
|
return;
|
|
@@ -2279,7 +2946,9 @@ function logPermissionsFor403(cmdPath) {
|
|
|
2279
2946
|
for (const permission of requirements.permissions) {
|
|
2280
2947
|
logger.logger.error(` - ${permission}`);
|
|
2281
2948
|
}
|
|
2282
|
-
|
|
2949
|
+
if (!isOAuthLoginActive()) {
|
|
2950
|
+
logger.logger.error('Please ensure your API token has the required permissions.');
|
|
2951
|
+
}
|
|
2283
2952
|
}
|
|
2284
2953
|
|
|
2285
2954
|
// The Socket API server that should be used for operations.
|
|
@@ -2295,7 +2964,16 @@ function getDefaultApiBaseUrl() {
|
|
|
2295
2964
|
/**
|
|
2296
2965
|
* Get user-friendly error message for HTTP status codes.
|
|
2297
2966
|
*/
|
|
2298
|
-
|
|
2967
|
+
function getOAuth403Guidance(apiError) {
|
|
2968
|
+
if (/missing[_ -]capability/i.test(apiError ?? '')) {
|
|
2969
|
+
return 'This organization does not grant the capability required for this command. Ask an organization admin to enable it.';
|
|
2970
|
+
}
|
|
2971
|
+
if (/missing[_ -]scope/i.test(apiError ?? '')) {
|
|
2972
|
+
return 'Browser sign-in is read-only. Use `socket login --api-token` or SOCKET_CLI_API_TOKEN for scans and write operations.';
|
|
2973
|
+
}
|
|
2974
|
+
return undefined;
|
|
2975
|
+
}
|
|
2976
|
+
async function getErrorMessageForHttpStatusCode(code, apiError) {
|
|
2299
2977
|
if (code === constants.HTTP_STATUS_BAD_REQUEST) {
|
|
2300
2978
|
return 'One of the options passed might be incorrect';
|
|
2301
2979
|
}
|
|
@@ -2303,6 +2981,13 @@ async function getErrorMessageForHttpStatusCode(code) {
|
|
|
2303
2981
|
return 'Your Socket API token appears to be invalid, expired, or revoked. Please verify your token is correct and active';
|
|
2304
2982
|
}
|
|
2305
2983
|
if (code === constants.HTTP_STATUS_FORBIDDEN) {
|
|
2984
|
+
if (isOAuthLoginActive()) {
|
|
2985
|
+
const guidance = getOAuth403Guidance(apiError);
|
|
2986
|
+
if (guidance) {
|
|
2987
|
+
return guidance;
|
|
2988
|
+
}
|
|
2989
|
+
return 'Browser sign-in is read-only and does not support this operation. Use `socket login --api-token` or SOCKET_CLI_API_TOKEN';
|
|
2990
|
+
}
|
|
2306
2991
|
return 'Your Socket 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 token you are logged in with';
|
|
2307
2992
|
}
|
|
2308
2993
|
if (code === constants.HTTP_STATUS_NOT_FOUND) {
|
|
@@ -2395,15 +3080,16 @@ async function handleApiCall(value, options) {
|
|
|
2395
3080
|
debug$2.debugDir('inspect', {
|
|
2396
3081
|
sdkResult
|
|
2397
3082
|
});
|
|
2398
|
-
const errStr =
|
|
3083
|
+
const errStr = getApiErrorText(sdkResult.error);
|
|
2399
3084
|
const message = errStr || NO_ERROR_MESSAGE;
|
|
2400
|
-
const reason = sdkResult.cause || NO_ERROR_MESSAGE;
|
|
3085
|
+
const reason = getApiErrorText(sdkResult.cause) || NO_ERROR_MESSAGE;
|
|
3086
|
+
const statusReason = sdkResult.status === constants.HTTP_STATUS_FORBIDDEN && isOAuthLoginActive() ? await getErrorMessageForHttpStatusCode(sdkResult.status, `${errStr} ${reason}`) : undefined;
|
|
2401
3087
|
const baseCause = reason && message !== reason ? `${message} (reason: ${reason})` : message;
|
|
2402
3088
|
const cause = sdkResult.url ? `${baseCause} (url: ${sdkResult.url})` : baseCause;
|
|
2403
3089
|
const socketSdkErrorResult = {
|
|
2404
3090
|
ok: false,
|
|
2405
3091
|
message: 'Socket API error',
|
|
2406
|
-
cause,
|
|
3092
|
+
cause: statusReason ? `${cause} (reason: ${statusReason})` : cause,
|
|
2407
3093
|
data: {
|
|
2408
3094
|
code: sdkResult.status
|
|
2409
3095
|
}
|
|
@@ -2411,7 +3097,7 @@ async function handleApiCall(value, options) {
|
|
|
2411
3097
|
|
|
2412
3098
|
// Log required permissions for 403 errors when in a command context.
|
|
2413
3099
|
if (commandPath && sdkResult.status === 403) {
|
|
2414
|
-
logPermissionsFor403(commandPath);
|
|
3100
|
+
logPermissionsFor403(commandPath, `${errStr} ${reason}`);
|
|
2415
3101
|
}
|
|
2416
3102
|
return socketSdkErrorResult;
|
|
2417
3103
|
}
|
|
@@ -2424,56 +3110,6 @@ async function handleApiCall(value, options) {
|
|
|
2424
3110
|
};
|
|
2425
3111
|
return socketSdkSuccessResult;
|
|
2426
3112
|
}
|
|
2427
|
-
async function handleApiCallNoSpinner(value, description) {
|
|
2428
|
-
let sdkResult;
|
|
2429
|
-
try {
|
|
2430
|
-
sdkResult = await value;
|
|
2431
|
-
} catch (e) {
|
|
2432
|
-
debug$2.debugFn('error', `API request failed: ${description}`);
|
|
2433
|
-
debug$2.debugDir('error', e);
|
|
2434
|
-
const errStr = e ? String(e).trim() : '';
|
|
2435
|
-
const message = 'Socket API error';
|
|
2436
|
-
const rawCause = errStr || NO_ERROR_MESSAGE;
|
|
2437
|
-
const cause = message !== rawCause ? rawCause : '';
|
|
2438
|
-
return {
|
|
2439
|
-
ok: false,
|
|
2440
|
-
message,
|
|
2441
|
-
...(cause ? {
|
|
2442
|
-
cause
|
|
2443
|
-
} : {})
|
|
2444
|
-
};
|
|
2445
|
-
}
|
|
2446
|
-
|
|
2447
|
-
// The `success` discriminant is a concrete boolean literal in both branches,
|
|
2448
|
-
// so this narrows the result to its error branch regardless of `R`.
|
|
2449
|
-
if (sdkResult.success === false) {
|
|
2450
|
-
debug$2.debugFn('error', `fail: ${description} bad response`);
|
|
2451
|
-
debug$2.debugDir('inspect', {
|
|
2452
|
-
sdkResult
|
|
2453
|
-
});
|
|
2454
|
-
const errStr = sdkResult.error ? String(sdkResult.error).trim() : '';
|
|
2455
|
-
const message = errStr || NO_ERROR_MESSAGE;
|
|
2456
|
-
const reason = sdkResult.cause || NO_ERROR_MESSAGE;
|
|
2457
|
-
const baseCause = reason && message !== reason ? `${message} (reason: ${reason})` : message;
|
|
2458
|
-
const cause = sdkResult.url ? `${baseCause} (url: ${sdkResult.url})` : baseCause;
|
|
2459
|
-
return {
|
|
2460
|
-
ok: false,
|
|
2461
|
-
message: 'Socket API error',
|
|
2462
|
-
cause,
|
|
2463
|
-
data: {
|
|
2464
|
-
code: sdkResult.status
|
|
2465
|
-
}
|
|
2466
|
-
};
|
|
2467
|
-
} else {
|
|
2468
|
-
// Narrowing a type parameter by its `success` discriminant resolves `.data`
|
|
2469
|
-
// through the constraint's success branch (`unknown`); re-apply the precise
|
|
2470
|
-
// per-call success type the return contract already guarantees.
|
|
2471
|
-
return {
|
|
2472
|
-
ok: true,
|
|
2473
|
-
data: sdkResult.data
|
|
2474
|
-
};
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
3113
|
async function queryApi(path, apiToken) {
|
|
2478
3114
|
const baseUrl = getDefaultApiBaseUrl();
|
|
2479
3115
|
const url = `${baseUrl}${baseUrl.endsWith('/') ? '' : '/'}${path}`;
|
|
@@ -2493,12 +3129,23 @@ async function queryApi(path, apiToken) {
|
|
|
2493
3129
|
* status-dependent flows such as the cached-scan 202 poll loop.
|
|
2494
3130
|
*/
|
|
2495
3131
|
async function queryApiSafeTextWithStatus(path, description, commandPath) {
|
|
2496
|
-
|
|
3132
|
+
let apiToken;
|
|
3133
|
+
try {
|
|
3134
|
+
apiToken = await resolveDefaultApiToken({
|
|
3135
|
+
apiBaseUrl: getDefaultApiBaseUrl()
|
|
3136
|
+
});
|
|
3137
|
+
} catch (error) {
|
|
3138
|
+
return {
|
|
3139
|
+
ok: false,
|
|
3140
|
+
message: 'Authentication Error',
|
|
3141
|
+
cause: getErrorCause(error)
|
|
3142
|
+
};
|
|
3143
|
+
}
|
|
2497
3144
|
if (!apiToken) {
|
|
2498
3145
|
return {
|
|
2499
3146
|
ok: false,
|
|
2500
3147
|
message: 'Authentication Error',
|
|
2501
|
-
cause: 'User must be authenticated to run this command. Run `socket login`
|
|
3148
|
+
cause: 'User must be authenticated to run this command. Run `socket login` or set SOCKET_CLI_API_TOKEN.'
|
|
2502
3149
|
};
|
|
2503
3150
|
}
|
|
2504
3151
|
const {
|
|
@@ -2605,15 +3252,26 @@ async function queryApiSafeJson(path, description = '') {
|
|
|
2605
3252
|
* Send POST/PUT request to Socket API with JSON response handling.
|
|
2606
3253
|
*/
|
|
2607
3254
|
async function sendApiRequest(path, options) {
|
|
2608
|
-
const
|
|
3255
|
+
const baseUrl = getDefaultApiBaseUrl();
|
|
3256
|
+
let apiToken;
|
|
3257
|
+
try {
|
|
3258
|
+
apiToken = await resolveDefaultApiToken({
|
|
3259
|
+
apiBaseUrl: baseUrl
|
|
3260
|
+
});
|
|
3261
|
+
} catch (error) {
|
|
3262
|
+
return {
|
|
3263
|
+
ok: false,
|
|
3264
|
+
message: 'Authentication Error',
|
|
3265
|
+
cause: getErrorCause(error)
|
|
3266
|
+
};
|
|
3267
|
+
}
|
|
2609
3268
|
if (!apiToken) {
|
|
2610
3269
|
return {
|
|
2611
3270
|
ok: false,
|
|
2612
3271
|
message: 'Authentication Error',
|
|
2613
|
-
cause: 'User must be authenticated to run this command.
|
|
3272
|
+
cause: 'User must be authenticated to run this command. Run `socket login` or set SOCKET_CLI_API_TOKEN.'
|
|
2614
3273
|
};
|
|
2615
3274
|
}
|
|
2616
|
-
const baseUrl = getDefaultApiBaseUrl();
|
|
2617
3275
|
const {
|
|
2618
3276
|
body,
|
|
2619
3277
|
commandPath,
|
|
@@ -5472,7 +6130,16 @@ async function spawnCoana(args, orgSlug, options) {
|
|
|
5472
6130
|
// outbound axios User-Agent header.
|
|
5473
6131
|
SOCKET_CALLER_USER_AGENT: getCliUserAgent()
|
|
5474
6132
|
};
|
|
5475
|
-
|
|
6133
|
+
let defaultApiToken;
|
|
6134
|
+
try {
|
|
6135
|
+
defaultApiToken = await resolveDefaultApiToken();
|
|
6136
|
+
} catch (error) {
|
|
6137
|
+
return {
|
|
6138
|
+
ok: false,
|
|
6139
|
+
message: 'Socket authentication failed',
|
|
6140
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
6141
|
+
};
|
|
6142
|
+
}
|
|
5476
6143
|
if (defaultApiToken) {
|
|
5477
6144
|
mixinsEnv['SOCKET_CLI_API_TOKEN'] = defaultApiToken;
|
|
5478
6145
|
}
|
|
@@ -6653,6 +7320,14 @@ function isHelpFlag(cmdArg) {
|
|
|
6653
7320
|
return helpFlags.has(cmdArg);
|
|
6654
7321
|
}
|
|
6655
7322
|
|
|
7323
|
+
/**
|
|
7324
|
+
* Check if npm command requires lockfile scanning.
|
|
7325
|
+
* npm uses: install, i, update
|
|
7326
|
+
*/
|
|
7327
|
+
function isNpmLockfileScanCommand(command) {
|
|
7328
|
+
return command === 'install' || command === 'i' || command === 'ci' || command === 'update';
|
|
7329
|
+
}
|
|
7330
|
+
|
|
6656
7331
|
/**
|
|
6657
7332
|
* Check if pnpm command requires lockfile scanning.
|
|
6658
7333
|
* pnpm uses: install, i, update, up
|
|
@@ -6726,10 +7401,10 @@ function parseReachEcosystems(raw) {
|
|
|
6726
7401
|
* within an ecosystem (e.g. only PNPM artifacts in a mixed pnpm/yarn/npm repo).
|
|
6727
7402
|
*
|
|
6728
7403
|
* Mirrors the list returned by Coana's `getFilterablePackageManagers()` in
|
|
6729
|
-
* packages/
|
|
7404
|
+
* packages/utils/src/package-manager-utils.ts.
|
|
6730
7405
|
*/
|
|
6731
7406
|
|
|
6732
|
-
const ALL_PACKAGE_MANAGERS = ['CARGO', 'COMPOSER', 'GO', 'GRADLE', 'MAVEN', 'NPM', 'NUGET', 'PIPENV', 'PIP_REQUIREMENTS', 'PNPM', 'POETRY', 'RUBYGEMS', 'RUSH', 'SBT', 'YARN'];
|
|
7407
|
+
const ALL_PACKAGE_MANAGERS = ['CARGO', 'COMPOSER', 'GO', 'GRADLE', 'MAVEN', 'NPM', 'NUGET', 'PIPENV', 'PIP_REQUIREMENTS', 'PNPM', 'POETRY', 'RUBYGEMS', 'RUSH', 'SBT', 'UV', 'YARN'];
|
|
6733
7408
|
const ALL_PACKAGE_MANAGERS_SET = new Set(ALL_PACKAGE_MANAGERS);
|
|
6734
7409
|
function isValidPackageManager(value) {
|
|
6735
7410
|
return ALL_PACKAGE_MANAGERS_SET.has(value);
|
|
@@ -7185,10 +7860,10 @@ function shadowNpmInstall(options) {
|
|
|
7185
7860
|
const useDebug = debug$2.isDebug('stdio');
|
|
7186
7861
|
const terminatorPos = args.indexOf('--');
|
|
7187
7862
|
const rawBinArgs = terminatorPos === -1 ? args : args.slice(0, terminatorPos);
|
|
7188
|
-
const binArgs = rawBinArgs.filter(a => !agent.isNpmAuditFlag(a) && !agent.isNpmFundFlag(a) && !agent.isNpmProgressFlag(a));
|
|
7863
|
+
const binArgs = rawBinArgs.filter(a => !agent$1.isNpmAuditFlag(a) && !agent$1.isNpmFundFlag(a) && !agent$1.isNpmProgressFlag(a));
|
|
7189
7864
|
const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
|
|
7190
|
-
const progressArg = rawBinArgs.findLast(agent.isNpmProgressFlag) !== '--no-progress';
|
|
7191
|
-
const isSilent = !useDebug && !binArgs.some(agent.isNpmLoglevelFlag);
|
|
7865
|
+
const progressArg = rawBinArgs.findLast(agent$1.isNpmProgressFlag) !== '--no-progress';
|
|
7866
|
+
const isSilent = !useDebug && !binArgs.some(agent$1.isNpmLoglevelFlag);
|
|
7192
7867
|
const logLevelArgs = isSilent ? [constants.FLAG_LOGLEVEL, 'silent'] : [];
|
|
7193
7868
|
const useIpc = objects.isObject(ipc);
|
|
7194
7869
|
|
|
@@ -7205,7 +7880,7 @@ function shadowNpmInstall(options) {
|
|
|
7205
7880
|
} else {
|
|
7206
7881
|
stdio = useIpc ? ['pipe', 'pipe', 'pipe', 'ipc'] : 'pipe';
|
|
7207
7882
|
}
|
|
7208
|
-
const spawnPromise = spawn.spawn(constants.default.execPath, [...constants.default.nodeNoWarningsFlags, ...constants.default.nodeDebugFlags, ...constants.default.nodeHardenFlags, ...constants.default.nodeMemoryFlags, ...(constants.default.ENV.INLINED_SOCKET_CLI_SENTRY_BUILD ? ['--require', constants.default.instrumentWithSentryPath] : []), '--require', constants.default.shadowNpmInjectPath, agent.resolveBinPathSync(agentExecPath), 'install',
|
|
7883
|
+
const spawnPromise = spawn.spawn(constants.default.execPath, [...constants.default.nodeNoWarningsFlags, ...constants.default.nodeDebugFlags, ...constants.default.nodeHardenFlags, ...constants.default.nodeMemoryFlags, ...(constants.default.ENV.INLINED_SOCKET_CLI_SENTRY_BUILD ? ['--require', constants.default.instrumentWithSentryPath] : []), '--require', constants.default.shadowNpmInjectPath, agent$1.resolveBinPathSync(agentExecPath), 'install',
|
|
7209
7884
|
// Avoid code paths for 'audit' and 'fund'.
|
|
7210
7885
|
'--no-audit', '--no-fund',
|
|
7211
7886
|
// Add '--no-progress' to fix input being swallowed by the npm spinner.
|
|
@@ -9104,8 +9779,10 @@ exports.CVE_FORMAT_REGEXP = CVE_FORMAT_REGEXP;
|
|
|
9104
9779
|
exports.GHSA_FORMAT_REGEXP = GHSA_FORMAT_REGEXP;
|
|
9105
9780
|
exports.IGNORED_DIRS = IGNORED_DIRS;
|
|
9106
9781
|
exports.InputError = InputError;
|
|
9782
|
+
exports.OAUTH_ISSUER = OAUTH_ISSUER;
|
|
9107
9783
|
exports.RangeStyles = RangeStyles;
|
|
9108
9784
|
exports.apiFetch = apiFetch;
|
|
9785
|
+
exports.beginOAuthLogin = beginOAuthLogin;
|
|
9109
9786
|
exports.cacheFetch = cacheFetch;
|
|
9110
9787
|
exports.camelToKebab = camelToKebab;
|
|
9111
9788
|
exports.captureException = captureException;
|
|
@@ -9141,7 +9818,9 @@ exports.getBaseBranch = getBaseBranch;
|
|
|
9141
9818
|
exports.getBashrcDetails = getBashrcDetails;
|
|
9142
9819
|
exports.getConfigValue = getConfigValue;
|
|
9143
9820
|
exports.getConfigValueOrUndef = getConfigValueOrUndef;
|
|
9821
|
+
exports.getDefaultApiBaseUrl = getDefaultApiBaseUrl$1;
|
|
9144
9822
|
exports.getDefaultOrgSlug = getDefaultOrgSlug;
|
|
9823
|
+
exports.getDefaultProxyUrl = getDefaultProxyUrl;
|
|
9145
9824
|
exports.getEcosystemChoicesForMeow = getEcosystemChoicesForMeow;
|
|
9146
9825
|
exports.getEnterpriseOrgs = getEnterpriseOrgs;
|
|
9147
9826
|
exports.getErrorCause = getErrorCause;
|
|
@@ -9160,7 +9839,6 @@ exports.getOrInsert = getOrInsert;
|
|
|
9160
9839
|
exports.getOrgSlugs = getOrgSlugs;
|
|
9161
9840
|
exports.getOutputKind = getOutputKind;
|
|
9162
9841
|
exports.getPackageFilesForScan = getPackageFilesForScan;
|
|
9163
|
-
exports.getPublicApiToken = getPublicApiToken;
|
|
9164
9842
|
exports.getReachabilityEcosystemChoices = getReachabilityEcosystemChoices;
|
|
9165
9843
|
exports.getRepoInfo = getRepoInfo;
|
|
9166
9844
|
exports.getRepoName = getRepoName;
|
|
@@ -9184,7 +9862,6 @@ exports.githubApiRequest = githubApiRequest;
|
|
|
9184
9862
|
exports.globWithGitIgnore = globWithGitIgnore;
|
|
9185
9863
|
exports.globWorkspace = globWorkspace;
|
|
9186
9864
|
exports.handleApiCall = handleApiCall;
|
|
9187
|
-
exports.handleApiCallNoSpinner = handleApiCallNoSpinner;
|
|
9188
9865
|
exports.hasDefaultApiToken = hasDefaultApiToken;
|
|
9189
9866
|
exports.hasEnterpriseOrgPlan = hasEnterpriseOrgPlan;
|
|
9190
9867
|
exports.idToNpmPurl = idToNpmPurl;
|
|
@@ -9198,6 +9875,7 @@ exports.isErrnoException = isErrnoException;
|
|
|
9198
9875
|
exports.isFactsOnlyTypes = isFactsOnlyTypes;
|
|
9199
9876
|
exports.isGitHubBlockingError = isGitHubBlockingError;
|
|
9200
9877
|
exports.isHelpFlag = isHelpFlag;
|
|
9878
|
+
exports.isNpmLockfileScanCommand = isNpmLockfileScanCommand;
|
|
9201
9879
|
exports.isPnpmLockfileScanCommand = isPnpmLockfileScanCommand;
|
|
9202
9880
|
exports.isReachabilityReportPath = isReachabilityReportPath;
|
|
9203
9881
|
exports.isReportSupportedFile = isReportSupportedFile;
|
|
@@ -9208,6 +9886,7 @@ exports.isValidPackageManager = isValidPackageManager;
|
|
|
9208
9886
|
exports.isYarnBerry = isYarnBerry;
|
|
9209
9887
|
exports.loadSocketConfig = loadSocketConfig;
|
|
9210
9888
|
exports.logAlertsMap = logAlertsMap;
|
|
9889
|
+
exports.logoutOAuth = logoutOAuth;
|
|
9211
9890
|
exports.mailtoLink = mailtoLink;
|
|
9212
9891
|
exports.mapToObject = mapToObject;
|
|
9213
9892
|
exports.mdTable = mdTable;
|
|
@@ -9229,10 +9908,12 @@ exports.readSocketJsonCascade = readSocketJsonCascade;
|
|
|
9229
9908
|
exports.readSocketJsonSync = readSocketJsonSync;
|
|
9230
9909
|
exports.realpathOrResolved = realpathOrResolved;
|
|
9231
9910
|
exports.resolveAdvisoryIds = resolveAdvisoryIds;
|
|
9911
|
+
exports.resolvePublicApiToken = resolvePublicApiToken;
|
|
9232
9912
|
exports.runAgentInstall = runAgentInstall;
|
|
9233
9913
|
exports.runSelfUpdateCheck = runSelfUpdateCheck;
|
|
9234
9914
|
exports.safeNpa = safeNpa$1;
|
|
9235
9915
|
exports.safeNpmSpecToPurl = safeNpmSpecToPurl;
|
|
9916
|
+
exports.saveOAuthCredentials = saveOAuthCredentials;
|
|
9236
9917
|
exports.sendApiRequest = sendApiRequest;
|
|
9237
9918
|
exports.serializeResultJson = serializeResultJson;
|
|
9238
9919
|
exports.setGitRemoteGithubRepoUrl = setGitRemoteGithubRepoUrl;
|
|
@@ -9260,5 +9941,5 @@ exports.walkNestedMap = walkNestedMap;
|
|
|
9260
9941
|
exports.webLink = webLink;
|
|
9261
9942
|
exports.withTmpDir = withTmpDir;
|
|
9262
9943
|
exports.writeSocketJson = writeSocketJson;
|
|
9263
|
-
//# debugId=
|
|
9944
|
+
//# debugId=ead18e45-7f35-4138-8864-de9f0791c0e
|
|
9264
9945
|
//# sourceMappingURL=utils.js.map
|