@socketsecurity/cli-with-sentry 1.1.147 → 1.1.152
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 +16 -0
- package/DISCLOSURE +45 -0
- package/dist/cli.js +680 -485
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +6 -6
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.js +3 -3
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/manifest-scripts/maven-extension/coana-maven-extension.jar +0 -0
- package/dist/shadow-npm-bin2.js +6 -6
- package/dist/shadow-npm-bin2.js.map +1 -1
- package/dist/shadow-npm-inject.js +10 -10
- package/dist/shadow-npm-inject.js.map +1 -1
- package/dist/shadow-pnpm-bin2.js +13 -13
- package/dist/shadow-pnpm-bin2.js.map +1 -1
- package/dist/shadow-yarn-bin.js +3 -3
- package/dist/shadow-yarn-bin.js.map +1 -1
- package/dist/socket-completion.bash +0 -0
- package/dist/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/types/commands/audit-log/output-audit-log.d.mts.map +1 -1
- package/dist/types/commands/ci/handle-ci.d.mts.map +1 -1
- package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
- package/dist/types/commands/manifest/cmd-manifest-auto.d.mts.map +1 -1
- package/dist/types/commands/manifest/cmd-manifest-scala.d.mts.map +1 -1
- package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts +3 -1
- package/dist/types/commands/manifest/convert-sbt-to-facts.d.mts.map +1 -1
- package/dist/types/commands/manifest/generate_auto_manifest.d.mts +4 -1
- package/dist/types/commands/manifest/generate_auto_manifest.d.mts.map +1 -1
- package/dist/types/commands/manifest/run-manifest-facts.d.mts +3 -1
- package/dist/types/commands/manifest/run-manifest-facts.d.mts.map +1 -1
- package/dist/types/commands/manifest/scripts/run.d.mts +8 -0
- package/dist/types/commands/manifest/scripts/run.d.mts.map +1 -1
- package/dist/types/commands/organization/fetch-organization-list.d.mts +2 -2
- package/dist/types/commands/organization/fetch-organization-list.d.mts.map +1 -1
- package/dist/types/commands/package/output-purls-shallow-score.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-create-repo.d.mts +2 -2
- package/dist/types/commands/repository/fetch-create-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-delete-repo.d.mts +2 -2
- package/dist/types/commands/repository/fetch-delete-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-list-all-repos.d.mts +2 -2
- package/dist/types/commands/repository/fetch-list-all-repos.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-list-repos.d.mts +2 -2
- package/dist/types/commands/repository/fetch-list-repos.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-update-repo.d.mts +2 -2
- package/dist/types/commands/repository/fetch-update-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/fetch-view-repo.d.mts +2 -2
- package/dist/types/commands/repository/fetch-view-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/handle-list-repos.d.mts.map +1 -1
- package/dist/types/commands/repository/output-create-repo.d.mts +2 -2
- package/dist/types/commands/repository/output-create-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/output-delete-repo.d.mts +2 -2
- package/dist/types/commands/repository/output-delete-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/output-list-repos.d.mts +2 -2
- package/dist/types/commands/repository/output-list-repos.d.mts.map +1 -1
- package/dist/types/commands/repository/output-update-repo.d.mts +2 -2
- package/dist/types/commands/repository/output-update-repo.d.mts.map +1 -1
- package/dist/types/commands/repository/output-view-repo.d.mts +2 -2
- package/dist/types/commands/repository/output-view-repo.d.mts.map +1 -1
- package/dist/types/commands/scan/cmd-scan-create.d.mts.map +1 -1
- package/dist/types/commands/scan/cmd-scan-reach.d.mts.map +1 -1
- package/dist/types/commands/scan/create-scan-from-github.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-create-org-full-scan.d.mts +2 -2
- package/dist/types/commands/scan/fetch-create-org-full-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-delete-org-full-scan.d.mts +2 -2
- package/dist/types/commands/scan/fetch-delete-org-full-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-list-scans.d.mts +2 -2
- package/dist/types/commands/scan/fetch-list-scans.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-scan-metadata.d.mts +2 -2
- package/dist/types/commands/scan/fetch-scan-metadata.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-scan.d.mts +4 -0
- package/dist/types/commands/scan/fetch-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts +2 -1
- package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts.map +1 -1
- package/dist/types/commands/scan/handle-create-new-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/handle-scan-reach.d.mts.map +1 -1
- package/dist/types/commands/scan/output-create-new-scan.d.mts +2 -2
- package/dist/types/commands/scan/output-create-new-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/output-delete-scan.d.mts +2 -2
- package/dist/types/commands/scan/output-delete-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/output-list-scans.d.mts +2 -2
- package/dist/types/commands/scan/output-list-scans.d.mts.map +1 -1
- package/dist/types/commands/scan/output-scan-metadata.d.mts +2 -2
- package/dist/types/commands/scan/output-scan-metadata.d.mts.map +1 -1
- package/dist/types/commands/scan/perform-reachability-analysis.d.mts +1 -0
- package/dist/types/commands/scan/perform-reachability-analysis.d.mts.map +1 -1
- package/dist/types/commands/scan/reachability-flags.d.mts.map +1 -1
- package/dist/types/commands/scan/stream-scan.d.mts +3 -1
- package/dist/types/commands/scan/stream-scan.d.mts.map +1 -1
- package/dist/types/utils/api.d.mts +49 -4
- package/dist/types/utils/api.d.mts.map +1 -1
- package/dist/types/utils/ecosystem.d.mts +1 -1
- package/dist/types/utils/ecosystem.d.mts.map +1 -1
- package/dist/types/utils/fs.d.mts +1 -0
- package/dist/types/utils/fs.d.mts.map +1 -1
- package/dist/types/utils/glob.d.mts +4 -4
- package/dist/types/utils/glob.d.mts.map +1 -1
- package/dist/types/utils/path-resolve.d.mts +1 -1
- package/dist/types/utils/path-resolve.d.mts.map +1 -1
- package/dist/types/utils/sdk.d.mts +5 -0
- package/dist/types/utils/sdk.d.mts.map +1 -1
- package/dist/types/utils/socket-package-alert.d.mts.map +1 -1
- package/dist/utils.js +268 -188
- package/dist/utils.js.map +1 -1
- package/dist/vendor.js +9530 -1726
- package/package.json +63 -133
- package/shadow-bin/npm +0 -0
- package/shadow-bin/npx +0 -0
- package/shadow-bin/pnpm +0 -0
- package/shadow-bin/yarn +0 -0
package/dist/cli.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
var require$$0$1 = require('node:url');
|
|
5
5
|
var vendor = require('./vendor.js');
|
|
6
|
-
var
|
|
6
|
+
var debug = require('../external/@socketsecurity/registry/lib/debug');
|
|
7
7
|
var logger = require('../external/@socketsecurity/registry/lib/logger');
|
|
8
8
|
var utils = require('./utils.js');
|
|
9
9
|
var fs = require('node:fs/promises');
|
|
10
|
-
var require$$
|
|
10
|
+
var require$$1 = require('node:module');
|
|
11
11
|
var constants = require('./constants.js');
|
|
12
12
|
var flags = require('./flags.js');
|
|
13
13
|
var path = require('node:path');
|
|
@@ -23,13 +23,13 @@ var childProcess = require('node:child_process');
|
|
|
23
23
|
var fs$2 = require('../external/@socketsecurity/registry/lib/fs');
|
|
24
24
|
var strings = require('../external/@socketsecurity/registry/lib/strings');
|
|
25
25
|
var path$1 = require('../external/@socketsecurity/registry/lib/path');
|
|
26
|
-
var
|
|
26
|
+
var objects = require('../external/@socketsecurity/registry/lib/objects');
|
|
27
27
|
var registry = require('../external/@socketsecurity/registry');
|
|
28
28
|
var packages = require('../external/@socketsecurity/registry/lib/packages');
|
|
29
|
-
var
|
|
29
|
+
var promises = require('../external/@socketsecurity/registry/lib/promises');
|
|
30
30
|
var regexps = require('../external/@socketsecurity/registry/lib/regexps');
|
|
31
|
-
var require$$
|
|
32
|
-
var
|
|
31
|
+
var require$$10 = require('node:util');
|
|
32
|
+
var require$$9 = require('node:stream/promises');
|
|
33
33
|
|
|
34
34
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
35
35
|
async function fetchOrgAnalyticsData(time, options) {
|
|
@@ -68,7 +68,7 @@ async function fetchRepoAnalyticsData(repo, time, options) {
|
|
|
68
68
|
|
|
69
69
|
// Note: Widgets does not seem to actually work as code :'(
|
|
70
70
|
|
|
71
|
-
const require$7 = require$$
|
|
71
|
+
const require$7 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
72
72
|
const METRICS = ['total_critical_alerts', 'total_high_alerts', 'total_medium_alerts', 'total_low_alerts', 'total_critical_added', 'total_medium_added', 'total_low_added', 'total_high_added', 'total_critical_prevented', 'total_high_prevented', 'total_medium_prevented', 'total_low_prevented'];
|
|
73
73
|
|
|
74
74
|
// Note: This maps `new Date(date).getMonth()` to English three letters
|
|
@@ -504,7 +504,7 @@ async function fetchAuditLog(config, options) {
|
|
|
504
504
|
});
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
const require$6 = require$$
|
|
507
|
+
const require$6 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
508
508
|
async function outputAuditLog(result, {
|
|
509
509
|
logType,
|
|
510
510
|
orgSlug,
|
|
@@ -619,8 +619,8 @@ ${table}
|
|
|
619
619
|
} catch (e) {
|
|
620
620
|
process.exitCode = 1;
|
|
621
621
|
logger.logger.fail(`There was a problem converting the logs to Markdown, please try the \`${constants.FLAG_JSON}\` flag`);
|
|
622
|
-
|
|
623
|
-
|
|
622
|
+
debug.debugFn('error', 'Markdown conversion failed');
|
|
623
|
+
debug.debugDir('error', e);
|
|
624
624
|
return 'Failed to generate the markdown report';
|
|
625
625
|
}
|
|
626
626
|
}
|
|
@@ -1100,7 +1100,8 @@ async function fetchCreateOrgFullScan(packagePaths, orgSlug, config, options) {
|
|
|
1100
1100
|
}));
|
|
1101
1101
|
logger.logger.info(`[DEBUG] ${new Date().toISOString()} Uploading full scan manifests: ${JSON.stringify(fileInfo)}`);
|
|
1102
1102
|
}
|
|
1103
|
-
return await utils.handleApiCall(sockSdk.
|
|
1103
|
+
return await utils.handleApiCall(sockSdk.createFullScan(orgSlug, packagePaths, {
|
|
1104
|
+
pathsRelativeTo: cwd,
|
|
1104
1105
|
...(branchName ? {
|
|
1105
1106
|
branch: branchName
|
|
1106
1107
|
} : {}),
|
|
@@ -1113,17 +1114,25 @@ async function fetchCreateOrgFullScan(packagePaths, orgSlug, config, options) {
|
|
|
1113
1114
|
...(committers ? {
|
|
1114
1115
|
committers
|
|
1115
1116
|
} : {}),
|
|
1116
|
-
|
|
1117
|
+
...(defaultBranch !== undefined ? {
|
|
1118
|
+
make_default_branch: defaultBranch
|
|
1119
|
+
} : {}),
|
|
1117
1120
|
...(pullRequest ? {
|
|
1118
|
-
pull_request:
|
|
1121
|
+
pull_request: pullRequest
|
|
1122
|
+
} : {}),
|
|
1123
|
+
...(scanType ? {
|
|
1124
|
+
scan_type: scanType
|
|
1119
1125
|
} : {}),
|
|
1120
|
-
scan_type: scanType,
|
|
1121
1126
|
repo: repoName,
|
|
1122
1127
|
...(workspace ? {
|
|
1123
1128
|
workspace
|
|
1124
1129
|
} : {}),
|
|
1125
|
-
|
|
1126
|
-
|
|
1130
|
+
...(pendingHead !== undefined ? {
|
|
1131
|
+
set_as_pending_head: pendingHead
|
|
1132
|
+
} : {}),
|
|
1133
|
+
...(tmp !== undefined ? {
|
|
1134
|
+
tmp
|
|
1135
|
+
} : {})
|
|
1127
1136
|
}), {
|
|
1128
1137
|
description: 'to create a scan'
|
|
1129
1138
|
});
|
|
@@ -1131,6 +1140,7 @@ async function fetchCreateOrgFullScan(packagePaths, orgSlug, config, options) {
|
|
|
1131
1140
|
|
|
1132
1141
|
async function fetchSupportedScanFileNames(options) {
|
|
1133
1142
|
const {
|
|
1143
|
+
orgSlug,
|
|
1134
1144
|
sdkOpts,
|
|
1135
1145
|
silence = false,
|
|
1136
1146
|
spinner
|
|
@@ -1143,7 +1153,18 @@ async function fetchSupportedScanFileNames(options) {
|
|
|
1143
1153
|
return sockSdkCResult;
|
|
1144
1154
|
}
|
|
1145
1155
|
const sockSdk = sockSdkCResult.data;
|
|
1146
|
-
|
|
1156
|
+
|
|
1157
|
+
// getSupportedFiles is org-scoped in SDK v4. Use the provided org or
|
|
1158
|
+
// discover the default one.
|
|
1159
|
+
let resolvedOrgSlug = orgSlug;
|
|
1160
|
+
if (!resolvedOrgSlug) {
|
|
1161
|
+
const orgSlugCResult = await utils.getDefaultOrgSlug();
|
|
1162
|
+
if (!orgSlugCResult.ok) {
|
|
1163
|
+
return orgSlugCResult;
|
|
1164
|
+
}
|
|
1165
|
+
resolvedOrgSlug = orgSlugCResult.data;
|
|
1166
|
+
}
|
|
1167
|
+
return await utils.handleApiCall(sockSdk.getSupportedFiles(resolvedOrgSlug), {
|
|
1147
1168
|
description: 'supported scan file types',
|
|
1148
1169
|
spinner,
|
|
1149
1170
|
silence
|
|
@@ -1226,8 +1247,8 @@ async function fetchScanData(orgSlug, scanId, options) {
|
|
|
1226
1247
|
return JSON.parse(line);
|
|
1227
1248
|
} catch (e) {
|
|
1228
1249
|
ok = false;
|
|
1229
|
-
|
|
1230
|
-
|
|
1250
|
+
debug.debugFn('error', 'Failed to parse report data line as JSON');
|
|
1251
|
+
debug.debugDir('error', {
|
|
1231
1252
|
error: e,
|
|
1232
1253
|
line
|
|
1233
1254
|
});
|
|
@@ -1853,7 +1874,9 @@ async function performReachabilityAnalysis(options) {
|
|
|
1853
1874
|
// legitimate INPUT to compute-artifacts, so we now upload them. Stale
|
|
1854
1875
|
// facts files are cleaned up downstream — see the post-success
|
|
1855
1876
|
// deletion in handle-create-new-scan.mts.
|
|
1856
|
-
const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, packagePaths,
|
|
1877
|
+
const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, packagePaths, {
|
|
1878
|
+
pathsRelativeTo: path.resolve(cwd, analysisTarget)
|
|
1879
|
+
}), {
|
|
1857
1880
|
description: 'upload manifests',
|
|
1858
1881
|
spinner
|
|
1859
1882
|
});
|
|
@@ -1893,7 +1916,7 @@ async function performReachabilityAnalysis(options) {
|
|
|
1893
1916
|
// Build Coana arguments.
|
|
1894
1917
|
const coanaArgs = ['run', analysisTarget, '--output-dir', path.dirname(outputFilePath), '--socket-mode', outputFilePath, '--disable-report-submission', ...(isOmittedReachValue(reachabilityOptions.reachAnalysisTimeout) ? [] : ['--analysis-timeout', reachabilityOptions.reachAnalysisTimeout]), ...(isOmittedReachValue(reachabilityOptions.reachAnalysisMemoryLimit) ? [] : ['--memory-limit', reachabilityOptions.reachAnalysisMemoryLimit]), ...(reachabilityOptions.reachConcurrency ? ['--concurrency', `${reachabilityOptions.reachConcurrency}`] : []), ...(reachabilityOptions.reachContinueOnAnalysisErrors ? ['--reach-continue-on-analysis-errors'] : []), ...(reachabilityOptions.reachContinueOnInstallErrors ? ['--reach-continue-on-install-errors'] : []), ...(reachabilityOptions.reachContinueOnMissingLockFiles ? ['--reach-continue-on-missing-lock-files'] : []), ...(reachabilityOptions.reachContinueOnNoSourceFiles ? ['--reach-continue-on-no-source-files'] : []), ...(reachabilityOptions.reachDebug ? ['--debug'] : []), ...(reachabilityOptions.reachDetailedAnalysisLogFile ? ['--print-analysis-log-file'] : []), ...(reachabilityOptions.reachDisableAnalytics ? ['--disable-analytics-sharing'] : []), ...(reachabilityOptions.reachDisableExternalToolChecks ? ['--disable-external-tool-checks'] : []), ...(reachabilityOptions.reachEnableAnalysisSplitting ? [] : ['--disable-analysis-splitting']), ...(tarHash ? ['--run-without-docker', '--manifests-tar-hash', tarHash] : []),
|
|
1895
1918
|
// Empty reachEcosystems implies scanning all ecosystems.
|
|
1896
|
-
...(reachabilityOptions.reachEcosystems.length ? ['--purl-types', ...reachabilityOptions.reachEcosystems] : []), ...(reachabilityOptions.reachExcludePaths.length ? ['--exclude-dirs', ...reachabilityOptions.reachExcludePaths] : []), ...(reachabilityOptions.reachLazyMode ? ['--lazy-mode'] : []), ...(reachabilityOptions.reachSkipCache ? ['--skip-cache-usage'] : []), ...(reachabilityOptions.reachUseOnlyPregeneratedSboms ? ['--use-only-pregenerated-sboms'] : []), ...(sidecarPath ? ['--compute-artifacts-sidecar', sidecarPath] : [])];
|
|
1919
|
+
...(reachabilityOptions.reachEcosystems.length ? ['--purl-types', ...reachabilityOptions.reachEcosystems] : []), ...(reachabilityOptions.reachExcludePaths.length ? ['--exclude-dirs', ...reachabilityOptions.reachExcludePaths] : []), ...(reachabilityOptions.dynamicSbomInference ? ['--maven-use-only-root-socket-facts'] : []), ...(reachabilityOptions.reachLazyMode ? ['--lazy-mode'] : []), ...(reachabilityOptions.reachSkipCache ? ['--skip-cache-usage'] : []), ...(reachabilityOptions.reachUseOnlyPregeneratedSboms ? ['--use-only-pregenerated-sboms'] : []), ...(sidecarPath ? ['--compute-artifacts-sidecar', sidecarPath] : [])];
|
|
1897
1920
|
|
|
1898
1921
|
// Build environment variables.
|
|
1899
1922
|
const coanaEnv = {};
|
|
@@ -1979,44 +2002,44 @@ sockJson, cwd = process.cwd()) {
|
|
|
1979
2002
|
sbt: false
|
|
1980
2003
|
};
|
|
1981
2004
|
if (sockJson?.defaults?.manifest?.bazel?.disabled) {
|
|
1982
|
-
|
|
2005
|
+
debug.debugLog('notice', `[DEBUG] - bazel auto-detection is disabled in ${constants.SOCKET_JSON}`);
|
|
1983
2006
|
} else if (fs$1.existsSync(path.join(cwd, 'MODULE.bazel')) || fs$1.existsSync(path.join(cwd, 'WORKSPACE')) || fs$1.existsSync(path.join(cwd, 'WORKSPACE.bazel'))) {
|
|
1984
|
-
|
|
2007
|
+
debug.debugLog('notice', '[DEBUG] - Detected a Bazel workspace');
|
|
1985
2008
|
output.bazel = true;
|
|
1986
2009
|
output.count += 1;
|
|
1987
2010
|
}
|
|
1988
2011
|
if (sockJson?.defaults?.manifest?.sbt?.disabled) {
|
|
1989
|
-
|
|
2012
|
+
debug.debugLog('notice', `[DEBUG] - sbt auto-detection is disabled in ${constants.SOCKET_JSON}`);
|
|
1990
2013
|
} else if (fs$1.existsSync(path.join(cwd, 'build.sbt'))) {
|
|
1991
|
-
|
|
2014
|
+
debug.debugLog('notice', '[DEBUG] - Detected a Scala sbt build file');
|
|
1992
2015
|
output.sbt = true;
|
|
1993
2016
|
output.count += 1;
|
|
1994
2017
|
}
|
|
1995
2018
|
if (sockJson?.defaults?.manifest?.gradle?.disabled) {
|
|
1996
|
-
|
|
2019
|
+
debug.debugLog('notice', `[DEBUG] - gradle auto-detection is disabled in ${constants.SOCKET_JSON}`);
|
|
1997
2020
|
} else if (fs$1.existsSync(path.join(cwd, 'build.gradle')) || fs$1.existsSync(path.join(cwd, 'build.gradle.kts')) || fs$1.existsSync(path.join(cwd, 'settings.gradle')) || fs$1.existsSync(path.join(cwd, 'settings.gradle.kts'))) {
|
|
1998
2021
|
// Detect by build descriptor, not the `gradlew` wrapper (a project can build via
|
|
1999
2022
|
// `gradle` on PATH). `settings.gradle(.kts)` covers Kotlin-DSL roots with no root build script.
|
|
2000
|
-
|
|
2023
|
+
debug.debugLog('notice', '[DEBUG] - Detected a gradle build file');
|
|
2001
2024
|
output.gradle = true;
|
|
2002
2025
|
output.count += 1;
|
|
2003
2026
|
}
|
|
2004
2027
|
if (sockJson?.defaults?.manifest?.maven?.disabled) {
|
|
2005
|
-
|
|
2028
|
+
debug.debugLog('notice', `[DEBUG] - maven auto-detection is disabled in ${constants.SOCKET_JSON}`);
|
|
2006
2029
|
} else if (fs$1.existsSync(path.join(cwd, 'pom.xml'))) {
|
|
2007
|
-
|
|
2030
|
+
debug.debugLog('notice', '[DEBUG] - Detected a Maven pom.xml build file');
|
|
2008
2031
|
output.maven = true;
|
|
2009
2032
|
output.count += 1;
|
|
2010
2033
|
}
|
|
2011
2034
|
if (sockJson?.defaults?.manifest?.conda?.disabled) {
|
|
2012
|
-
|
|
2035
|
+
debug.debugLog('notice', `[DEBUG] - conda auto-detection is disabled in ${constants.SOCKET_JSON}`);
|
|
2013
2036
|
} else {
|
|
2014
2037
|
const envyml = path.join(cwd, constants.ENVIRONMENT_YML);
|
|
2015
2038
|
const hasEnvyml = fs$1.existsSync(envyml);
|
|
2016
2039
|
const envyaml = path.join(cwd, constants.ENVIRONMENT_YAML);
|
|
2017
2040
|
const hasEnvyaml = !hasEnvyml && fs$1.existsSync(envyaml);
|
|
2018
2041
|
if (hasEnvyml || hasEnvyaml) {
|
|
2019
|
-
|
|
2042
|
+
debug.debugLog('notice', '[DEBUG] - Detected an environment.yml Conda file');
|
|
2020
2043
|
output.conda = true;
|
|
2021
2044
|
output.count += 1;
|
|
2022
2045
|
}
|
|
@@ -4978,8 +5001,8 @@ function buildArtifactPaths(finalNodes, projects, fileExists) {
|
|
|
4978
5001
|
}
|
|
4979
5002
|
coords.add(coordKey);
|
|
4980
5003
|
const pi = projectsByGav.get(gav(c.group, c.name, c.version ?? ''));
|
|
4981
|
-
const sources = (pi?.sources ?? []).filter(fileExists);
|
|
4982
|
-
const targets = [...new Set(
|
|
5004
|
+
const sources = (pi?.sources ?? []).filter(fileExists).sort();
|
|
5005
|
+
const targets = [...new Set(pi ? pi.targets : fn.targets)].filter(fileExists).sort();
|
|
4983
5006
|
if (sources.length) {
|
|
4984
5007
|
sourcesByCoord.set(coordKey, sources);
|
|
4985
5008
|
}
|
|
@@ -5306,17 +5329,6 @@ async function runNeverThrow(bin, args, opts) {
|
|
|
5306
5329
|
throw e;
|
|
5307
5330
|
}
|
|
5308
5331
|
}
|
|
5309
|
-
async function withTmpDir(prefix, fn) {
|
|
5310
|
-
const tmpDir = await fs$1.promises.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
5311
|
-
try {
|
|
5312
|
-
return await fn(tmpDir);
|
|
5313
|
-
} finally {
|
|
5314
|
-
await fs$1.promises.rm(tmpDir, {
|
|
5315
|
-
recursive: true,
|
|
5316
|
-
force: true
|
|
5317
|
-
}).catch(() => {});
|
|
5318
|
-
}
|
|
5319
|
-
}
|
|
5320
5332
|
async function writeSbtPlugin(globalBase) {
|
|
5321
5333
|
const src = await fs$1.promises.readFile(manifestScriptsPath('socket-facts.plugin.scala'), 'utf8');
|
|
5322
5334
|
const pluginsDir = path.join(globalBase, 'plugins');
|
|
@@ -5386,7 +5398,7 @@ function commonProps(opts, prefix) {
|
|
|
5386
5398
|
}
|
|
5387
5399
|
async function runGradle(opts) {
|
|
5388
5400
|
const initScript = manifestScriptsPath('socket-facts.init.gradle');
|
|
5389
|
-
return await withTmpDir('socket-gradle-facts-', async tmp => {
|
|
5401
|
+
return await utils.withTmpDir('socket-gradle-facts-', async tmp => {
|
|
5390
5402
|
const recordsFile = path.join(tmp, 'records.tsv');
|
|
5391
5403
|
const bin = resolveBuildToolBin('gradle', opts.projectDir, opts.bin);
|
|
5392
5404
|
// Disable the configuration cache: the init script's legacy
|
|
@@ -5396,27 +5408,35 @@ async function runGradle(opts) {
|
|
|
5396
5408
|
return await assembleFromRecords(out, recordsFile);
|
|
5397
5409
|
});
|
|
5398
5410
|
}
|
|
5411
|
+
async function runSbtIn(globalBase, opts) {
|
|
5412
|
+
await writeSbtPlugin(globalBase);
|
|
5413
|
+
const recordsFile = path.join(globalBase, 'records.tsv');
|
|
5414
|
+
const bin = resolveBuildToolBin('sbt', opts.projectDir, opts.bin);
|
|
5415
|
+
// Fresh per-run global base (not ~/.sbt): sbt executes everything under
|
|
5416
|
+
// plugins/, so a shared path is a code-injection surface. BSP off for this
|
|
5417
|
+
// run. sbt also provisions the project's Scala toolchain under
|
|
5418
|
+
// <global.base>/boot; when opts.tmpDir was supplied, the caller keeps this
|
|
5419
|
+
// directory (and that toolchain) alive until it's done with withFiles'
|
|
5420
|
+
// artifactPaths, so no special-casing is needed here.
|
|
5421
|
+
const props = [`-Dsbt.global.base=${globalBase}`, '-Dsbt.server.autostart=false', `-Dsocket.recordsFile=${recordsFile}`, ...commonProps(opts, '-D')];
|
|
5422
|
+
// sbt's launcher doesn't always honor JAVA_HOME; never override a
|
|
5423
|
+
// caller-supplied --java-home.
|
|
5424
|
+
const javaHome = opts.env?.['JAVA_HOME'] ?? process.env['JAVA_HOME'];
|
|
5425
|
+
const javaHomeOpt = javaHome && !(opts.toolOpts ?? []).includes('--java-home') ? ['--java-home', javaHome] : [];
|
|
5426
|
+
const args = [...javaHomeOpt, ...props, ...(opts.toolOpts ?? []), '--batch', FACTS_TASK];
|
|
5427
|
+
const out = await runNeverThrow(bin, args, opts);
|
|
5428
|
+
return await assembleFromRecords(out, recordsFile);
|
|
5429
|
+
}
|
|
5399
5430
|
async function runSbt(opts) {
|
|
5400
|
-
|
|
5401
|
-
await
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
// Fresh per-run global base (not ~/.sbt): sbt executes everything under
|
|
5405
|
-
// plugins/, so a shared path is a code-injection surface. BSP off for this run.
|
|
5406
|
-
const props = [`-Dsbt.global.base=${globalBase}`, '-Dsbt.server.autostart=false', `-Dsocket.recordsFile=${recordsFile}`, ...commonProps(opts, '-D')];
|
|
5407
|
-
// sbt's launcher doesn't always honor JAVA_HOME; never override a
|
|
5408
|
-
// caller-supplied --java-home.
|
|
5409
|
-
const javaHome = opts.env?.['JAVA_HOME'] ?? process.env['JAVA_HOME'];
|
|
5410
|
-
const javaHomeOpt = javaHome && !(opts.toolOpts ?? []).includes('--java-home') ? ['--java-home', javaHome] : [];
|
|
5411
|
-
const args = [...javaHomeOpt, ...props, ...(opts.toolOpts ?? []), '--batch', FACTS_TASK];
|
|
5412
|
-
const out = await runNeverThrow(bin, args, opts);
|
|
5413
|
-
return await assembleFromRecords(out, recordsFile);
|
|
5414
|
-
});
|
|
5431
|
+
if (opts.tmpDir) {
|
|
5432
|
+
return await runSbtIn(opts.tmpDir, opts);
|
|
5433
|
+
}
|
|
5434
|
+
return await utils.withTmpDir('socket-sbt-facts-', globalBase => runSbtIn(globalBase, opts));
|
|
5415
5435
|
}
|
|
5416
5436
|
async function runMaven(opts) {
|
|
5417
5437
|
const jarPath = manifestScriptsPath('maven-extension', 'coana-maven-extension.jar');
|
|
5418
5438
|
assertMavenExtensionBuilt(jarPath);
|
|
5419
|
-
return await withTmpDir('socket-maven-facts-', async tmp => {
|
|
5439
|
+
return await utils.withTmpDir('socket-maven-facts-', async tmp => {
|
|
5420
5440
|
const recordsFile = path.join(tmp, 'records.tsv');
|
|
5421
5441
|
const bin = resolveBuildToolBin('maven', opts.projectDir, opts.bin);
|
|
5422
5442
|
// `validate` is the cheapest phase that triggers the afterSessionEnd
|
|
@@ -5516,6 +5536,7 @@ async function runManifestFacts({
|
|
|
5516
5536
|
ignoreUnresolved,
|
|
5517
5537
|
includeConfigs,
|
|
5518
5538
|
sidecarAcc,
|
|
5539
|
+
tmpDir,
|
|
5519
5540
|
verbose,
|
|
5520
5541
|
withFiles
|
|
5521
5542
|
}) {
|
|
@@ -5530,6 +5551,7 @@ async function runManifestFacts({
|
|
|
5530
5551
|
// Stream the build tool's output only when asked; otherwise capture it and
|
|
5531
5552
|
// show a spinner, surfacing the output only if the build crashes.
|
|
5532
5553
|
stdio: verbose ? 'inherit' : 'pipe',
|
|
5554
|
+
tmpDir,
|
|
5533
5555
|
toolOpts: buildOpts,
|
|
5534
5556
|
withFiles
|
|
5535
5557
|
};
|
|
@@ -5698,6 +5720,7 @@ async function convertSbtToFacts({
|
|
|
5698
5720
|
includeConfigs,
|
|
5699
5721
|
sbtOpts,
|
|
5700
5722
|
sidecarAcc,
|
|
5723
|
+
tmpDir,
|
|
5701
5724
|
verbose,
|
|
5702
5725
|
withFiles
|
|
5703
5726
|
}) {
|
|
@@ -5711,6 +5734,7 @@ async function convertSbtToFacts({
|
|
|
5711
5734
|
ignoreUnresolved,
|
|
5712
5735
|
includeConfigs,
|
|
5713
5736
|
sidecarAcc,
|
|
5737
|
+
tmpDir,
|
|
5714
5738
|
verbose,
|
|
5715
5739
|
withFiles
|
|
5716
5740
|
});
|
|
@@ -6236,6 +6260,7 @@ async function generateAutoManifest({
|
|
|
6236
6260
|
detected,
|
|
6237
6261
|
excludePaths,
|
|
6238
6262
|
outputKind,
|
|
6263
|
+
tmpDir,
|
|
6239
6264
|
verbose
|
|
6240
6265
|
}) {
|
|
6241
6266
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
@@ -6269,6 +6294,7 @@ async function generateAutoManifest({
|
|
|
6269
6294
|
ignoreUnresolved: Boolean(sockJson.defaults?.manifest?.sbt?.ignoreUnresolved),
|
|
6270
6295
|
includeConfigs: sockJson.defaults?.manifest?.sbt?.includeConfigs ?? '',
|
|
6271
6296
|
sidecarAcc,
|
|
6297
|
+
tmpDir,
|
|
6272
6298
|
withFiles: computeArtifactsSidecar
|
|
6273
6299
|
});
|
|
6274
6300
|
abortManifestRunIfFailed('sbt', beforeExitCode);
|
|
@@ -6431,8 +6457,8 @@ async function handleCreateNewScan({
|
|
|
6431
6457
|
workspace
|
|
6432
6458
|
}) {
|
|
6433
6459
|
let scanTargets = targets;
|
|
6434
|
-
|
|
6435
|
-
|
|
6460
|
+
debug.debugFn('notice', `Creating new scan for ${orgSlug}/${workspace ? `${workspace}/` : ''}${repoName}`);
|
|
6461
|
+
debug.debugDir('inspect', {
|
|
6436
6462
|
autoManifest,
|
|
6437
6463
|
branchName,
|
|
6438
6464
|
commitHash,
|
|
@@ -6450,234 +6476,244 @@ async function handleCreateNewScan({
|
|
|
6450
6476
|
|
|
6451
6477
|
// Sidecar forwarded to reachability; populated only when reach runs.
|
|
6452
6478
|
let resolvedPathsSidecar;
|
|
6453
|
-
if (autoManifest) {
|
|
6454
|
-
logger.logger.info('Auto-generating manifest files ...');
|
|
6455
|
-
require$$9.debugFn('notice', 'Auto-manifest mode enabled');
|
|
6456
|
-
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
6457
|
-
const detected = await detectManifestActions(sockJson, cwd);
|
|
6458
|
-
require$$9.debugDir('inspect', {
|
|
6459
|
-
detected
|
|
6460
|
-
});
|
|
6461
|
-
const autoManifestResult = await generateAutoManifest({
|
|
6462
|
-
computeArtifactsSidecar: reach.runReachabilityAnalysis,
|
|
6463
|
-
cwd,
|
|
6464
|
-
detected,
|
|
6465
|
-
excludePaths: reach.excludePaths,
|
|
6466
|
-
outputKind,
|
|
6467
|
-
verbose: false
|
|
6468
|
-
});
|
|
6469
|
-
resolvedPathsSidecar = autoManifestResult.resolvedPathsSidecar;
|
|
6470
|
-
if (autoManifestResult.generatedFiles.length) {
|
|
6471
|
-
scanTargets = Array.from(new Set([...targets, ...autoManifestResult.generatedFiles]));
|
|
6472
|
-
}
|
|
6473
|
-
logger.logger.info('Auto-generation finished. Proceeding with Scan creation.');
|
|
6474
|
-
}
|
|
6475
|
-
const {
|
|
6476
|
-
spinner
|
|
6477
|
-
} = constants.default;
|
|
6478
|
-
const supportedFilesCResult = await fetchSupportedScanFileNames({
|
|
6479
|
-
spinner
|
|
6480
|
-
});
|
|
6481
|
-
if (!supportedFilesCResult.ok) {
|
|
6482
|
-
require$$9.debugFn('warn', 'Failed to fetch supported scan file names');
|
|
6483
|
-
require$$9.debugDir('inspect', {
|
|
6484
|
-
supportedFilesCResult
|
|
6485
|
-
});
|
|
6486
|
-
await outputCreateNewScan(supportedFilesCResult, {
|
|
6487
|
-
interactive,
|
|
6488
|
-
outputKind
|
|
6489
|
-
});
|
|
6490
|
-
return;
|
|
6491
|
-
}
|
|
6492
|
-
require$$9.debugFn('notice', `Fetched ${supportedFilesCResult.data['size']} supported file types`);
|
|
6493
|
-
spinner.start('Searching for local files to include in scan...');
|
|
6494
|
-
const supportedFiles = supportedFilesCResult.data;
|
|
6495
|
-
|
|
6496
|
-
// Load socket.yml to respect projectIgnorePaths when collecting files.
|
|
6497
|
-
const socketYmlResult = utils.findSocketYmlSync(cwd);
|
|
6498
|
-
const socketConfig = socketYmlResult.ok ? socketYmlResult.data?.parsed : undefined;
|
|
6499
|
-
const {
|
|
6500
|
-
additionalScaIgnores,
|
|
6501
|
-
mergedReachabilityOptions
|
|
6502
|
-
} = applyFullExcludePaths({
|
|
6503
|
-
cwd,
|
|
6504
|
-
reachabilityOptions: reach,
|
|
6505
|
-
target: targets[0]
|
|
6506
|
-
});
|
|
6507
|
-
const packagePaths = await utils.getPackageFilesForScan(scanTargets, supportedFiles, {
|
|
6508
|
-
additionalIgnores: additionalScaIgnores,
|
|
6509
|
-
config: socketConfig,
|
|
6510
|
-
cwd
|
|
6511
|
-
});
|
|
6512
|
-
spinner.successAndStop(`Found ${packagePaths.length} ${words.pluralize('file', packagePaths.length)} to include in scan.`);
|
|
6513
|
-
const wasValidInput = utils.checkCommandInput(outputKind, {
|
|
6514
|
-
nook: true,
|
|
6515
|
-
test: packagePaths.length > 0,
|
|
6516
|
-
fail: `found no eligible files to scan. See supported manifest files at ${utils.socketDocsLink('/docs/manifest-file-detection-in-socket', 'docs.socket.dev')}`,
|
|
6517
|
-
message: 'TARGET (file/dir) must contain matching / supported file types for a scan'
|
|
6518
|
-
});
|
|
6519
|
-
if (!wasValidInput) {
|
|
6520
|
-
require$$9.debugFn('warn', 'No eligible files found to scan');
|
|
6521
|
-
return;
|
|
6522
|
-
}
|
|
6523
|
-
logger.logger.success(`Found ${packagePaths.length} local ${words.pluralize('file', packagePaths.length)}`);
|
|
6524
|
-
require$$9.debugDir('inspect', {
|
|
6525
|
-
packagePaths
|
|
6526
|
-
});
|
|
6527
|
-
if (readOnly) {
|
|
6528
|
-
logger.logger.log('[ReadOnly] Bailing now');
|
|
6529
|
-
require$$9.debugFn('notice', 'Read-only mode, exiting early');
|
|
6530
|
-
return;
|
|
6531
|
-
}
|
|
6532
|
-
let scanPaths = packagePaths;
|
|
6533
|
-
let tier1ReachabilityScanId;
|
|
6534
|
-
let reachabilityReport;
|
|
6535
6479
|
|
|
6536
|
-
//
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6480
|
+
// sbt provisions its Scala toolchain under the directory passed as its
|
|
6481
|
+
// isolated global base; withFiles' artifactPaths point into it, so it must
|
|
6482
|
+
// stay on disk until the reachability analysis below has consumed those
|
|
6483
|
+
// paths. Always allocated (even when unused) to keep this uniform rather
|
|
6484
|
+
// than conditional on autoManifest/reach.
|
|
6485
|
+
await utils.withTmpDir('socket-auto-manifest-', async manifestTmpDir => {
|
|
6486
|
+
if (autoManifest) {
|
|
6487
|
+
logger.logger.info('Auto-generating manifest files ...');
|
|
6488
|
+
debug.debugFn('notice', 'Auto-manifest mode enabled');
|
|
6489
|
+
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
6490
|
+
const detected = await detectManifestActions(sockJson, cwd);
|
|
6491
|
+
debug.debugDir('inspect', {
|
|
6492
|
+
detected
|
|
6493
|
+
});
|
|
6494
|
+
const autoManifestResult = await generateAutoManifest({
|
|
6495
|
+
computeArtifactsSidecar: reach.runReachabilityAnalysis,
|
|
6496
|
+
cwd,
|
|
6497
|
+
detected,
|
|
6498
|
+
excludePaths: reach.excludePaths,
|
|
6499
|
+
outputKind,
|
|
6500
|
+
tmpDir: manifestTmpDir,
|
|
6501
|
+
verbose: false
|
|
6502
|
+
});
|
|
6503
|
+
resolvedPathsSidecar = autoManifestResult.resolvedPathsSidecar;
|
|
6504
|
+
if (autoManifestResult.generatedFiles.length) {
|
|
6505
|
+
scanTargets = Array.from(new Set([...targets, ...autoManifestResult.generatedFiles]));
|
|
6506
|
+
}
|
|
6507
|
+
logger.logger.info('Auto-generation finished. Proceeding with Scan creation.');
|
|
6508
|
+
}
|
|
6509
|
+
const {
|
|
6510
|
+
spinner
|
|
6511
|
+
} = constants.default;
|
|
6512
|
+
const supportedFilesCResult = await fetchSupportedScanFileNames({
|
|
6548
6513
|
orgSlug,
|
|
6549
|
-
|
|
6550
|
-
packagePaths,
|
|
6551
|
-
reachabilityOptions: mergedReachabilityOptions,
|
|
6552
|
-
repoName,
|
|
6553
|
-
resolvedPathsSidecar,
|
|
6554
|
-
spinner,
|
|
6555
|
-
target: targets[0]
|
|
6514
|
+
spinner
|
|
6556
6515
|
});
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6516
|
+
if (!supportedFilesCResult.ok) {
|
|
6517
|
+
debug.debugFn('warn', 'Failed to fetch supported scan file names');
|
|
6518
|
+
debug.debugDir('inspect', {
|
|
6519
|
+
supportedFilesCResult
|
|
6520
|
+
});
|
|
6521
|
+
await outputCreateNewScan(supportedFilesCResult, {
|
|
6560
6522
|
interactive,
|
|
6561
6523
|
outputKind
|
|
6562
6524
|
});
|
|
6563
6525
|
return;
|
|
6564
6526
|
}
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
//
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
// input can resolve to the same path coana wrote its report to.
|
|
6577
|
-
const reportPath = reachabilityReport ? path.resolve(cwd, reachabilityReport) : undefined;
|
|
6578
|
-
scanPaths = [...pathsForScan.filter(p => path.resolve(cwd, p) !== reportPath), ...(reachabilityReport ? [reachabilityReport] : [])];
|
|
6579
|
-
tier1ReachabilityScanId = reachResult.data?.tier1ReachabilityScanId;
|
|
6580
|
-
}
|
|
6581
|
-
|
|
6582
|
-
// Brotli-compress any .socket.facts.json paths in scanPaths just before
|
|
6583
|
-
// upload. depscan's api-v0 multipart boundary streams brotli decode based
|
|
6584
|
-
// on the .br filename suffix. Coana keeps writing plain .socket.facts.json
|
|
6585
|
-
// on disk, so the local read paths (extractTier1ReachabilityScanId,
|
|
6586
|
-
// extractReachabilityErrors) stay correct. The cleanup() in the finally
|
|
6587
|
-
// block removes the temp dirs whether the upload succeeded or threw.
|
|
6588
|
-
const compressed = await utils.compressSocketFactsForUpload(scanPaths);
|
|
6589
|
-
let fullScanCResult;
|
|
6590
|
-
try {
|
|
6591
|
-
fullScanCResult = await fetchCreateOrgFullScan(compressed.paths, orgSlug, {
|
|
6592
|
-
commitHash,
|
|
6593
|
-
commitMessage,
|
|
6594
|
-
committers,
|
|
6595
|
-
pullRequest,
|
|
6596
|
-
repoName,
|
|
6597
|
-
branchName,
|
|
6598
|
-
scanType: reach.runReachabilityAnalysis ? constants.default.SCAN_TYPE_SOCKET_TIER1 : constants.default.SCAN_TYPE_SOCKET,
|
|
6599
|
-
workspace
|
|
6600
|
-
}, {
|
|
6527
|
+
debug.debugFn('notice', `Fetched ${supportedFilesCResult.data['size']} supported file types`);
|
|
6528
|
+
spinner.start('Searching for local files to include in scan...');
|
|
6529
|
+
const supportedFiles = supportedFilesCResult.data;
|
|
6530
|
+
|
|
6531
|
+
// Load socket.yml to respect projectIgnorePaths when collecting files.
|
|
6532
|
+
const socketYmlResult = utils.findSocketYmlSync(cwd);
|
|
6533
|
+
const socketConfig = socketYmlResult.ok ? socketYmlResult.data?.parsed : undefined;
|
|
6534
|
+
const {
|
|
6535
|
+
additionalScaIgnores,
|
|
6536
|
+
mergedReachabilityOptions
|
|
6537
|
+
} = applyFullExcludePaths({
|
|
6601
6538
|
cwd,
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
tmp
|
|
6539
|
+
reachabilityOptions: reach,
|
|
6540
|
+
target: targets[0]
|
|
6605
6541
|
});
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
// On a successful scan, clean up the `.socket.facts.json` coana wrote at
|
|
6622
|
-
// the path we instructed it to write to (via `--socket-mode`). Failed
|
|
6623
|
-
// scans leave the file in place for debugging. Producer-written files
|
|
6624
|
-
// (e.g. from `socket manifest gradle --facts`) are NOT touched here —
|
|
6625
|
-
// those are user-owned input that the user can clean up themselves; in
|
|
6626
|
-
// the --reach path coana overwrites that file with its enriched output
|
|
6627
|
-
// anyway, so it's the same path that gets removed. `--reach-retain-facts-file`
|
|
6628
|
-
// opts out of this cleanup so the report can be inspected; the user is then
|
|
6629
|
-
// responsible for deleting it before the next full application reachability
|
|
6630
|
-
// scan (a stale file is picked up as pre-generated input and would make those
|
|
6631
|
-
// results unreliable).
|
|
6632
|
-
if (fullScanCResult.ok && scanId && reachabilityReport && !reach.reachRetainFactsFile) {
|
|
6633
|
-
try {
|
|
6634
|
-
await fs.unlink(path.resolve(cwd, reachabilityReport));
|
|
6635
|
-
require$$9.debugFn('notice', `[socket-facts] removed coana output after successful scan: ${reachabilityReport}`);
|
|
6636
|
-
} catch {
|
|
6637
|
-
// Best-effort — file may already be gone or unwritable.
|
|
6542
|
+
const packagePaths = await utils.getPackageFilesForScan(scanTargets, supportedFiles, {
|
|
6543
|
+
additionalIgnores: additionalScaIgnores,
|
|
6544
|
+
config: socketConfig,
|
|
6545
|
+
cwd
|
|
6546
|
+
});
|
|
6547
|
+
spinner.successAndStop(`Found ${packagePaths.length} ${words.pluralize('file', packagePaths.length)} to include in scan.`);
|
|
6548
|
+
const wasValidInput = utils.checkCommandInput(outputKind, {
|
|
6549
|
+
nook: true,
|
|
6550
|
+
test: packagePaths.length > 0,
|
|
6551
|
+
fail: `found no eligible files to scan. See supported manifest files at ${utils.socketDocsLink('/docs/manifest-file-detection-in-socket', 'docs.socket.dev')}`,
|
|
6552
|
+
message: 'TARGET (file/dir) must contain matching / supported file types for a scan'
|
|
6553
|
+
});
|
|
6554
|
+
if (!wasValidInput) {
|
|
6555
|
+
debug.debugFn('warn', 'No eligible files found to scan');
|
|
6556
|
+
return;
|
|
6638
6557
|
}
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6558
|
+
logger.logger.success(`Found ${packagePaths.length} local ${words.pluralize('file', packagePaths.length)}`);
|
|
6559
|
+
debug.debugDir('inspect', {
|
|
6560
|
+
packagePaths
|
|
6561
|
+
});
|
|
6562
|
+
if (readOnly) {
|
|
6563
|
+
logger.logger.log('[ReadOnly] Bailing now');
|
|
6564
|
+
debug.debugFn('notice', 'Read-only mode, exiting early');
|
|
6565
|
+
return;
|
|
6566
|
+
}
|
|
6567
|
+
let scanPaths = packagePaths;
|
|
6568
|
+
let tier1ReachabilityScanId;
|
|
6569
|
+
let reachabilityReport;
|
|
6570
|
+
|
|
6571
|
+
// If reachability is enabled, perform reachability analysis.
|
|
6572
|
+
if (reach.runReachabilityAnalysis) {
|
|
6573
|
+
logger.logger.error('');
|
|
6574
|
+
logger.logger.info('Starting reachability analysis...');
|
|
6575
|
+
debug.debugFn('notice', 'Reachability analysis enabled');
|
|
6576
|
+
debug.debugDir('inspect', {
|
|
6577
|
+
reachabilityOptions: mergedReachabilityOptions
|
|
6578
|
+
});
|
|
6579
|
+
spinner.start();
|
|
6580
|
+
const reachResult = await performReachabilityAnalysis({
|
|
6581
|
+
branchName,
|
|
6582
|
+
cwd,
|
|
6646
6583
|
orgSlug,
|
|
6647
6584
|
outputKind,
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6585
|
+
packagePaths,
|
|
6586
|
+
reachabilityOptions: mergedReachabilityOptions,
|
|
6587
|
+
repoName,
|
|
6588
|
+
resolvedPathsSidecar,
|
|
6589
|
+
spinner,
|
|
6590
|
+
target: targets[0]
|
|
6651
6591
|
});
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6592
|
+
spinner.stop();
|
|
6593
|
+
if (!reachResult.ok) {
|
|
6594
|
+
await outputCreateNewScan(reachResult, {
|
|
6595
|
+
interactive,
|
|
6596
|
+
outputKind
|
|
6597
|
+
});
|
|
6598
|
+
return;
|
|
6599
|
+
}
|
|
6600
|
+
logger.logger.success('Reachability analysis completed successfully');
|
|
6601
|
+
reachabilityReport = reachResult.data?.reachabilityReport;
|
|
6602
|
+
|
|
6603
|
+
// When using only pre-generated SBOMs, build the scan from those inputs —
|
|
6604
|
+
// CycloneDX, SPDX, and Socket facts (`.socket.facts.json`) — matching
|
|
6605
|
+
// Coana's `--use-only-pregenerated-sboms` selection. Otherwise drop any
|
|
6606
|
+
// stray `.socket.facts.json`; coana's fresh reachability report (appended
|
|
6607
|
+
// below) is the authoritative facts file for the scan.
|
|
6608
|
+
const pathsForScan = reach.reachUseOnlyPregeneratedSboms ? filterToPregeneratedSboms(packagePaths, supportedFiles) : packagePaths.filter(p => path.basename(p) !== constants.default.DOT_SOCKET_DOT_FACTS_JSON);
|
|
6609
|
+
|
|
6610
|
+
// Append coana's reachability report, but not twice: a pre-generated facts
|
|
6611
|
+
// input can resolve to the same path coana wrote its report to.
|
|
6612
|
+
const reportPath = reachabilityReport ? path.resolve(cwd, reachabilityReport) : undefined;
|
|
6613
|
+
scanPaths = [...pathsForScan.filter(p => path.resolve(cwd, p) !== reportPath), ...(reachabilityReport ? [reachabilityReport] : [])];
|
|
6614
|
+
tier1ReachabilityScanId = reachResult.data?.tier1ReachabilityScanId;
|
|
6615
|
+
}
|
|
6616
|
+
|
|
6617
|
+
// Brotli-compress any .socket.facts.json paths in scanPaths just before
|
|
6618
|
+
// upload. depscan's api-v0 multipart boundary streams brotli decode based
|
|
6619
|
+
// on the .br filename suffix. Coana keeps writing plain .socket.facts.json
|
|
6620
|
+
// on disk, so the local read paths (extractTier1ReachabilityScanId,
|
|
6621
|
+
// extractReachabilityErrors) stay correct. The cleanup() in the finally
|
|
6622
|
+
// block removes the temp dirs whether the upload succeeded or threw.
|
|
6623
|
+
const compressed = await utils.compressSocketFactsForUpload(scanPaths);
|
|
6624
|
+
let fullScanCResult;
|
|
6625
|
+
try {
|
|
6626
|
+
fullScanCResult = await fetchCreateOrgFullScan(compressed.paths, orgSlug, {
|
|
6627
|
+
commitHash,
|
|
6628
|
+
commitMessage,
|
|
6629
|
+
committers,
|
|
6630
|
+
pullRequest,
|
|
6631
|
+
repoName,
|
|
6632
|
+
branchName,
|
|
6633
|
+
scanType: reach.runReachabilityAnalysis ? constants.default.SCAN_TYPE_SOCKET_TIER1 : constants.default.SCAN_TYPE_SOCKET,
|
|
6634
|
+
workspace
|
|
6658
6635
|
}, {
|
|
6636
|
+
cwd,
|
|
6637
|
+
defaultBranch,
|
|
6638
|
+
pendingHead,
|
|
6639
|
+
tmp
|
|
6640
|
+
});
|
|
6641
|
+
} finally {
|
|
6642
|
+
await compressed.cleanup();
|
|
6643
|
+
}
|
|
6644
|
+
const scanId = fullScanCResult.ok ? fullScanCResult.data?.id : undefined;
|
|
6645
|
+
if (reach && scanId && tier1ReachabilityScanId) {
|
|
6646
|
+
await finalizeTier1Scan(tier1ReachabilityScanId, scanId);
|
|
6647
|
+
} else if (reach.runReachabilityAnalysis && scanId && !tier1ReachabilityScanId) {
|
|
6648
|
+
// Reachability analysis ran and a scan was created, but no full
|
|
6649
|
+
// application reachability scan id was extracted from the facts file.
|
|
6650
|
+
// Surface this instead of silently skipping finalize — otherwise the
|
|
6651
|
+
// reachability row stays stuck (e.g. at COANA_DONE) and the full scan is
|
|
6652
|
+
// never linked to its reachability report.
|
|
6653
|
+
logger.logger.warn('Reachability analysis ran but no full application reachability scan ID was found; skipping reachability finalize. The scan was created but its reachability report was not linked.');
|
|
6654
|
+
}
|
|
6655
|
+
|
|
6656
|
+
// On a successful scan, clean up the `.socket.facts.json` coana wrote at
|
|
6657
|
+
// the path we instructed it to write to (via `--socket-mode`). Failed
|
|
6658
|
+
// scans leave the file in place for debugging. Producer-written files
|
|
6659
|
+
// (e.g. from `socket manifest gradle --facts`) are NOT touched here —
|
|
6660
|
+
// those are user-owned input that the user can clean up themselves; in
|
|
6661
|
+
// the --reach path coana overwrites that file with its enriched output
|
|
6662
|
+
// anyway, so it's the same path that gets removed. `--reach-retain-facts-file`
|
|
6663
|
+
// opts out of this cleanup so the report can be inspected; the user is then
|
|
6664
|
+
// responsible for deleting it before the next full application reachability
|
|
6665
|
+
// scan (a stale file is picked up as pre-generated input and would make those
|
|
6666
|
+
// results unreliable).
|
|
6667
|
+
if (fullScanCResult.ok && scanId && reachabilityReport && !reach.reachRetainFactsFile) {
|
|
6668
|
+
try {
|
|
6669
|
+
await fs.unlink(path.resolve(cwd, reachabilityReport));
|
|
6670
|
+
debug.debugFn('notice', `[socket-facts] removed coana output after successful scan: ${reachabilityReport}`);
|
|
6671
|
+
} catch {
|
|
6672
|
+
// Best-effort — file may already be gone or unwritable.
|
|
6673
|
+
}
|
|
6674
|
+
}
|
|
6675
|
+
if (report && fullScanCResult.ok) {
|
|
6676
|
+
if (scanId) {
|
|
6677
|
+
await handleScanReport({
|
|
6678
|
+
filepath: '-',
|
|
6679
|
+
fold: constants.default.FOLD_SETTING_VERSION,
|
|
6680
|
+
includeLicensePolicy: true,
|
|
6681
|
+
orgSlug,
|
|
6682
|
+
outputKind,
|
|
6683
|
+
reportLevel,
|
|
6684
|
+
scanId,
|
|
6685
|
+
short: false
|
|
6686
|
+
});
|
|
6687
|
+
} else {
|
|
6688
|
+
await outputCreateNewScan({
|
|
6689
|
+
ok: false,
|
|
6690
|
+
message: 'Missing Scan ID',
|
|
6691
|
+
cause: 'Server did not respond with a scan ID',
|
|
6692
|
+
data: fullScanCResult.data
|
|
6693
|
+
}, {
|
|
6694
|
+
interactive,
|
|
6695
|
+
outputKind
|
|
6696
|
+
});
|
|
6697
|
+
}
|
|
6698
|
+
} else {
|
|
6699
|
+
spinner.stop();
|
|
6700
|
+
await outputCreateNewScan(fullScanCResult, {
|
|
6659
6701
|
interactive,
|
|
6660
6702
|
outputKind
|
|
6661
6703
|
});
|
|
6662
6704
|
}
|
|
6663
|
-
}
|
|
6664
|
-
spinner.stop();
|
|
6665
|
-
await outputCreateNewScan(fullScanCResult, {
|
|
6666
|
-
interactive,
|
|
6667
|
-
outputKind
|
|
6668
|
-
});
|
|
6669
|
-
}
|
|
6705
|
+
});
|
|
6670
6706
|
}
|
|
6671
6707
|
|
|
6672
6708
|
async function handleCi(autoManifest) {
|
|
6673
|
-
|
|
6674
|
-
|
|
6709
|
+
debug.debugFn('notice', 'Starting CI scan');
|
|
6710
|
+
debug.debugDir('inspect', {
|
|
6675
6711
|
autoManifest
|
|
6676
6712
|
});
|
|
6677
6713
|
const orgSlugCResult = await utils.getDefaultOrgSlug();
|
|
6678
6714
|
if (!orgSlugCResult.ok) {
|
|
6679
|
-
|
|
6680
|
-
|
|
6715
|
+
debug.debugFn('warn', 'Failed to get default org slug');
|
|
6716
|
+
debug.debugDir('inspect', {
|
|
6681
6717
|
orgSlugCResult
|
|
6682
6718
|
});
|
|
6683
6719
|
process.exitCode = orgSlugCResult.code ?? 1;
|
|
@@ -6689,8 +6725,8 @@ async function handleCi(autoManifest) {
|
|
|
6689
6725
|
const cwd = process.cwd();
|
|
6690
6726
|
const branchName = (await utils.gitBranch(cwd)) || (await utils.detectDefaultBranch(cwd));
|
|
6691
6727
|
const repoName = await utils.getRepoName(cwd);
|
|
6692
|
-
|
|
6693
|
-
|
|
6728
|
+
debug.debugFn('notice', `CI scan for ${orgSlug}/${repoName} on branch ${branchName}`);
|
|
6729
|
+
debug.debugDir('inspect', {
|
|
6694
6730
|
orgSlug,
|
|
6695
6731
|
cwd,
|
|
6696
6732
|
branchName,
|
|
@@ -6711,6 +6747,7 @@ async function handleCi(autoManifest) {
|
|
|
6711
6747
|
pendingHead: true,
|
|
6712
6748
|
pullRequest: 0,
|
|
6713
6749
|
reach: {
|
|
6750
|
+
dynamicSbomInference: false,
|
|
6714
6751
|
excludePaths: [],
|
|
6715
6752
|
reachAnalysisMemoryLimit: '',
|
|
6716
6753
|
reachAnalysisTimeout: '',
|
|
@@ -7381,8 +7418,8 @@ async function handleConfigSet({
|
|
|
7381
7418
|
outputKind,
|
|
7382
7419
|
value
|
|
7383
7420
|
}) {
|
|
7384
|
-
|
|
7385
|
-
|
|
7421
|
+
debug.debugFn('notice', `Setting config ${key} = ${value}`);
|
|
7422
|
+
debug.debugDir('inspect', {
|
|
7386
7423
|
key,
|
|
7387
7424
|
value,
|
|
7388
7425
|
outputKind
|
|
@@ -7400,8 +7437,8 @@ async function handleConfigSet({
|
|
|
7400
7437
|
message: `Config key '${key}' was not saved`,
|
|
7401
7438
|
cause: result.data
|
|
7402
7439
|
} : result;
|
|
7403
|
-
|
|
7404
|
-
|
|
7440
|
+
debug.debugFn('notice', `Config update ${outcome.ok ? 'succeeded' : 'failed'}`);
|
|
7441
|
+
debug.debugDir('inspect', {
|
|
7405
7442
|
outcome,
|
|
7406
7443
|
result
|
|
7407
7444
|
});
|
|
@@ -7651,11 +7688,11 @@ const cmdConfig = {
|
|
|
7651
7688
|
*/
|
|
7652
7689
|
async function cleanupStaleBranch(branch, ghsaId, cwd) {
|
|
7653
7690
|
logger.logger.warn(`Stale branch ${branch} found without open PR, cleaning up...`);
|
|
7654
|
-
|
|
7691
|
+
debug.debugFn('notice', `cleanup: deleting stale branch ${branch}`);
|
|
7655
7692
|
const deleted = await utils.gitDeleteRemoteBranch(branch, cwd);
|
|
7656
7693
|
if (!deleted) {
|
|
7657
7694
|
logger.logger.error(`Failed to delete stale remote branch ${branch}, skipping ${ghsaId}.`);
|
|
7658
|
-
|
|
7695
|
+
debug.debugFn('error', `cleanup: remote deletion failed for ${branch}`);
|
|
7659
7696
|
return false;
|
|
7660
7697
|
}
|
|
7661
7698
|
|
|
@@ -7760,7 +7797,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7760
7797
|
base: baseBranch,
|
|
7761
7798
|
body: getSocketFixPullRequestBody(ghsaIds, ghsaDetails)
|
|
7762
7799
|
};
|
|
7763
|
-
|
|
7800
|
+
debug.debugDir('inspect', {
|
|
7764
7801
|
octokitPullsCreateParams
|
|
7765
7802
|
});
|
|
7766
7803
|
const pr = await octokit.pulls.create(octokitPullsCreateParams);
|
|
@@ -7776,7 +7813,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7776
7813
|
|
|
7777
7814
|
// Check for "PR already exists" error.
|
|
7778
7815
|
if (errorMessages.some(msg => msg.toLowerCase().includes('pull request already exists'))) {
|
|
7779
|
-
|
|
7816
|
+
debug.debugFn('error', 'Failed to open pull request: already exists');
|
|
7780
7817
|
return {
|
|
7781
7818
|
ok: false,
|
|
7782
7819
|
reason: 'already_exists',
|
|
@@ -7787,7 +7824,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7787
7824
|
// Check for validation errors (e.g., no commits between branches).
|
|
7788
7825
|
if (errors && errors.length > 0) {
|
|
7789
7826
|
const details = errorMessages.map(d => `- ${d}`).join('\n');
|
|
7790
|
-
|
|
7827
|
+
debug.debugFn('error', `Failed to open pull request:\n${details}`);
|
|
7791
7828
|
return {
|
|
7792
7829
|
ok: false,
|
|
7793
7830
|
reason: 'validation_error',
|
|
@@ -7798,7 +7835,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7798
7835
|
|
|
7799
7836
|
// Check HTTP status codes.
|
|
7800
7837
|
if (e.status === 403 || e.status === 401) {
|
|
7801
|
-
|
|
7838
|
+
debug.debugFn('error', 'Failed to open pull request: permission denied');
|
|
7802
7839
|
return {
|
|
7803
7840
|
ok: false,
|
|
7804
7841
|
reason: 'permission_denied',
|
|
@@ -7806,7 +7843,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7806
7843
|
};
|
|
7807
7844
|
}
|
|
7808
7845
|
if (e.status && e.status >= 500) {
|
|
7809
|
-
|
|
7846
|
+
debug.debugFn('error', 'Failed to open pull request: network error');
|
|
7810
7847
|
return {
|
|
7811
7848
|
ok: false,
|
|
7812
7849
|
reason: 'network_error',
|
|
@@ -7816,7 +7853,7 @@ async function openSocketFixPr(owner, repo, branch, ghsaIds, options) {
|
|
|
7816
7853
|
}
|
|
7817
7854
|
|
|
7818
7855
|
// Unknown error.
|
|
7819
|
-
|
|
7856
|
+
debug.debugFn('error', `Failed to open pull request: ${e}`);
|
|
7820
7857
|
return {
|
|
7821
7858
|
ok: false,
|
|
7822
7859
|
reason: 'unknown',
|
|
@@ -7918,7 +7955,7 @@ async function getSocketFixPrsWithContext(owner, repo, options) {
|
|
|
7918
7955
|
|
|
7919
7956
|
// Safety limit to prevent infinite loops.
|
|
7920
7957
|
if (pageIndex === constants.GQL_PAGE_SENTINEL) {
|
|
7921
|
-
|
|
7958
|
+
debug.debugFn('warn', `GraphQL pagination reached safety limit (${constants.GQL_PAGE_SENTINEL} pages) for ${owner}/${repo}`);
|
|
7922
7959
|
break;
|
|
7923
7960
|
}
|
|
7924
7961
|
|
|
@@ -7929,8 +7966,8 @@ async function getSocketFixPrsWithContext(owner, repo, options) {
|
|
|
7929
7966
|
}
|
|
7930
7967
|
}
|
|
7931
7968
|
} catch (e) {
|
|
7932
|
-
|
|
7933
|
-
|
|
7969
|
+
debug.debugFn('error', `GraphQL pagination failed for ${owner}/${repo}`);
|
|
7970
|
+
debug.debugDir('error', e);
|
|
7934
7971
|
}
|
|
7935
7972
|
return contextualMatches;
|
|
7936
7973
|
}
|
|
@@ -7940,7 +7977,7 @@ function ciRepoInfo() {
|
|
|
7940
7977
|
GITHUB_REPOSITORY
|
|
7941
7978
|
} = constants.default.ENV;
|
|
7942
7979
|
if (!GITHUB_REPOSITORY) {
|
|
7943
|
-
|
|
7980
|
+
debug.debugFn('notice', 'miss: GITHUB_REPOSITORY env var');
|
|
7944
7981
|
}
|
|
7945
7982
|
const ownerSlashRepo = GITHUB_REPOSITORY;
|
|
7946
7983
|
const slashIndex = ownerSlashRepo.indexOf('/');
|
|
@@ -8016,8 +8053,8 @@ async function getFixEnv() {
|
|
|
8016
8053
|
// If not in CI but some CI-related env vars are set.
|
|
8017
8054
|
!constants.default.ENV.CI && envCheck.present.length &&
|
|
8018
8055
|
// then log about it when in debug mode.
|
|
8019
|
-
|
|
8020
|
-
|
|
8056
|
+
debug.isDebug('notice')) {
|
|
8057
|
+
debug.debugFn('notice', `miss: fixEnv.isCi is false, expected ${arrays.joinAnd(envCheck.missing)} to be set`);
|
|
8021
8058
|
}
|
|
8022
8059
|
let repoInfo;
|
|
8023
8060
|
if (isCi) {
|
|
@@ -8025,7 +8062,7 @@ async function getFixEnv() {
|
|
|
8025
8062
|
}
|
|
8026
8063
|
if (!repoInfo) {
|
|
8027
8064
|
if (isCi) {
|
|
8028
|
-
|
|
8065
|
+
debug.debugFn('notice', 'falling back to `git remote get-url origin`');
|
|
8029
8066
|
}
|
|
8030
8067
|
repoInfo = await utils.getRepoInfo();
|
|
8031
8068
|
}
|
|
@@ -8044,6 +8081,57 @@ async function getFixEnv() {
|
|
|
8044
8081
|
};
|
|
8045
8082
|
}
|
|
8046
8083
|
|
|
8084
|
+
async function readStructuredDiscoveryResult(outputFile, silence) {
|
|
8085
|
+
let raw;
|
|
8086
|
+
try {
|
|
8087
|
+
raw = await fs$1.promises.readFile(outputFile, 'utf8');
|
|
8088
|
+
} catch {
|
|
8089
|
+
return {
|
|
8090
|
+
ok: false,
|
|
8091
|
+
message: 'Coana did not write a vulnerability discovery result file',
|
|
8092
|
+
cause: `Expected \`find-vulnerabilities --output-file\` to create ${outputFile}.`
|
|
8093
|
+
};
|
|
8094
|
+
}
|
|
8095
|
+
let parsed;
|
|
8096
|
+
try {
|
|
8097
|
+
parsed = JSON.parse(raw);
|
|
8098
|
+
} catch {
|
|
8099
|
+
return {
|
|
8100
|
+
ok: false,
|
|
8101
|
+
message: 'Could not parse the vulnerability discovery result written by Coana',
|
|
8102
|
+
cause: `Expected JSON in ${outputFile}, got:\n ${raw.slice(0, 500)}`
|
|
8103
|
+
};
|
|
8104
|
+
}
|
|
8105
|
+
if (parsed === null || typeof parsed !== 'object') {
|
|
8106
|
+
return {
|
|
8107
|
+
ok: false,
|
|
8108
|
+
message: 'Coana wrote an unexpected vulnerability discovery result',
|
|
8109
|
+
cause: `Expected a JSON object with a ghsaIds string array, got:\n ${raw.slice(0, 500)}`
|
|
8110
|
+
};
|
|
8111
|
+
}
|
|
8112
|
+
const {
|
|
8113
|
+
artifactCount,
|
|
8114
|
+
ghsaIds
|
|
8115
|
+
} = parsed;
|
|
8116
|
+
if (!Array.isArray(ghsaIds) || ghsaIds.some(id => typeof id !== 'string')) {
|
|
8117
|
+
return {
|
|
8118
|
+
ok: false,
|
|
8119
|
+
message: 'Coana wrote an unexpected vulnerability discovery result',
|
|
8120
|
+
cause: `Expected a JSON object with a ghsaIds string array, got:\n ${raw.slice(0, 500)}`
|
|
8121
|
+
};
|
|
8122
|
+
}
|
|
8123
|
+
|
|
8124
|
+
// Zero artifacts means the backend resolved nothing — suspicious when
|
|
8125
|
+
// manifests were uploaded, so warn even though discovery itself succeeded.
|
|
8126
|
+
if (artifactCount === 0 && !silence) {
|
|
8127
|
+
logger.logger.warn('The Socket backend resolved 0 artifacts, so vulnerability discovery may be incomplete.');
|
|
8128
|
+
}
|
|
8129
|
+
return {
|
|
8130
|
+
ok: true,
|
|
8131
|
+
data: ghsaIds
|
|
8132
|
+
};
|
|
8133
|
+
}
|
|
8134
|
+
|
|
8047
8135
|
/**
|
|
8048
8136
|
* Discovers GHSA IDs by running coana without applying fixes.
|
|
8049
8137
|
* Returns a list of GHSA IDs, optionally limited.
|
|
@@ -8059,23 +8147,31 @@ async function discoverGhsaIds(orgSlug, tarHash, options) {
|
|
|
8059
8147
|
__proto__: null,
|
|
8060
8148
|
...options
|
|
8061
8149
|
};
|
|
8062
|
-
|
|
8150
|
+
|
|
8151
|
+
// Coana writes a structured JSON result ({ ghsaIds, artifactCount,
|
|
8152
|
+
// filteredArtifactCount }) via --output-file (available since coana 15.9.7,
|
|
8153
|
+
// older than the pinned @coana-tech/cli version).
|
|
8154
|
+
const outputFile = path.join(os.tmpdir(), `socket-fix-discovery-${Date.now()}.json`);
|
|
8155
|
+
const foundCResult = await utils.spawnCoanaDlx(['find-vulnerabilities', cwd, '--manifests-tar-hash', tarHash, '--output-file', outputFile, ...(ecosystems?.length ? ['--purl-types', ...ecosystems] : []), ...(packageManagers?.length ? ['--package-managers', ...packageManagers] : [])], orgSlug, {
|
|
8063
8156
|
cwd,
|
|
8064
8157
|
spinner: silence ? undefined : spinner,
|
|
8065
8158
|
coanaVersion: options?.coanaVersion
|
|
8066
8159
|
}, {
|
|
8067
8160
|
stdio: 'pipe'
|
|
8068
8161
|
});
|
|
8069
|
-
if (foundCResult.ok) {
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8162
|
+
if (!foundCResult.ok) {
|
|
8163
|
+
await fs$1.promises.rm(outputFile, {
|
|
8164
|
+
force: true
|
|
8165
|
+
}).catch(() => {});
|
|
8166
|
+
return foundCResult;
|
|
8167
|
+
}
|
|
8168
|
+
try {
|
|
8169
|
+
return await readStructuredDiscoveryResult(outputFile, silence);
|
|
8170
|
+
} finally {
|
|
8171
|
+
await fs$1.promises.rm(outputFile, {
|
|
8172
|
+
force: true
|
|
8173
|
+
}).catch(() => {});
|
|
8077
8174
|
}
|
|
8078
|
-
return [];
|
|
8079
8175
|
}
|
|
8080
8176
|
async function coanaFix(fixConfig) {
|
|
8081
8177
|
const {
|
|
@@ -8084,7 +8180,7 @@ async function coanaFix(fixConfig) {
|
|
|
8084
8180
|
autopilot,
|
|
8085
8181
|
coanaVersion,
|
|
8086
8182
|
cwd,
|
|
8087
|
-
debug,
|
|
8183
|
+
debug: debug$1,
|
|
8088
8184
|
disableExternalToolChecks,
|
|
8089
8185
|
disableMajorUpdates,
|
|
8090
8186
|
ecosystems,
|
|
@@ -8102,7 +8198,7 @@ async function coanaFix(fixConfig) {
|
|
|
8102
8198
|
spinner
|
|
8103
8199
|
} = fixConfig;
|
|
8104
8200
|
const fixEnv = await getFixEnv();
|
|
8105
|
-
|
|
8201
|
+
debug.debugDir('inspect', {
|
|
8106
8202
|
fixEnv
|
|
8107
8203
|
});
|
|
8108
8204
|
if (!silence) {
|
|
@@ -8114,6 +8210,7 @@ async function coanaFix(fixConfig) {
|
|
|
8114
8210
|
}
|
|
8115
8211
|
const sockSdk = sockSdkCResult.data;
|
|
8116
8212
|
const supportedFilesCResult = await fetchSupportedScanFileNames({
|
|
8213
|
+
orgSlug,
|
|
8117
8214
|
spinner: silence ? undefined : spinner,
|
|
8118
8215
|
silence
|
|
8119
8216
|
});
|
|
@@ -8155,7 +8252,9 @@ async function coanaFix(fixConfig) {
|
|
|
8155
8252
|
cause: `Delete the following ${words.pluralize('file', factsFiles.length)} before running socket fix again:\n` + factsFiles.map(p => ` - ${p}`).join('\n')
|
|
8156
8253
|
};
|
|
8157
8254
|
}
|
|
8158
|
-
const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, scanFilepaths,
|
|
8255
|
+
const uploadCResult = await utils.handleApiCall(sockSdk.uploadManifestFiles(orgSlug, scanFilepaths, {
|
|
8256
|
+
pathsRelativeTo: cwd
|
|
8257
|
+
}), {
|
|
8159
8258
|
description: 'upload manifests',
|
|
8160
8259
|
spinner,
|
|
8161
8260
|
silence
|
|
@@ -8197,14 +8296,26 @@ async function coanaFix(fixConfig) {
|
|
|
8197
8296
|
}
|
|
8198
8297
|
|
|
8199
8298
|
// In local mode, process all discovered/provided IDs (no limit).
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8299
|
+
let ids;
|
|
8300
|
+
if (shouldDiscoverGhsaIds) {
|
|
8301
|
+
const discoverCResult = await discoverGhsaIds(orgSlug, tarHash, {
|
|
8302
|
+
coanaVersion,
|
|
8303
|
+
cwd,
|
|
8304
|
+
ecosystems,
|
|
8305
|
+
packageManagers,
|
|
8306
|
+
silence,
|
|
8307
|
+
spinner
|
|
8308
|
+
});
|
|
8309
|
+
if (!discoverCResult.ok) {
|
|
8310
|
+
if (!silence) {
|
|
8311
|
+
spinner?.stop();
|
|
8312
|
+
}
|
|
8313
|
+
return discoverCResult;
|
|
8314
|
+
}
|
|
8315
|
+
ids = discoverCResult.data;
|
|
8316
|
+
} else {
|
|
8317
|
+
ids = ghsas;
|
|
8318
|
+
}
|
|
8208
8319
|
if (ids.length === 0) {
|
|
8209
8320
|
if (!silence) {
|
|
8210
8321
|
spinner?.stop();
|
|
@@ -8222,7 +8333,7 @@ async function coanaFix(fixConfig) {
|
|
|
8222
8333
|
const tmpDir = os.tmpdir();
|
|
8223
8334
|
const tmpFile = path.join(tmpDir, `socket-fix-${Date.now()}.json`);
|
|
8224
8335
|
try {
|
|
8225
|
-
const fixCResult = await utils.spawnCoanaDlx(['compute-fixes-and-upgrade-purls', cwd, '--manifests-tar-hash', tarHash, '--apply-fixes-to', ...ids, ...(fixConfig.rangeStyle ? ['--range-style', fixConfig.rangeStyle] : []), ...(minimumReleaseAge ? ['--minimum-release-age', minimumReleaseAge] : []), ...(include.length ? ['--include', ...include] : []), ...(coanaExcludePatterns.length ? ['--exclude', ...coanaExcludePatterns] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), ...(packageManagers.length ? ['--package-managers', ...packageManagers] : []), ...(!applyFixes ? [constants.FLAG_DRY_RUN] : []), '--output-file', tmpFile, ...(debug ? ['--debug'] : []), ...(disableExternalToolChecks ? ['--disable-external-tool-checks'] : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] : []), ...fixConfig.unknownFlags], fixConfig.orgSlug, {
|
|
8336
|
+
const fixCResult = await utils.spawnCoanaDlx(['compute-fixes-and-upgrade-purls', cwd, '--manifests-tar-hash', tarHash, '--apply-fixes-to', ...ids, ...(fixConfig.rangeStyle ? ['--range-style', fixConfig.rangeStyle] : []), ...(minimumReleaseAge ? ['--minimum-release-age', minimumReleaseAge] : []), ...(include.length ? ['--include', ...include] : []), ...(coanaExcludePatterns.length ? ['--exclude', ...coanaExcludePatterns] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), ...(packageManagers.length ? ['--package-managers', ...packageManagers] : []), ...(!applyFixes ? [constants.FLAG_DRY_RUN] : []), '--output-file', tmpFile, ...(debug$1 ? ['--debug'] : []), ...(disableExternalToolChecks ? ['--disable-external-tool-checks'] : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] : []), ...fixConfig.unknownFlags], fixConfig.orgSlug, {
|
|
8226
8337
|
coanaVersion,
|
|
8227
8338
|
cwd,
|
|
8228
8339
|
spinner: silence ? undefined : spinner,
|
|
@@ -8276,30 +8387,41 @@ async function coanaFix(fixConfig) {
|
|
|
8276
8387
|
// Reduce limit by number of open PRs to avoid creating too many.
|
|
8277
8388
|
adjustedPrLimit = Math.max(0, prLimit - openPrCount);
|
|
8278
8389
|
if (openPrCount > 0) {
|
|
8279
|
-
|
|
8390
|
+
debug.debugFn('notice', `prLimit: adjusted from ${prLimit} to ${adjustedPrLimit} (${openPrCount} open Socket Fix ${words.pluralize('PR', openPrCount)}`);
|
|
8280
8391
|
}
|
|
8281
8392
|
} catch (e) {
|
|
8282
|
-
|
|
8283
|
-
|
|
8393
|
+
debug.debugFn('warn', 'Failed to count open PRs, using original limit');
|
|
8394
|
+
debug.debugDir('error', e);
|
|
8284
8395
|
}
|
|
8285
8396
|
}
|
|
8286
8397
|
const shouldSpawnCoana = adjustedPrLimit > 0;
|
|
8287
8398
|
let ids;
|
|
8288
8399
|
if (shouldSpawnCoana) {
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8400
|
+
if (shouldDiscoverGhsaIds) {
|
|
8401
|
+
const discoverCResult = await discoverGhsaIds(orgSlug, tarHash, {
|
|
8402
|
+
coanaVersion,
|
|
8403
|
+
cwd,
|
|
8404
|
+
ecosystems,
|
|
8405
|
+
packageManagers,
|
|
8406
|
+
silence,
|
|
8407
|
+
spinner
|
|
8408
|
+
});
|
|
8409
|
+
if (!discoverCResult.ok) {
|
|
8410
|
+
if (!silence) {
|
|
8411
|
+
spinner?.stop();
|
|
8412
|
+
}
|
|
8413
|
+
return discoverCResult;
|
|
8414
|
+
}
|
|
8415
|
+
ids = discoverCResult.data.slice(0, adjustedPrLimit);
|
|
8416
|
+
} else {
|
|
8417
|
+
ids = ghsas.slice(0, adjustedPrLimit);
|
|
8418
|
+
}
|
|
8297
8419
|
}
|
|
8298
8420
|
if (!ids?.length) {
|
|
8299
|
-
|
|
8421
|
+
debug.debugFn('notice', 'miss: no GHSA IDs to process');
|
|
8300
8422
|
}
|
|
8301
8423
|
if (!fixEnv.repoInfo) {
|
|
8302
|
-
|
|
8424
|
+
debug.debugFn('notice', 'miss: no repo info detected');
|
|
8303
8425
|
}
|
|
8304
8426
|
if (!ids?.length || !fixEnv.repoInfo) {
|
|
8305
8427
|
if (!silence) {
|
|
@@ -8313,10 +8435,10 @@ async function coanaFix(fixConfig) {
|
|
|
8313
8435
|
}
|
|
8314
8436
|
};
|
|
8315
8437
|
}
|
|
8316
|
-
|
|
8438
|
+
debug.debugFn('notice', `fetch: ${ids.length} GHSA details for ${arrays.joinAnd(ids)}`);
|
|
8317
8439
|
const ghsaDetails = await utils.fetchGhsaDetails(ids);
|
|
8318
8440
|
const scanBaseNames = new Set(scanFilepaths.map(p => path.basename(p)));
|
|
8319
|
-
|
|
8441
|
+
debug.debugFn('notice', `found: ${ghsaDetails.size} GHSA details`);
|
|
8320
8442
|
let count = 0;
|
|
8321
8443
|
let overallFixed = false;
|
|
8322
8444
|
const ghsaFixResults = [];
|
|
@@ -8326,7 +8448,7 @@ async function coanaFix(fixConfig) {
|
|
|
8326
8448
|
length
|
|
8327
8449
|
} = ids; i < length; i += 1) {
|
|
8328
8450
|
const ghsaId = ids[i];
|
|
8329
|
-
|
|
8451
|
+
debug.debugFn('notice', `check: ${ghsaId}`);
|
|
8330
8452
|
|
|
8331
8453
|
// Create a temporary file for Coana output.
|
|
8332
8454
|
const tmpDir = os.tmpdir();
|
|
@@ -8334,7 +8456,7 @@ async function coanaFix(fixConfig) {
|
|
|
8334
8456
|
|
|
8335
8457
|
// Apply fix for single GHSA ID.
|
|
8336
8458
|
// eslint-disable-next-line no-await-in-loop
|
|
8337
|
-
const fixCResult = await utils.spawnCoanaDlx(['compute-fixes-and-upgrade-purls', cwd, '--manifests-tar-hash', tarHash, '--apply-fixes-to', ghsaId, ...(fixConfig.rangeStyle ? ['--range-style', fixConfig.rangeStyle] : []), ...(minimumReleaseAge ? ['--minimum-release-age', minimumReleaseAge] : []), ...(include.length ? ['--include', ...include] : []), ...(coanaExcludePatterns.length ? ['--exclude', ...coanaExcludePatterns] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), ...(packageManagers.length ? ['--package-managers', ...packageManagers] : []), ...(debug ? ['--debug'] : []), ...(disableExternalToolChecks ? ['--disable-external-tool-checks'] : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] : []), '--output-file', tmpFile, ...fixConfig.unknownFlags], fixConfig.orgSlug, {
|
|
8459
|
+
const fixCResult = await utils.spawnCoanaDlx(['compute-fixes-and-upgrade-purls', cwd, '--manifests-tar-hash', tarHash, '--apply-fixes-to', ghsaId, ...(fixConfig.rangeStyle ? ['--range-style', fixConfig.rangeStyle] : []), ...(minimumReleaseAge ? ['--minimum-release-age', minimumReleaseAge] : []), ...(include.length ? ['--include', ...include] : []), ...(coanaExcludePatterns.length ? ['--exclude', ...coanaExcludePatterns] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), ...(packageManagers.length ? ['--package-managers', ...packageManagers] : []), ...(debug$1 ? ['--debug'] : []), ...(disableExternalToolChecks ? ['--disable-external-tool-checks'] : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] : []), '--output-file', tmpFile, ...fixConfig.unknownFlags], fixConfig.orgSlug, {
|
|
8338
8460
|
coanaVersion,
|
|
8339
8461
|
cwd,
|
|
8340
8462
|
spinner: silence ? undefined : spinner,
|
|
@@ -8359,7 +8481,7 @@ async function coanaFix(fixConfig) {
|
|
|
8359
8481
|
const unstagedCResult = await utils.gitUnstagedModifiedFiles(cwd);
|
|
8360
8482
|
const modifiedFiles = unstagedCResult.ok ? unstagedCResult.data.filter(relPath => scanBaseNames.has(path.basename(relPath))) : [];
|
|
8361
8483
|
if (!modifiedFiles.length) {
|
|
8362
|
-
|
|
8484
|
+
debug.debugFn('notice', `skip: no changes for ${ghsaId}`);
|
|
8363
8485
|
// Clean up temp file before continuing.
|
|
8364
8486
|
try {
|
|
8365
8487
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -8383,7 +8505,7 @@ async function coanaFix(fixConfig) {
|
|
|
8383
8505
|
if (!silence) {
|
|
8384
8506
|
logger.logger.info(`PR #${prNum} already exists for ${ghsaId}, skipping.`);
|
|
8385
8507
|
}
|
|
8386
|
-
|
|
8508
|
+
debug.debugFn('notice', `skip: open PR #${prNum} exists for ${ghsaId}`);
|
|
8387
8509
|
continue ghsaLoop;
|
|
8388
8510
|
}
|
|
8389
8511
|
|
|
@@ -8403,12 +8525,12 @@ async function coanaFix(fixConfig) {
|
|
|
8403
8525
|
if (!silence) {
|
|
8404
8526
|
logger.logger.error('Cannot create pull request: SOCKET_CLI_GITHUB_TOKEN environment variable is not set.\n' + 'Set SOCKET_CLI_GITHUB_TOKEN or GITHUB_TOKEN to enable PR creation.');
|
|
8405
8527
|
}
|
|
8406
|
-
|
|
8528
|
+
debug.debugFn('error', `skip: missing GitHub token for ${ghsaId}`);
|
|
8407
8529
|
continue ghsaLoop;
|
|
8408
8530
|
}
|
|
8409
|
-
|
|
8531
|
+
debug.debugFn('notice', `pr: creating for ${ghsaId}`);
|
|
8410
8532
|
const details = ghsaDetails.get(ghsaId);
|
|
8411
|
-
|
|
8533
|
+
debug.debugFn('notice', `ghsa: ${ghsaId} details ${details ? 'found' : 'missing'}`);
|
|
8412
8534
|
const pushed =
|
|
8413
8535
|
// eslint-disable-next-line no-await-in-loop
|
|
8414
8536
|
(await utils.gitCreateBranch(branch, cwd)) && (
|
|
@@ -8535,7 +8657,7 @@ async function coanaFix(fixConfig) {
|
|
|
8535
8657
|
if (!silence) {
|
|
8536
8658
|
logger.logger.warn(`Unexpected condition: Push failed for ${ghsaId}, skipping PR creation.`);
|
|
8537
8659
|
}
|
|
8538
|
-
|
|
8660
|
+
debug.debugDir('error', e);
|
|
8539
8661
|
// Clean up branches (push may have succeeded before error).
|
|
8540
8662
|
// eslint-disable-next-line no-await-in-loop
|
|
8541
8663
|
const remoteBranchExists = await utils.gitRemoteBranchExists(branch, cwd);
|
|
@@ -8555,7 +8677,7 @@ async function coanaFix(fixConfig) {
|
|
|
8555
8677
|
}
|
|
8556
8678
|
}
|
|
8557
8679
|
count += 1;
|
|
8558
|
-
|
|
8680
|
+
debug.debugFn('notice', `increment: count ${count}/${Math.min(adjustedPrLimit, ids.length)}`);
|
|
8559
8681
|
if (count >= adjustedPrLimit) {
|
|
8560
8682
|
break ghsaLoop;
|
|
8561
8683
|
}
|
|
@@ -8601,8 +8723,8 @@ async function convertIdsToGhsas(ids, options) {
|
|
|
8601
8723
|
__proto__: null,
|
|
8602
8724
|
...options
|
|
8603
8725
|
};
|
|
8604
|
-
|
|
8605
|
-
|
|
8726
|
+
debug.debugFn('notice', `Converting ${ids.length} IDs to GHSA format`);
|
|
8727
|
+
debug.debugDir('inspect', {
|
|
8606
8728
|
ids
|
|
8607
8729
|
});
|
|
8608
8730
|
const validGhsas = [];
|
|
@@ -8654,12 +8776,12 @@ async function convertIdsToGhsas(ids, options) {
|
|
|
8654
8776
|
if (!silence) {
|
|
8655
8777
|
logger.logger.warn(`Skipped ${errors.length} invalid IDs:\n${errors.map(e => ` - ${e}`).join('\n')}`);
|
|
8656
8778
|
}
|
|
8657
|
-
|
|
8779
|
+
debug.debugDir('inspect', {
|
|
8658
8780
|
errors
|
|
8659
8781
|
});
|
|
8660
8782
|
}
|
|
8661
|
-
|
|
8662
|
-
|
|
8783
|
+
debug.debugFn('notice', `Converted to ${validGhsas.length} valid GHSA IDs`);
|
|
8784
|
+
debug.debugDir('inspect', {
|
|
8663
8785
|
validGhsas
|
|
8664
8786
|
});
|
|
8665
8787
|
return validGhsas;
|
|
@@ -8670,7 +8792,7 @@ async function handleFix({
|
|
|
8670
8792
|
autopilot,
|
|
8671
8793
|
coanaVersion,
|
|
8672
8794
|
cwd,
|
|
8673
|
-
debug,
|
|
8795
|
+
debug: debug$1,
|
|
8674
8796
|
disableExternalToolChecks,
|
|
8675
8797
|
disableMajorUpdates,
|
|
8676
8798
|
ecosystems,
|
|
@@ -8692,14 +8814,14 @@ async function handleFix({
|
|
|
8692
8814
|
spinner,
|
|
8693
8815
|
unknownFlags
|
|
8694
8816
|
}) {
|
|
8695
|
-
|
|
8696
|
-
|
|
8817
|
+
debug.debugFn('notice', `Starting fix command for ${orgSlug}`);
|
|
8818
|
+
debug.debugDir('inspect', {
|
|
8697
8819
|
all,
|
|
8698
8820
|
applyFixes,
|
|
8699
8821
|
autopilot,
|
|
8700
8822
|
coanaVersion,
|
|
8701
8823
|
cwd,
|
|
8702
|
-
debug,
|
|
8824
|
+
debug: debug$1,
|
|
8703
8825
|
disableExternalToolChecks,
|
|
8704
8826
|
disableMajorUpdates,
|
|
8705
8827
|
ecosystems,
|
|
@@ -8725,7 +8847,7 @@ async function handleFix({
|
|
|
8725
8847
|
autopilot,
|
|
8726
8848
|
coanaVersion,
|
|
8727
8849
|
cwd,
|
|
8728
|
-
debug,
|
|
8850
|
+
debug: debug$1,
|
|
8729
8851
|
disableExternalToolChecks,
|
|
8730
8852
|
disableMajorUpdates,
|
|
8731
8853
|
ecosystems,
|
|
@@ -9193,9 +9315,9 @@ async function setupTabCompletion(targetName) {
|
|
|
9193
9315
|
|
|
9194
9316
|
// Target dir is something like ~/.local/share/socket/settings/completion (linux)
|
|
9195
9317
|
const targetDir = path.dirname(targetPath);
|
|
9196
|
-
|
|
9318
|
+
debug.debugFn('notice', 'target: path + dir', targetPath, targetDir);
|
|
9197
9319
|
if (!fs$1.existsSync(targetDir)) {
|
|
9198
|
-
|
|
9320
|
+
debug.debugFn('notice', 'create: target dir');
|
|
9199
9321
|
fs$1.mkdirSync(targetDir, {
|
|
9200
9322
|
recursive: true
|
|
9201
9323
|
});
|
|
@@ -9453,8 +9575,8 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
9453
9575
|
logger.logger.success(`API token verified: ${arrays.joinAnd(orgSlugs)}`);
|
|
9454
9576
|
const enterpriseOrgs = utils.getEnterpriseOrgs(organizations);
|
|
9455
9577
|
const enforcedChoices = enterpriseOrgs.map(org => ({
|
|
9456
|
-
name: org
|
|
9457
|
-
value: org
|
|
9578
|
+
name: org['name'] ?? 'undefined',
|
|
9579
|
+
value: org['id']
|
|
9458
9580
|
}));
|
|
9459
9581
|
let enforcedOrgs = [];
|
|
9460
9582
|
if (enforcedChoices.length > 1) {
|
|
@@ -11223,7 +11345,7 @@ async function run$G(argv, importMeta, {
|
|
|
11223
11345
|
// If given path is absolute then cwd should not affect it.
|
|
11224
11346
|
cwd = path.resolve(process.cwd(), cwd);
|
|
11225
11347
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
11226
|
-
|
|
11348
|
+
debug.debugFn('inspect', `override: ${constants.SOCKET_JSON} bazel`, sockJson?.defaults?.manifest?.bazel);
|
|
11227
11349
|
const {
|
|
11228
11350
|
ecosystem
|
|
11229
11351
|
} = cli.flags;
|
|
@@ -11372,6 +11494,12 @@ async function run$G(argv, importMeta, {
|
|
|
11372
11494
|
}
|
|
11373
11495
|
|
|
11374
11496
|
const reachabilityFlags = {
|
|
11497
|
+
dynamicSbomInference: {
|
|
11498
|
+
type: 'boolean',
|
|
11499
|
+
default: false,
|
|
11500
|
+
hidden: true,
|
|
11501
|
+
description: 'Internal: enables dynamic SBOM inference for full application reachability analysis. Passes --maven-use-only-root-socket-facts to Coana and implies --auto-manifest.'
|
|
11502
|
+
},
|
|
11375
11503
|
reachVersion: {
|
|
11376
11504
|
type: 'string',
|
|
11377
11505
|
description: `Override the version of @coana-tech/cli used for reachability analysis. Default: ${constants.default.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION}.`
|
|
@@ -11553,7 +11681,7 @@ async function run$F(argv, importMeta, {
|
|
|
11553
11681
|
}
|
|
11554
11682
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
11555
11683
|
const detected = await detectManifestActions(sockJson, cwd);
|
|
11556
|
-
|
|
11684
|
+
debug.debugDir('inspect', {
|
|
11557
11685
|
detected
|
|
11558
11686
|
});
|
|
11559
11687
|
if (dryRun) {
|
|
@@ -11571,13 +11699,14 @@ async function run$F(argv, importMeta, {
|
|
|
11571
11699
|
}
|
|
11572
11700
|
const excludePaths = utils.cmdFlagValueToArray(cli.flags['excludePaths']);
|
|
11573
11701
|
assertValidExcludePaths(excludePaths);
|
|
11574
|
-
await generateAutoManifest({
|
|
11702
|
+
await utils.withTmpDir('socket-manifest-auto-', tmpDir => generateAutoManifest({
|
|
11575
11703
|
detected,
|
|
11576
11704
|
cwd,
|
|
11577
11705
|
excludePaths,
|
|
11578
11706
|
outputKind,
|
|
11707
|
+
tmpDir,
|
|
11579
11708
|
verbose
|
|
11580
|
-
});
|
|
11709
|
+
}));
|
|
11581
11710
|
logger.logger.success(`Finished. Should have attempted to generate manifest files for ${detected.count} targets.`);
|
|
11582
11711
|
}
|
|
11583
11712
|
|
|
@@ -11840,7 +11969,7 @@ async function run$D(argv, importMeta, {
|
|
|
11840
11969
|
// If given path is absolute then cwd should not affect it.
|
|
11841
11970
|
cwd = path.resolve(process.cwd(), cwd);
|
|
11842
11971
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
11843
|
-
|
|
11972
|
+
debug.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
|
|
11844
11973
|
let {
|
|
11845
11974
|
bin,
|
|
11846
11975
|
excludeConfigs,
|
|
@@ -12091,7 +12220,7 @@ async function run$C(argv, importMeta, {
|
|
|
12091
12220
|
// If given path is absolute then cwd should not affect it.
|
|
12092
12221
|
cwd = path.resolve(process.cwd(), cwd);
|
|
12093
12222
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
12094
|
-
|
|
12223
|
+
debug.debugFn('inspect', `override: ${constants.SOCKET_JSON} gradle`, sockJson?.defaults?.manifest?.gradle);
|
|
12095
12224
|
let {
|
|
12096
12225
|
bin,
|
|
12097
12226
|
excludeConfigs,
|
|
@@ -12319,7 +12448,7 @@ async function run$B(argv, importMeta, {
|
|
|
12319
12448
|
// If given path is absolute then cwd should not affect it.
|
|
12320
12449
|
cwd = path.resolve(process.cwd(), cwd);
|
|
12321
12450
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
12322
|
-
|
|
12451
|
+
debug.debugFn('inspect', `override: ${constants.SOCKET_JSON} maven`, sockJson?.defaults?.manifest?.maven);
|
|
12323
12452
|
let {
|
|
12324
12453
|
bin,
|
|
12325
12454
|
excludeConfigs,
|
|
@@ -12543,7 +12672,7 @@ async function run$A(argv, importMeta, {
|
|
|
12543
12672
|
// TODO: Implement json/md further.
|
|
12544
12673
|
const outputKind = utils.getOutputKind(json, markdown);
|
|
12545
12674
|
const sockJson = utils.readOrDefaultSocketJson(cwd);
|
|
12546
|
-
|
|
12675
|
+
debug.debugFn('inspect', `override: ${constants.SOCKET_JSON} sbt`, sockJson?.defaults?.manifest?.sbt);
|
|
12547
12676
|
let {
|
|
12548
12677
|
bin,
|
|
12549
12678
|
excludeConfigs,
|
|
@@ -12689,7 +12818,7 @@ async function run$A(argv, importMeta, {
|
|
|
12689
12818
|
const excludePaths = utils.cmdFlagValueToArray(cli.flags['excludePaths']);
|
|
12690
12819
|
assertValidExcludePaths(excludePaths);
|
|
12691
12820
|
if (facts) {
|
|
12692
|
-
await convertSbtToFacts({
|
|
12821
|
+
await utils.withTmpDir('socket-manifest-scala-', tmpDir => convertSbtToFacts({
|
|
12693
12822
|
bin: String(bin),
|
|
12694
12823
|
cwd,
|
|
12695
12824
|
excludeConfigs: String(excludeConfigs || ''),
|
|
@@ -12697,8 +12826,9 @@ async function run$A(argv, importMeta, {
|
|
|
12697
12826
|
ignoreUnresolved: Boolean(ignoreUnresolved),
|
|
12698
12827
|
includeConfigs: String(includeConfigs || ''),
|
|
12699
12828
|
sbtOpts: parsedSbtOpts,
|
|
12829
|
+
tmpDir,
|
|
12700
12830
|
verbose: Boolean(verbose)
|
|
12701
|
-
});
|
|
12831
|
+
}));
|
|
12702
12832
|
return;
|
|
12703
12833
|
}
|
|
12704
12834
|
await convertSbtToMaven({
|
|
@@ -12723,7 +12853,7 @@ async function outputManifestSetup(result) {
|
|
|
12723
12853
|
|
|
12724
12854
|
async function setupManifestConfig(cwd, defaultOnReadError = false) {
|
|
12725
12855
|
const detected = await detectManifestActions(null, cwd);
|
|
12726
|
-
|
|
12856
|
+
debug.debugDir('inspect', {
|
|
12727
12857
|
detected
|
|
12728
12858
|
});
|
|
12729
12859
|
|
|
@@ -13391,7 +13521,7 @@ async function run$y(argv, importMeta, {
|
|
|
13391
13521
|
});
|
|
13392
13522
|
}
|
|
13393
13523
|
|
|
13394
|
-
const require$5 = require$$
|
|
13524
|
+
const require$5 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
13395
13525
|
const CMD_NAME$q = constants.NPM;
|
|
13396
13526
|
const description$w = 'Wraps npm with Socket security scanning';
|
|
13397
13527
|
const hidden$q = false;
|
|
@@ -13477,7 +13607,7 @@ async function run$x(argv, importMeta, context) {
|
|
|
13477
13607
|
await spawnPromise;
|
|
13478
13608
|
}
|
|
13479
13609
|
|
|
13480
|
-
const require$4 = require$$
|
|
13610
|
+
const require$4 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
13481
13611
|
const CMD_NAME$p = constants.NPX;
|
|
13482
13612
|
const description$v = 'Wraps npx with Socket security scanning';
|
|
13483
13613
|
const hidden$p = false;
|
|
@@ -14039,8 +14169,8 @@ function updatePkgJsonField(editablePkgJson, field, value) {
|
|
|
14039
14169
|
if (oldValue) {
|
|
14040
14170
|
// The field already exists so we simply update the field value.
|
|
14041
14171
|
if (field === PNPM) {
|
|
14042
|
-
const isPnpmObj =
|
|
14043
|
-
if (
|
|
14172
|
+
const isPnpmObj = objects.isObject(oldValue);
|
|
14173
|
+
if (objects.hasKeys(value)) {
|
|
14044
14174
|
editablePkgJson.update({
|
|
14045
14175
|
[field]: {
|
|
14046
14176
|
...(isPnpmObj ? oldValue : {}),
|
|
@@ -14052,7 +14182,7 @@ function updatePkgJsonField(editablePkgJson, field, value) {
|
|
|
14052
14182
|
});
|
|
14053
14183
|
} else {
|
|
14054
14184
|
// Properties with undefined values are deleted when saved as JSON.
|
|
14055
|
-
editablePkgJson.update(
|
|
14185
|
+
editablePkgJson.update(objects.hasKeys(oldValue) ? {
|
|
14056
14186
|
[field]: {
|
|
14057
14187
|
...(isPnpmObj ? oldValue : {}),
|
|
14058
14188
|
overrides: undefined
|
|
@@ -14064,7 +14194,7 @@ function updatePkgJsonField(editablePkgJson, field, value) {
|
|
|
14064
14194
|
} else if (field === OVERRIDES || field === RESOLUTIONS) {
|
|
14065
14195
|
// Properties with undefined values are deleted when saved as JSON.
|
|
14066
14196
|
editablePkgJson.update({
|
|
14067
|
-
[field]:
|
|
14197
|
+
[field]: objects.hasKeys(value) ? value : undefined
|
|
14068
14198
|
});
|
|
14069
14199
|
} else {
|
|
14070
14200
|
editablePkgJson.update({
|
|
@@ -14073,7 +14203,7 @@ function updatePkgJsonField(editablePkgJson, field, value) {
|
|
|
14073
14203
|
}
|
|
14074
14204
|
return;
|
|
14075
14205
|
}
|
|
14076
|
-
if ((field === OVERRIDES || field === PNPM || field === RESOLUTIONS) && !
|
|
14206
|
+
if ((field === OVERRIDES || field === PNPM || field === RESOLUTIONS) && !objects.hasKeys(value)) {
|
|
14077
14207
|
return;
|
|
14078
14208
|
}
|
|
14079
14209
|
// Since the field doesn't exist we want to insert it into the package.json
|
|
@@ -14199,7 +14329,7 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
|
|
|
14199
14329
|
let loggedAddingText = false;
|
|
14200
14330
|
|
|
14201
14331
|
// Chunk package names to process them in parallel 3 at a time.
|
|
14202
|
-
await
|
|
14332
|
+
await promises.pEach(manifestNpmOverrides, async ({
|
|
14203
14333
|
1: data
|
|
14204
14334
|
}) => {
|
|
14205
14335
|
const {
|
|
@@ -14213,11 +14343,11 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
|
|
|
14213
14343
|
for (const {
|
|
14214
14344
|
1: depObj
|
|
14215
14345
|
} of depEntries) {
|
|
14216
|
-
const sockSpec =
|
|
14346
|
+
const sockSpec = objects.hasOwn(depObj, sockRegPkgName) ? depObj[sockRegPkgName] : undefined;
|
|
14217
14347
|
if (sockSpec) {
|
|
14218
14348
|
depAliasMap.set(sockRegPkgName, sockSpec);
|
|
14219
14349
|
}
|
|
14220
|
-
const origSpec =
|
|
14350
|
+
const origSpec = objects.hasOwn(depObj, origPkgName) ? depObj[origPkgName] : undefined;
|
|
14221
14351
|
if (origSpec) {
|
|
14222
14352
|
let thisSpec = origSpec;
|
|
14223
14353
|
// Add package aliases for direct dependencies to avoid npm EOVERRIDE
|
|
@@ -14253,11 +14383,11 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
|
|
|
14253
14383
|
npmExecPath
|
|
14254
14384
|
});
|
|
14255
14385
|
// Chunk package names to process them in parallel 3 at a time.
|
|
14256
|
-
await
|
|
14386
|
+
await promises.pEach(overridesDataObjects, async ({
|
|
14257
14387
|
overrides,
|
|
14258
14388
|
type
|
|
14259
14389
|
}) => {
|
|
14260
|
-
const overrideExists =
|
|
14390
|
+
const overrideExists = objects.hasOwn(overrides, origPkgName);
|
|
14261
14391
|
if (overrideExists || thingScanner(pkgEnvDetails, thingToScan, origPkgName, lockName)) {
|
|
14262
14392
|
const oldSpec = overrideExists ? overrides[origPkgName] : undefined;
|
|
14263
14393
|
const origDepAlias = depAliasMap.get(origPkgName);
|
|
@@ -14311,7 +14441,7 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
|
|
|
14311
14441
|
});
|
|
14312
14442
|
if (isWorkspace) {
|
|
14313
14443
|
// Chunk package names to process them in parallel 3 at a time.
|
|
14314
|
-
await
|
|
14444
|
+
await promises.pEach(workspacePkgJsonPaths, async workspacePkgJsonPath => {
|
|
14315
14445
|
const otherState = await addOverrides(pkgEnvDetails, path.dirname(workspacePkgJsonPath), {
|
|
14316
14446
|
logger,
|
|
14317
14447
|
pin,
|
|
@@ -14334,7 +14464,7 @@ async function addOverrides(pkgEnvDetails, pkgPath, options) {
|
|
|
14334
14464
|
overrides,
|
|
14335
14465
|
type
|
|
14336
14466
|
} of overridesDataObjects) {
|
|
14337
|
-
updateManifest(type, pkgEnvDetails.editablePkgJson,
|
|
14467
|
+
updateManifest(type, pkgEnvDetails.editablePkgJson, objects.toSortedObject(overrides));
|
|
14338
14468
|
}
|
|
14339
14469
|
}
|
|
14340
14470
|
await pkgEnvDetails.editablePkgJson.save();
|
|
@@ -14366,8 +14496,8 @@ async function updateLockfile(pkgEnvDetails, options) {
|
|
|
14366
14496
|
}
|
|
14367
14497
|
} catch (e) {
|
|
14368
14498
|
spinner?.stop();
|
|
14369
|
-
|
|
14370
|
-
|
|
14499
|
+
debug.debugFn('error', 'Lockfile update failed');
|
|
14500
|
+
debug.debugDir('error', e);
|
|
14371
14501
|
if (wasSpinning) {
|
|
14372
14502
|
spinner.start();
|
|
14373
14503
|
}
|
|
@@ -14467,8 +14597,8 @@ async function handleOptimize({
|
|
|
14467
14597
|
pin,
|
|
14468
14598
|
prod
|
|
14469
14599
|
}) {
|
|
14470
|
-
|
|
14471
|
-
|
|
14600
|
+
debug.debugFn('notice', `Starting optimization for ${cwd}`);
|
|
14601
|
+
debug.debugDir('inspect', {
|
|
14472
14602
|
cwd,
|
|
14473
14603
|
outputKind,
|
|
14474
14604
|
pin,
|
|
@@ -14481,8 +14611,8 @@ async function handleOptimize({
|
|
|
14481
14611
|
});
|
|
14482
14612
|
if (!pkgEnvCResult.ok) {
|
|
14483
14613
|
process.exitCode = pkgEnvCResult.code ?? 1;
|
|
14484
|
-
|
|
14485
|
-
|
|
14614
|
+
debug.debugFn('warn', 'Package environment validation failed');
|
|
14615
|
+
debug.debugDir('inspect', {
|
|
14486
14616
|
pkgEnvCResult
|
|
14487
14617
|
});
|
|
14488
14618
|
await outputOptimizeResult(pkgEnvCResult, outputKind);
|
|
@@ -14491,7 +14621,7 @@ async function handleOptimize({
|
|
|
14491
14621
|
const pkgEnvDetails = pkgEnvCResult.data;
|
|
14492
14622
|
if (!pkgEnvDetails) {
|
|
14493
14623
|
process.exitCode = 1;
|
|
14494
|
-
|
|
14624
|
+
debug.debugFn('warn', 'No package environment details found');
|
|
14495
14625
|
await outputOptimizeResult({
|
|
14496
14626
|
ok: false,
|
|
14497
14627
|
message: 'No package found.',
|
|
@@ -14499,8 +14629,8 @@ async function handleOptimize({
|
|
|
14499
14629
|
}, outputKind);
|
|
14500
14630
|
return;
|
|
14501
14631
|
}
|
|
14502
|
-
|
|
14503
|
-
|
|
14632
|
+
debug.debugFn('notice', `Detected package manager: ${pkgEnvDetails.agent} v${pkgEnvDetails.agentVersion}`);
|
|
14633
|
+
debug.debugDir('inspect', {
|
|
14504
14634
|
pkgEnvDetails
|
|
14505
14635
|
});
|
|
14506
14636
|
const {
|
|
@@ -14509,7 +14639,7 @@ async function handleOptimize({
|
|
|
14509
14639
|
} = pkgEnvDetails;
|
|
14510
14640
|
if (agent === VLT) {
|
|
14511
14641
|
process.exitCode = 1;
|
|
14512
|
-
|
|
14642
|
+
debug.debugFn('warn', `${agent} does not support overrides`);
|
|
14513
14643
|
await outputOptimizeResult({
|
|
14514
14644
|
ok: false,
|
|
14515
14645
|
message: 'Unsupported',
|
|
@@ -14518,7 +14648,7 @@ async function handleOptimize({
|
|
|
14518
14648
|
return;
|
|
14519
14649
|
}
|
|
14520
14650
|
logger.logger.info(`Optimizing packages for ${agent} v${agentVersion}.\n`);
|
|
14521
|
-
|
|
14651
|
+
debug.debugFn('notice', 'Applying optimization');
|
|
14522
14652
|
const optimizationResult = await applyOptimization(pkgEnvDetails, {
|
|
14523
14653
|
pin,
|
|
14524
14654
|
prod
|
|
@@ -14526,8 +14656,8 @@ async function handleOptimize({
|
|
|
14526
14656
|
if (!optimizationResult.ok) {
|
|
14527
14657
|
process.exitCode = optimizationResult.code ?? 1;
|
|
14528
14658
|
}
|
|
14529
|
-
|
|
14530
|
-
|
|
14659
|
+
debug.debugFn('notice', `Optimization ${optimizationResult.ok ? 'succeeded' : 'failed'}`);
|
|
14660
|
+
debug.debugDir('inspect', {
|
|
14531
14661
|
optimizationResult
|
|
14532
14662
|
});
|
|
14533
14663
|
await outputOptimizeResult(optimizationResult, outputKind);
|
|
@@ -14698,8 +14828,8 @@ async function handleDependencies({
|
|
|
14698
14828
|
offset,
|
|
14699
14829
|
outputKind
|
|
14700
14830
|
}) {
|
|
14701
|
-
|
|
14702
|
-
|
|
14831
|
+
debug.debugFn('notice', `Fetching dependencies with limit=${limit}, offset=${offset}`);
|
|
14832
|
+
debug.debugDir('inspect', {
|
|
14703
14833
|
limit,
|
|
14704
14834
|
offset,
|
|
14705
14835
|
outputKind
|
|
@@ -14708,8 +14838,8 @@ async function handleDependencies({
|
|
|
14708
14838
|
limit,
|
|
14709
14839
|
offset
|
|
14710
14840
|
});
|
|
14711
|
-
|
|
14712
|
-
|
|
14841
|
+
debug.debugFn('notice', `Dependencies ${result.ok ? 'fetched successfully' : 'fetch failed'}`);
|
|
14842
|
+
debug.debugDir('inspect', {
|
|
14713
14843
|
result
|
|
14714
14844
|
});
|
|
14715
14845
|
await outputDependencies(result, {
|
|
@@ -15122,13 +15252,13 @@ async function outputOrganizationList(orgsCResult, outputKind = 'text') {
|
|
|
15122
15252
|
}
|
|
15123
15253
|
|
|
15124
15254
|
async function handleOrganizationList(outputKind = 'text') {
|
|
15125
|
-
|
|
15126
|
-
|
|
15255
|
+
debug.debugFn('notice', 'Fetching organization list');
|
|
15256
|
+
debug.debugDir('inspect', {
|
|
15127
15257
|
outputKind
|
|
15128
15258
|
});
|
|
15129
15259
|
const data = await utils.fetchOrganization();
|
|
15130
|
-
|
|
15131
|
-
|
|
15260
|
+
debug.debugFn('notice', `Organization list ${data.ok ? 'fetched successfully' : 'fetch failed'}`);
|
|
15261
|
+
debug.debugDir('inspect', {
|
|
15132
15262
|
data
|
|
15133
15263
|
});
|
|
15134
15264
|
await outputOrganizationList(data, outputKind);
|
|
@@ -15537,14 +15667,14 @@ function createMarkdownReport(data) {
|
|
|
15537
15667
|
}
|
|
15538
15668
|
|
|
15539
15669
|
async function handlePurlDeepScore(purl, outputKind) {
|
|
15540
|
-
|
|
15541
|
-
|
|
15670
|
+
debug.debugFn('notice', `Fetching deep score for ${purl}`);
|
|
15671
|
+
debug.debugDir('inspect', {
|
|
15542
15672
|
purl,
|
|
15543
15673
|
outputKind
|
|
15544
15674
|
});
|
|
15545
15675
|
const result = await fetchPurlDeepScore(purl);
|
|
15546
|
-
|
|
15547
|
-
|
|
15676
|
+
debug.debugFn('notice', `Deep score ${result.ok ? 'fetched successfully' : 'fetch failed'}`);
|
|
15677
|
+
debug.debugDir('inspect', {
|
|
15548
15678
|
result
|
|
15549
15679
|
});
|
|
15550
15680
|
await outputPurlsDeepScore(purl, result, outputKind);
|
|
@@ -15774,7 +15904,7 @@ function formatReportCard(artifact, colorize) {
|
|
|
15774
15904
|
colorize
|
|
15775
15905
|
});
|
|
15776
15906
|
if (!artifact.ecosystem) {
|
|
15777
|
-
|
|
15907
|
+
debug.debugFn('notice', 'miss: artifact ecosystem', artifact);
|
|
15778
15908
|
}
|
|
15779
15909
|
const purl = `pkg:${artifact.ecosystem}/${artifact.name}${artifact.version ? '@' + artifact.version : ''}`;
|
|
15780
15910
|
|
|
@@ -15978,14 +16108,14 @@ async function handlePurlsShallowScore({
|
|
|
15978
16108
|
outputKind,
|
|
15979
16109
|
purls
|
|
15980
16110
|
}) {
|
|
15981
|
-
|
|
15982
|
-
|
|
16111
|
+
debug.debugFn('notice', `Fetching shallow scores for ${purls.length} packages`);
|
|
16112
|
+
debug.debugDir('inspect', {
|
|
15983
16113
|
purls,
|
|
15984
16114
|
outputKind
|
|
15985
16115
|
});
|
|
15986
16116
|
const packageData = await fetchPurlsShallowScore(purls);
|
|
15987
|
-
|
|
15988
|
-
|
|
16117
|
+
debug.debugFn('notice', `Shallow scores ${packageData.ok ? 'fetched successfully' : 'fetch failed'}`);
|
|
16118
|
+
debug.debugDir('inspect', {
|
|
15989
16119
|
packageData
|
|
15990
16120
|
});
|
|
15991
16121
|
outputPurlsShallowScore(purls, packageData, outputKind);
|
|
@@ -16206,7 +16336,7 @@ async function run$m(argv, _importMeta, _context) {
|
|
|
16206
16336
|
}
|
|
16207
16337
|
}
|
|
16208
16338
|
|
|
16209
|
-
const require$3 = require$$
|
|
16339
|
+
const require$3 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
16210
16340
|
const CMD_NAME$g = constants.PNPM;
|
|
16211
16341
|
const description$j = 'Wraps pnpm with Socket security scanning';
|
|
16212
16342
|
const hidden$g = true;
|
|
@@ -16442,12 +16572,11 @@ async function fetchCreateRepo(config, options) {
|
|
|
16442
16572
|
return sockSdkCResult;
|
|
16443
16573
|
}
|
|
16444
16574
|
const sockSdk = sockSdkCResult.data;
|
|
16445
|
-
return await utils.handleApiCall(sockSdk.
|
|
16575
|
+
return await utils.handleApiCall(sockSdk.createRepository(orgSlug, repoName, {
|
|
16446
16576
|
default_branch: defaultBranch,
|
|
16447
16577
|
description,
|
|
16448
16578
|
homepage,
|
|
16449
|
-
|
|
16450
|
-
visibility
|
|
16579
|
+
visibility: visibility
|
|
16451
16580
|
}), {
|
|
16452
16581
|
description: 'to create a repository'
|
|
16453
16582
|
});
|
|
@@ -16479,8 +16608,8 @@ async function handleCreateRepo({
|
|
|
16479
16608
|
repoName,
|
|
16480
16609
|
visibility
|
|
16481
16610
|
}, outputKind) {
|
|
16482
|
-
|
|
16483
|
-
|
|
16611
|
+
debug.debugFn('notice', `Creating repository ${orgSlug}/${repoName}`);
|
|
16612
|
+
debug.debugDir('inspect', {
|
|
16484
16613
|
defaultBranch,
|
|
16485
16614
|
description,
|
|
16486
16615
|
homepage,
|
|
@@ -16497,8 +16626,8 @@ async function handleCreateRepo({
|
|
|
16497
16626
|
repoName,
|
|
16498
16627
|
visibility
|
|
16499
16628
|
});
|
|
16500
|
-
|
|
16501
|
-
|
|
16629
|
+
debug.debugFn('notice', `Repository creation ${data.ok ? 'succeeded' : 'failed'}`);
|
|
16630
|
+
debug.debugDir('inspect', {
|
|
16502
16631
|
data
|
|
16503
16632
|
});
|
|
16504
16633
|
outputCreateRepo(data, repoName, outputKind);
|
|
@@ -16638,7 +16767,7 @@ async function fetchDeleteRepo(orgSlug, repoName, options) {
|
|
|
16638
16767
|
return sockSdkCResult;
|
|
16639
16768
|
}
|
|
16640
16769
|
const sockSdk = sockSdkCResult.data;
|
|
16641
|
-
return await utils.handleApiCall(sockSdk.
|
|
16770
|
+
return await utils.handleApiCall(sockSdk.deleteRepository(orgSlug, repoName), {
|
|
16642
16771
|
description: 'to delete a repository'
|
|
16643
16772
|
});
|
|
16644
16773
|
}
|
|
@@ -16781,12 +16910,16 @@ async function fetchListAllRepos(orgSlug, options) {
|
|
|
16781
16910
|
};
|
|
16782
16911
|
}
|
|
16783
16912
|
// eslint-disable-next-line no-await-in-loop
|
|
16784
|
-
const orgRepoListCResult = await utils.handleApiCall(sockSdk.
|
|
16785
|
-
sort
|
|
16786
|
-
|
|
16787
|
-
|
|
16913
|
+
const orgRepoListCResult = await utils.handleApiCall(sockSdk.listRepositories(orgSlug, {
|
|
16914
|
+
...(sort ? {
|
|
16915
|
+
sort: sort
|
|
16916
|
+
} : {}),
|
|
16917
|
+
...(direction ? {
|
|
16918
|
+
direction: direction
|
|
16919
|
+
} : {}),
|
|
16920
|
+
per_page: 100,
|
|
16788
16921
|
// max
|
|
16789
|
-
page:
|
|
16922
|
+
page: nextPage
|
|
16790
16923
|
}), {
|
|
16791
16924
|
description: 'list of repositories'
|
|
16792
16925
|
});
|
|
@@ -16827,11 +16960,15 @@ async function fetchListRepos(config, options) {
|
|
|
16827
16960
|
return sockSdkCResult;
|
|
16828
16961
|
}
|
|
16829
16962
|
const sockSdk = sockSdkCResult.data;
|
|
16830
|
-
return await utils.handleApiCall(sockSdk.
|
|
16831
|
-
sort
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16963
|
+
return await utils.handleApiCall(sockSdk.listRepositories(orgSlug, {
|
|
16964
|
+
...(sort ? {
|
|
16965
|
+
sort: sort
|
|
16966
|
+
} : {}),
|
|
16967
|
+
...(direction ? {
|
|
16968
|
+
direction: direction
|
|
16969
|
+
} : {}),
|
|
16970
|
+
per_page: perPage,
|
|
16971
|
+
page
|
|
16835
16972
|
}), {
|
|
16836
16973
|
description: 'list of repositories'
|
|
16837
16974
|
});
|
|
@@ -16920,8 +17057,10 @@ async function handleListRepos({
|
|
|
16920
17057
|
if (!data.ok) {
|
|
16921
17058
|
await outputListRepos(data, outputKind, 0, 0, '', 0, direction);
|
|
16922
17059
|
} else {
|
|
16923
|
-
// Note: nextPage defaults to 0, is null when there's no next page
|
|
16924
|
-
|
|
17060
|
+
// Note: nextPage defaults to 0, is null when there's no next page.
|
|
17061
|
+
// The SDK's strict type marks it optional (absent === no next page), so
|
|
17062
|
+
// coalesce undefined to null to match outputListRepos's number | null.
|
|
17063
|
+
await outputListRepos(data, outputKind, page, data.data.nextPage ?? null, sort, perPage, direction);
|
|
16925
17064
|
}
|
|
16926
17065
|
}
|
|
16927
17066
|
}
|
|
@@ -17083,7 +17222,7 @@ async function fetchUpdateRepo(config, options) {
|
|
|
17083
17222
|
return sockSdkCResult;
|
|
17084
17223
|
}
|
|
17085
17224
|
const sockSdk = sockSdkCResult.data;
|
|
17086
|
-
return await utils.handleApiCall(sockSdk.
|
|
17225
|
+
return await utils.handleApiCall(sockSdk.updateRepository(orgSlug, repoName, {
|
|
17087
17226
|
default_branch: defaultBranch,
|
|
17088
17227
|
description,
|
|
17089
17228
|
homepage,
|
|
@@ -17265,7 +17404,7 @@ async function fetchViewRepo(orgSlug, repoName, options) {
|
|
|
17265
17404
|
return sockSdkCResult;
|
|
17266
17405
|
}
|
|
17267
17406
|
const sockSdk = sockSdkCResult.data;
|
|
17268
|
-
return await utils.handleApiCall(sockSdk.
|
|
17407
|
+
return await utils.handleApiCall(sockSdk.getRepository(orgSlug, repoName), {
|
|
17269
17408
|
description: 'repository data'
|
|
17270
17409
|
});
|
|
17271
17410
|
}
|
|
@@ -17672,6 +17811,7 @@ async function run$d(argv, importMeta, {
|
|
|
17672
17811
|
committers,
|
|
17673
17812
|
cwd: cwdOverride,
|
|
17674
17813
|
defaultBranch,
|
|
17814
|
+
dynamicSbomInference,
|
|
17675
17815
|
interactive = true,
|
|
17676
17816
|
json,
|
|
17677
17817
|
markdown,
|
|
@@ -17728,6 +17868,11 @@ async function run$d(argv, importMeta, {
|
|
|
17728
17868
|
autoManifest = false;
|
|
17729
17869
|
}
|
|
17730
17870
|
}
|
|
17871
|
+
// --dynamic-sbom-inference requires auto-manifest to generate the
|
|
17872
|
+
// per-workspace facts it feeds to Coana.
|
|
17873
|
+
if (dynamicSbomInference) {
|
|
17874
|
+
autoManifest = true;
|
|
17875
|
+
}
|
|
17731
17876
|
if (!branchName) {
|
|
17732
17877
|
if (sockJson.defaults?.scan?.create?.branch) {
|
|
17733
17878
|
branchName = sockJson.defaults.scan.create.branch;
|
|
@@ -17844,7 +17989,7 @@ async function run$d(argv, importMeta, {
|
|
|
17844
17989
|
const isUsingNonDefaultConcurrency = reachConcurrency !== reachabilityFlags['reachConcurrency']?.default;
|
|
17845
17990
|
const isUsingNonDefaultAnalytics = reachDisableAnalytics !== reachabilityFlags['reachDisableAnalytics']?.default;
|
|
17846
17991
|
const isUsingNonDefaultVersion = reachVersion !== reachabilityFlags['reachVersion']?.default;
|
|
17847
|
-
const isUsingAnyReachabilityFlags = hasReachEcosystems || hasReachExcludePaths || isUsingNonDefaultAnalytics || isUsingNonDefaultConcurrency || isUsingNonDefaultMemoryLimit || isUsingNonDefaultTimeout || isUsingNonDefaultVersion || reachContinueOnAnalysisErrors || reachContinueOnInstallErrors || reachContinueOnMissingLockFiles || reachContinueOnNoSourceFiles || reachEnableAnalysisSplitting || reachLazyMode || reachSkipCache || reachUseOnlyPregeneratedSboms;
|
|
17992
|
+
const isUsingAnyReachabilityFlags = dynamicSbomInference || hasReachEcosystems || hasReachExcludePaths || isUsingNonDefaultAnalytics || isUsingNonDefaultConcurrency || isUsingNonDefaultMemoryLimit || isUsingNonDefaultTimeout || isUsingNonDefaultVersion || reachContinueOnAnalysisErrors || reachContinueOnInstallErrors || reachContinueOnMissingLockFiles || reachContinueOnNoSourceFiles || reachEnableAnalysisSplitting || reachLazyMode || reachSkipCache || reachUseOnlyPregeneratedSboms;
|
|
17848
17993
|
|
|
17849
17994
|
// Validate target constraints when --reach is enabled.
|
|
17850
17995
|
const reachTargetValidation = reach ? await validateReachabilityTarget(targets, cwd) : {
|
|
@@ -17929,6 +18074,7 @@ async function run$d(argv, importMeta, {
|
|
|
17929
18074
|
pendingHead: Boolean(pendingHead),
|
|
17930
18075
|
pullRequest: Number(pullRequest),
|
|
17931
18076
|
reach: {
|
|
18077
|
+
dynamicSbomInference: Boolean(dynamicSbomInference),
|
|
17932
18078
|
excludePaths,
|
|
17933
18079
|
reachAnalysisMemoryLimit,
|
|
17934
18080
|
reachAnalysisTimeout,
|
|
@@ -17973,7 +18119,7 @@ async function fetchDeleteOrgFullScan(orgSlug, scanId, options) {
|
|
|
17973
18119
|
return sockSdkCResult;
|
|
17974
18120
|
}
|
|
17975
18121
|
const sockSdk = sockSdkCResult.data;
|
|
17976
|
-
return await utils.handleApiCall(sockSdk.
|
|
18122
|
+
return await utils.handleApiCall(sockSdk.deleteFullScan(orgSlug, scanId), {
|
|
17977
18123
|
description: 'to delete a scan'
|
|
17978
18124
|
});
|
|
17979
18125
|
}
|
|
@@ -18129,7 +18275,7 @@ async function outputDiffScan(result, {
|
|
|
18129
18275
|
// Dump the JSON to CLI and let NodeJS deal with truncation
|
|
18130
18276
|
|
|
18131
18277
|
logger.logger.log('Diff scan result:');
|
|
18132
|
-
logger.logger.log(require$$
|
|
18278
|
+
logger.logger.log(require$$10.inspect(result.data, {
|
|
18133
18279
|
showHidden: false,
|
|
18134
18280
|
depth: depth > 0 ? depth : null,
|
|
18135
18281
|
colors: true,
|
|
@@ -18543,13 +18689,14 @@ async function scanOneRepo(repoSlug, {
|
|
|
18543
18689
|
};
|
|
18544
18690
|
}
|
|
18545
18691
|
const tmpDir = fs$1.mkdtempSync(path.join(os.tmpdir(), repoSlug));
|
|
18546
|
-
|
|
18692
|
+
debug.debugFn('notice', 'init: temp dir for scan root', tmpDir);
|
|
18547
18693
|
const downloadResult = await testAndDownloadManifestFiles({
|
|
18548
18694
|
files,
|
|
18549
18695
|
tmpDir,
|
|
18550
18696
|
repoSlug,
|
|
18551
18697
|
defaultBranch,
|
|
18552
18698
|
orgGithub,
|
|
18699
|
+
orgSlug,
|
|
18553
18700
|
repoApiUrl,
|
|
18554
18701
|
githubToken
|
|
18555
18702
|
});
|
|
@@ -18589,6 +18736,7 @@ async function scanOneRepo(repoSlug, {
|
|
|
18589
18736
|
pendingHead: true,
|
|
18590
18737
|
pullRequest: 0,
|
|
18591
18738
|
reach: {
|
|
18739
|
+
dynamicSbomInference: false,
|
|
18592
18740
|
excludePaths: [],
|
|
18593
18741
|
reachAnalysisMemoryLimit: '',
|
|
18594
18742
|
reachAnalysisTimeout: '',
|
|
@@ -18630,6 +18778,7 @@ async function testAndDownloadManifestFiles({
|
|
|
18630
18778
|
files,
|
|
18631
18779
|
githubToken,
|
|
18632
18780
|
orgGithub,
|
|
18781
|
+
orgSlug,
|
|
18633
18782
|
repoApiUrl,
|
|
18634
18783
|
repoSlug,
|
|
18635
18784
|
tmpDir
|
|
@@ -18644,6 +18793,7 @@ async function testAndDownloadManifestFiles({
|
|
|
18644
18793
|
file,
|
|
18645
18794
|
tmpDir,
|
|
18646
18795
|
defaultBranch,
|
|
18796
|
+
orgSlug,
|
|
18647
18797
|
repoApiUrl,
|
|
18648
18798
|
githubToken
|
|
18649
18799
|
});
|
|
@@ -18677,14 +18827,17 @@ async function testAndDownloadManifestFile({
|
|
|
18677
18827
|
defaultBranch,
|
|
18678
18828
|
file,
|
|
18679
18829
|
githubToken,
|
|
18830
|
+
orgSlug,
|
|
18680
18831
|
repoApiUrl,
|
|
18681
18832
|
tmpDir
|
|
18682
18833
|
}) {
|
|
18683
|
-
|
|
18684
|
-
const supportedFilesCResult = await fetchSupportedScanFileNames(
|
|
18834
|
+
debug.debugFn('notice', 'testing: file', file);
|
|
18835
|
+
const supportedFilesCResult = await fetchSupportedScanFileNames({
|
|
18836
|
+
orgSlug
|
|
18837
|
+
});
|
|
18685
18838
|
const supportedFiles = supportedFilesCResult.ok ? supportedFilesCResult.data : undefined;
|
|
18686
18839
|
if (!supportedFiles || !utils.isReportSupportedFile(file, supportedFiles)) {
|
|
18687
|
-
|
|
18840
|
+
debug.debugFn('notice', 'skip: not a known pattern');
|
|
18688
18841
|
// Not an error.
|
|
18689
18842
|
return {
|
|
18690
18843
|
ok: true,
|
|
@@ -18693,7 +18846,7 @@ async function testAndDownloadManifestFile({
|
|
|
18693
18846
|
}
|
|
18694
18847
|
};
|
|
18695
18848
|
}
|
|
18696
|
-
|
|
18849
|
+
debug.debugFn('notice', 'found: manifest file, going to attempt to download it;', file);
|
|
18697
18850
|
const result = await downloadManifestFile({
|
|
18698
18851
|
file,
|
|
18699
18852
|
tmpDir,
|
|
@@ -18715,9 +18868,9 @@ async function downloadManifestFile({
|
|
|
18715
18868
|
repoApiUrl,
|
|
18716
18869
|
tmpDir
|
|
18717
18870
|
}) {
|
|
18718
|
-
|
|
18871
|
+
debug.debugFn('notice', 'request: download url from GitHub');
|
|
18719
18872
|
const fileUrl = `${repoApiUrl}/contents/${file}?ref=${defaultBranch}`;
|
|
18720
|
-
|
|
18873
|
+
debug.debugDir('inspect', {
|
|
18721
18874
|
fileUrl
|
|
18722
18875
|
});
|
|
18723
18876
|
utils.debugApiRequest('GET', fileUrl);
|
|
@@ -18734,9 +18887,9 @@ async function downloadManifestFile({
|
|
|
18734
18887
|
utils.debugApiResponse('GET', fileUrl, undefined, e);
|
|
18735
18888
|
throw e;
|
|
18736
18889
|
}
|
|
18737
|
-
|
|
18890
|
+
debug.debugFn('notice', 'complete: request');
|
|
18738
18891
|
const downloadUrlText = await downloadUrlResponse.text();
|
|
18739
|
-
|
|
18892
|
+
debug.debugFn('inspect', 'response: raw download url', downloadUrlText);
|
|
18740
18893
|
let downloadUrl;
|
|
18741
18894
|
try {
|
|
18742
18895
|
downloadUrl = JSON.parse(downloadUrlText).download_url;
|
|
@@ -18749,7 +18902,7 @@ async function downloadManifestFile({
|
|
|
18749
18902
|
};
|
|
18750
18903
|
}
|
|
18751
18904
|
const localPath = path.join(tmpDir, file);
|
|
18752
|
-
|
|
18905
|
+
debug.debugFn('notice', 'download: manifest file started', downloadUrl, '->', localPath);
|
|
18753
18906
|
|
|
18754
18907
|
// Now stream the file to that file...
|
|
18755
18908
|
const result = await streamDownloadWithFetch(localPath, downloadUrl);
|
|
@@ -18758,7 +18911,7 @@ async function downloadManifestFile({
|
|
|
18758
18911
|
logger.logger.fail(`Failed to download manifest file, skipping to next file. File: ${file}`);
|
|
18759
18912
|
return result;
|
|
18760
18913
|
}
|
|
18761
|
-
|
|
18914
|
+
debug.debugFn('notice', 'download: manifest file completed');
|
|
18762
18915
|
return {
|
|
18763
18916
|
ok: true,
|
|
18764
18917
|
data: undefined
|
|
@@ -18803,7 +18956,7 @@ async function streamDownloadWithFetch(localPath, downloadUrl) {
|
|
|
18803
18956
|
|
|
18804
18957
|
// Using stream.pipeline for better error handling and cleanup
|
|
18805
18958
|
|
|
18806
|
-
await
|
|
18959
|
+
await require$$9.pipeline(response.body, fileStream);
|
|
18807
18960
|
// 'pipeline' will automatically handle closing streams and propagating errors.
|
|
18808
18961
|
// It resolves when the piping is fully complete and fileStream is closed.
|
|
18809
18962
|
return {
|
|
@@ -18815,7 +18968,7 @@ async function streamDownloadWithFetch(localPath, downloadUrl) {
|
|
|
18815
18968
|
utils.debugApiResponse('GET', downloadUrl, undefined, e);
|
|
18816
18969
|
}
|
|
18817
18970
|
logger.logger.fail('An error was thrown while trying to download a manifest file... url:', downloadUrl);
|
|
18818
|
-
|
|
18971
|
+
debug.debugDir('error', e);
|
|
18819
18972
|
|
|
18820
18973
|
// If an error occurs and fileStream was created, attempt to clean up.
|
|
18821
18974
|
if (fs$1.existsSync(localPath)) {
|
|
@@ -18837,7 +18990,7 @@ async function streamDownloadWithFetch(localPath, downloadUrl) {
|
|
|
18837
18990
|
// If error was due to bad HTTP status
|
|
18838
18991
|
detailedError += ` (HTTP Status: ${response.status} ${response.statusText})`;
|
|
18839
18992
|
}
|
|
18840
|
-
|
|
18993
|
+
debug.debugFn('error', detailedError);
|
|
18841
18994
|
return {
|
|
18842
18995
|
ok: false,
|
|
18843
18996
|
message: 'Download Failed',
|
|
@@ -18854,7 +19007,7 @@ async function getLastCommitDetails({
|
|
|
18854
19007
|
}) {
|
|
18855
19008
|
logger.logger.info(`Requesting last commit for default branch ${defaultBranch} for ${orgGithub}/${repoSlug}...`);
|
|
18856
19009
|
const commitApiUrl = `${repoApiUrl}/commits?sha=${defaultBranch}&per_page=1`;
|
|
18857
|
-
|
|
19010
|
+
debug.debugFn('inspect', 'url: commit', commitApiUrl);
|
|
18858
19011
|
utils.debugApiRequest('GET', commitApiUrl);
|
|
18859
19012
|
let commitResponse;
|
|
18860
19013
|
try {
|
|
@@ -18869,7 +19022,7 @@ async function getLastCommitDetails({
|
|
|
18869
19022
|
throw e;
|
|
18870
19023
|
}
|
|
18871
19024
|
const commitText = await commitResponse.text();
|
|
18872
|
-
|
|
19025
|
+
debug.debugFn('inspect', 'response: commit', commitText);
|
|
18873
19026
|
let lastCommit;
|
|
18874
19027
|
try {
|
|
18875
19028
|
lastCommit = JSON.parse(commitText)?.[0];
|
|
@@ -18956,7 +19109,7 @@ async function getRepoDetails({
|
|
|
18956
19109
|
repoSlug
|
|
18957
19110
|
}) {
|
|
18958
19111
|
const repoApiUrl = `${githubApiUrl}/repos/${orgGithub}/${repoSlug}`;
|
|
18959
|
-
|
|
19112
|
+
debug.debugDir('inspect', {
|
|
18960
19113
|
repoApiUrl
|
|
18961
19114
|
});
|
|
18962
19115
|
let repoDetailsResponse;
|
|
@@ -18975,7 +19128,7 @@ async function getRepoDetails({
|
|
|
18975
19128
|
}
|
|
18976
19129
|
logger.logger.success(`Request completed.`);
|
|
18977
19130
|
const repoDetailsText = await repoDetailsResponse.text();
|
|
18978
|
-
|
|
19131
|
+
debug.debugFn('inspect', 'response: repo', repoDetailsText);
|
|
18979
19132
|
let repoDetails;
|
|
18980
19133
|
try {
|
|
18981
19134
|
repoDetails = JSON.parse(repoDetailsText);
|
|
@@ -19014,7 +19167,7 @@ async function getRepoBranchTree({
|
|
|
19014
19167
|
}) {
|
|
19015
19168
|
logger.logger.info(`Requesting default branch file tree; branch \`${defaultBranch}\`, repo \`${orgGithub}/${repoSlug}\`...`);
|
|
19016
19169
|
const treeApiUrl = `${repoApiUrl}/git/trees/${defaultBranch}?recursive=1`;
|
|
19017
|
-
|
|
19170
|
+
debug.debugFn('inspect', 'url: tree', treeApiUrl);
|
|
19018
19171
|
let treeResponse;
|
|
19019
19172
|
try {
|
|
19020
19173
|
utils.debugApiRequest('GET', treeApiUrl);
|
|
@@ -19030,7 +19183,7 @@ async function getRepoBranchTree({
|
|
|
19030
19183
|
throw e;
|
|
19031
19184
|
}
|
|
19032
19185
|
const treeText = await treeResponse.text();
|
|
19033
|
-
|
|
19186
|
+
debug.debugFn('inspect', 'response: tree', treeText);
|
|
19034
19187
|
let treeDetails;
|
|
19035
19188
|
try {
|
|
19036
19189
|
treeDetails = JSON.parse(treeText);
|
|
@@ -19059,7 +19212,7 @@ async function getRepoBranchTree({
|
|
|
19059
19212
|
};
|
|
19060
19213
|
}
|
|
19061
19214
|
if (!treeDetails.tree || !Array.isArray(treeDetails.tree)) {
|
|
19062
|
-
|
|
19215
|
+
debug.debugDir('inspect', {
|
|
19063
19216
|
treeDetails: {
|
|
19064
19217
|
tree: treeDetails.tree
|
|
19065
19218
|
}
|
|
@@ -19340,18 +19493,22 @@ async function fetchOrgFullScanList(config, options) {
|
|
|
19340
19493
|
__proto__: null,
|
|
19341
19494
|
...config
|
|
19342
19495
|
};
|
|
19343
|
-
return await utils.handleApiCall(sockSdk.
|
|
19496
|
+
return await utils.handleApiCall(sockSdk.listFullScans(orgSlug, {
|
|
19344
19497
|
...(branch ? {
|
|
19345
19498
|
branch
|
|
19346
19499
|
} : {}),
|
|
19347
19500
|
...(repo ? {
|
|
19348
19501
|
repo
|
|
19349
19502
|
} : {}),
|
|
19350
|
-
sort
|
|
19351
|
-
|
|
19503
|
+
...(sort ? {
|
|
19504
|
+
sort: sort
|
|
19505
|
+
} : {}),
|
|
19506
|
+
...(direction ? {
|
|
19507
|
+
direction: direction
|
|
19508
|
+
} : {}),
|
|
19352
19509
|
from: from_time,
|
|
19353
|
-
page
|
|
19354
|
-
per_page:
|
|
19510
|
+
page,
|
|
19511
|
+
per_page: perPage
|
|
19355
19512
|
}), {
|
|
19356
19513
|
description: 'list of scans'
|
|
19357
19514
|
});
|
|
@@ -19595,7 +19752,7 @@ async function fetchScanMetadata(orgSlug, scanId, options) {
|
|
|
19595
19752
|
return sockSdkCResult;
|
|
19596
19753
|
}
|
|
19597
19754
|
const sockSdk = sockSdkCResult.data;
|
|
19598
|
-
return await utils.handleApiCall(sockSdk.
|
|
19755
|
+
return await utils.handleApiCall(sockSdk.getFullScanMetadata(orgSlug, scanId), {
|
|
19599
19756
|
description: 'meta data for a full scan'
|
|
19600
19757
|
});
|
|
19601
19758
|
}
|
|
@@ -19780,6 +19937,7 @@ async function handleScanReach({
|
|
|
19780
19937
|
|
|
19781
19938
|
// Get supported file names.
|
|
19782
19939
|
const supportedFilesCResult = await fetchSupportedScanFileNames({
|
|
19940
|
+
orgSlug,
|
|
19783
19941
|
spinner
|
|
19784
19942
|
});
|
|
19785
19943
|
if (!supportedFilesCResult.ok) {
|
|
@@ -20041,6 +20199,9 @@ async function run$7(argv, importMeta, {
|
|
|
20041
20199
|
outputKind,
|
|
20042
20200
|
outputPath: outputPath || '',
|
|
20043
20201
|
reachabilityOptions: {
|
|
20202
|
+
// Not exposed here: it relies on --auto-manifest generating per-workspace
|
|
20203
|
+
// Socket facts first, which `socket scan reach` never runs.
|
|
20204
|
+
dynamicSbomInference: false,
|
|
20044
20205
|
excludePaths,
|
|
20045
20206
|
reachAnalysisMemoryLimit,
|
|
20046
20207
|
reachAnalysisTimeout,
|
|
@@ -20588,39 +20749,71 @@ async function run$5(argv, importMeta, {
|
|
|
20588
20749
|
await handleScanConfig(cwd, Boolean(defaultOnReadError));
|
|
20589
20750
|
}
|
|
20590
20751
|
|
|
20752
|
+
// HTTP 202 Accepted: cached results are still being computed; poll again.
|
|
20753
|
+
const HTTP_STATUS_ACCEPTED = 202;
|
|
20754
|
+
const CACHED_POLL_INITIAL_DELAY_MS = 1000;
|
|
20755
|
+
const CACHED_POLL_MAX_DELAY_MS = 10_000;
|
|
20756
|
+
const CACHED_POLL_TIMEOUT_MS = 10 * 60 * 1000;
|
|
20757
|
+
function sleep(ms) {
|
|
20758
|
+
return new Promise(resolve => {
|
|
20759
|
+
setTimeout(resolve, ms);
|
|
20760
|
+
});
|
|
20761
|
+
}
|
|
20591
20762
|
async function fetchScan(orgSlug, scanId) {
|
|
20592
|
-
|
|
20593
|
-
|
|
20594
|
-
|
|
20763
|
+
// Serve pre-computed results from the immutable store (`?cached=true`): a
|
|
20764
|
+
// 200 carries the ndjson body, a 202 means the server enqueued a background
|
|
20765
|
+
// job to compute them — poll with backoff until the results are ready, so
|
|
20766
|
+
// callers only ever observe the final scan.
|
|
20767
|
+
const path = `orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}?cached=true`;
|
|
20768
|
+
const deadline = Date.now() + CACHED_POLL_TIMEOUT_MS;
|
|
20769
|
+
let delayMs = CACHED_POLL_INITIAL_DELAY_MS;
|
|
20770
|
+
for (;;) {
|
|
20771
|
+
// eslint-disable-next-line no-await-in-loop
|
|
20772
|
+
const result = await utils.queryApiSafeTextWithStatus(path, 'a scan');
|
|
20773
|
+
if (!result.ok) {
|
|
20774
|
+
return result;
|
|
20775
|
+
}
|
|
20776
|
+
if (result.data.status !== HTTP_STATUS_ACCEPTED) {
|
|
20777
|
+
return parseArtifactsNdjson(result.data.text);
|
|
20778
|
+
}
|
|
20779
|
+
if (Date.now() >= deadline) {
|
|
20780
|
+
return {
|
|
20781
|
+
ok: false,
|
|
20782
|
+
message: 'Scan results not ready',
|
|
20783
|
+
cause: `The Socket API is still computing cached results for scan ${scanId} after ${CACHED_POLL_TIMEOUT_MS / 60_000} minutes (path: ${path}). Retry in a few minutes — the server keeps computing in the background.`
|
|
20784
|
+
};
|
|
20785
|
+
}
|
|
20786
|
+
// eslint-disable-next-line no-await-in-loop
|
|
20787
|
+
await sleep(delayMs);
|
|
20788
|
+
delayMs = Math.min(delayMs * 2, CACHED_POLL_MAX_DELAY_MS);
|
|
20595
20789
|
}
|
|
20596
|
-
|
|
20597
|
-
|
|
20598
|
-
// This is nd-json; each line is a json object
|
|
20790
|
+
}
|
|
20791
|
+
function parseArtifactsNdjson(jsonsString) {
|
|
20792
|
+
// This is nd-json; each line is a json object.
|
|
20599
20793
|
const lines = jsonsString.split('\n').filter(Boolean);
|
|
20600
|
-
|
|
20601
|
-
|
|
20794
|
+
const data = [];
|
|
20795
|
+
for (let i = 0, {
|
|
20796
|
+
length
|
|
20797
|
+
} = lines; i < length; i += 1) {
|
|
20798
|
+
const line = lines[i];
|
|
20602
20799
|
try {
|
|
20603
|
-
|
|
20800
|
+
data.push(JSON.parse(line));
|
|
20604
20801
|
} catch (e) {
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
require$$9.debugDir('error', {
|
|
20802
|
+
debug.debugFn('error', 'Failed to parse scan result line as JSON');
|
|
20803
|
+
debug.debugDir('error', {
|
|
20608
20804
|
error: e,
|
|
20609
20805
|
line
|
|
20610
20806
|
});
|
|
20611
|
-
return
|
|
20807
|
+
return {
|
|
20808
|
+
ok: false,
|
|
20809
|
+
message: 'Invalid Socket API response',
|
|
20810
|
+
cause: 'The Socket API responded with at least one line that was not valid JSON. Please report if this persists.'
|
|
20811
|
+
};
|
|
20612
20812
|
}
|
|
20613
|
-
});
|
|
20614
|
-
if (ok) {
|
|
20615
|
-
return {
|
|
20616
|
-
ok: true,
|
|
20617
|
-
data
|
|
20618
|
-
};
|
|
20619
20813
|
}
|
|
20620
20814
|
return {
|
|
20621
|
-
ok:
|
|
20622
|
-
|
|
20623
|
-
cause: 'The Socket API responded with at least one line that was not valid JSON. Please report if this persists.'
|
|
20815
|
+
ok: true,
|
|
20816
|
+
data
|
|
20624
20817
|
};
|
|
20625
20818
|
}
|
|
20626
20819
|
|
|
@@ -20715,7 +20908,9 @@ async function streamScan(orgSlug, scanId, options) {
|
|
|
20715
20908
|
logger.logger.info('Requesting data from API...');
|
|
20716
20909
|
|
|
20717
20910
|
// Note: this will write to stdout or target file. It's not a noop
|
|
20718
|
-
return await utils.handleApiCall(sockSdk.
|
|
20911
|
+
return await utils.handleApiCall(sockSdk.streamFullScan(orgSlug, scanId, {
|
|
20912
|
+
output: file === '-' ? undefined : file
|
|
20913
|
+
}), {
|
|
20719
20914
|
description: 'a scan'
|
|
20720
20915
|
});
|
|
20721
20916
|
}
|
|
@@ -20885,7 +21080,7 @@ async function fetchThreatFeed({
|
|
|
20885
21080
|
return await utils.queryApiSafeJson(`orgs/${orgSlug}/threat-feed?${queryParams}`, 'the Threat Feed data');
|
|
20886
21081
|
}
|
|
20887
21082
|
|
|
20888
|
-
const require$2 = require$$
|
|
21083
|
+
const require$2 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
20889
21084
|
async function outputThreatFeed(result, outputKind) {
|
|
20890
21085
|
if (!result.ok) {
|
|
20891
21086
|
process.exitCode = result.code ?? 1;
|
|
@@ -21488,8 +21683,8 @@ Do you want to install the Socket npm wrapper (this will create an alias to the
|
|
|
21488
21683
|
}
|
|
21489
21684
|
}
|
|
21490
21685
|
} catch (e) {
|
|
21491
|
-
|
|
21492
|
-
|
|
21686
|
+
debug.debugFn('warn', 'Tab completion setup failed (non-fatal)');
|
|
21687
|
+
debug.debugDir('warn', e);
|
|
21493
21688
|
// Ignore. Skip tab completion setup.
|
|
21494
21689
|
}
|
|
21495
21690
|
if (!updatedTabCompletion) {
|
|
@@ -21654,7 +21849,7 @@ async function run$1(argv, importMeta, {
|
|
|
21654
21849
|
}
|
|
21655
21850
|
}
|
|
21656
21851
|
|
|
21657
|
-
const require$1 = require$$
|
|
21852
|
+
const require$1 = require$$1.createRequire((typeof document === 'undefined' ? require$$0$1.pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
21658
21853
|
const CMD_NAME = constants.YARN;
|
|
21659
21854
|
const description = 'Wraps yarn with Socket security scanning';
|
|
21660
21855
|
const hidden = true;
|
|
@@ -21879,8 +22074,8 @@ void (async () => {
|
|
|
21879
22074
|
|
|
21880
22075
|
// Track CLI error for telemetry.
|
|
21881
22076
|
await utils.trackCliError(process.argv, cliStartTime, e, process.exitCode);
|
|
21882
|
-
|
|
21883
|
-
|
|
22077
|
+
debug.debugFn('error', 'CLI uncaught error');
|
|
22078
|
+
debug.debugDir('error', e);
|
|
21884
22079
|
let errorBody;
|
|
21885
22080
|
let errorTitle;
|
|
21886
22081
|
let errorMessage = '';
|
|
@@ -21924,7 +22119,7 @@ void (async () => {
|
|
|
21924
22119
|
logger.logger.error('\n');
|
|
21925
22120
|
logger.logger.fail(utils.failMsgWithBadge(errorTitle, errorMessage));
|
|
21926
22121
|
if (errorBody) {
|
|
21927
|
-
|
|
22122
|
+
debug.debugDir('inspect', {
|
|
21928
22123
|
errorBody
|
|
21929
22124
|
});
|
|
21930
22125
|
}
|
|
@@ -21973,5 +22168,5 @@ process.on('unhandledRejection', async (reason, promise) => {
|
|
|
21973
22168
|
// eslint-disable-next-line n/no-process-exit
|
|
21974
22169
|
process.exit(1);
|
|
21975
22170
|
});
|
|
21976
|
-
//# debugId=
|
|
22171
|
+
//# debugId=69b61d3f-9a18-4a06-a0cd-4567860caa90
|
|
21977
22172
|
//# sourceMappingURL=cli.js.map
|