Skip to content

Commit 175c43a

Browse files
committed
feat: backport v1.x features and DRY out HTTP layer
Backport missing features from v1.x branch: - SSL_CERT_FILE support for TLS certificate configuration - Request URL included in API error messages - --reach-version flag for scan/reach commands - --reach-enable-analysis-splitting (splitting disabled by default) - --reach-detailed-analysis-log-file flag - --reach-disable-external-tool-checks flag for scan and fix commands - --output flag for socket scan reach - PR link/number in socket fix JSON output (ghsaDetails) - Enhanced Coana error logging on reachability failure - Remove unused cwd from output-scan-reach DRY out HTTP requests: - Replace all direct fetch() calls with socketHttpRequest wrapper - Use httpRequest from @socketsecurity/lib for all HTTP communication - Centralize SSL_CERT_FILE/CA cert handling in socketHttpRequest - Remove hand-rolled _httpsRequestFetch redirect/TLS implementation
1 parent e5bf9fa commit 175c43a

20 files changed

Lines changed: 385 additions & 161 deletions

packages/cli/src/commands/ci/handle-ci.mts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,18 @@ export async function handleCi(autoManifest: boolean): Promise<void> {
5555
reachAnalysisTimeout: 0,
5656
reachConcurrency: 1,
5757
reachDebug: false,
58+
reachDetailedAnalysisLogFile: false,
5859
reachDisableAnalytics: false,
59-
reachDisableAnalysisSplitting: false,
60+
reachDisableExternalToolChecks: false,
61+
reachEnableAnalysisSplitting: false,
6062
reachEcosystems: [],
6163
reachExcludePaths: [],
6264
reachLazyMode: false,
6365
reachMinSeverity: '',
6466
reachSkipCache: false,
6567
reachUseOnlyPregeneratedSboms: false,
6668
reachUseUnreachableFromPrecomputation: false,
69+
reachVersion: undefined,
6770
runReachabilityAnalysis: false,
6871
},
6972
repoName,

packages/cli/src/commands/fix/cmd-fix.mts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface FixFlags {
4141
applyFixes: boolean
4242
autopilot: boolean
4343
debug: boolean
44+
disableExternalToolChecks: boolean
4445
ecosystems: string[]
4546
exclude: string[]
4647
fixVersion: string | undefined
@@ -177,6 +178,12 @@ Available styles:
177178
'Enable debug logging in the Coana-based Socket Fix CLI invocation.',
178179
shortFlag: 'd',
179180
},
181+
disableExternalToolChecks: {
182+
type: 'boolean',
183+
default: false,
184+
description: 'Disable external tool checks during fix analysis.',
185+
hidden: true,
186+
},
180187
showAffectedDirectDependencies: {
181188
type: 'boolean',
182189
default: false,
@@ -324,6 +331,7 @@ async function run(
324331
applyFixes,
325332
autopilot,
326333
debug,
334+
disableExternalToolChecks,
327335
ecosystems,
328336
exclude,
329337
fixVersion,
@@ -486,6 +494,7 @@ async function run(
486494
coanaVersion: fixVersion,
487495
cwd,
488496
debug,
497+
disableExternalToolChecks: Boolean(disableExternalToolChecks),
489498
disableMajorUpdates,
490499
ecosystems: validatedEcosystems,
491500
exclude: excludePatterns,

packages/cli/src/commands/fix/coana-fix.mts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import path from 'node:path'
44

55
import { joinAnd } from '@socketsecurity/lib/arrays'
66
import { debug, debugDir } from '@socketsecurity/lib/debug'
7-
import { readJsonSync } from '@socketsecurity/lib/fs'
87
import { getDefaultLogger } from '@socketsecurity/lib/logger'
98
import { pluralize } from '@socketsecurity/lib/words'
109

@@ -67,16 +66,24 @@ async function cleanupTempFile(filePath: string): Promise<void> {
6766
}
6867
}
6968

69+
export type GhsaFixResult = {
70+
ghsaId: string
71+
fixed: boolean
72+
pullRequestLink?: string | undefined
73+
pullRequestNumber?: number | undefined
74+
}
75+
7076
export async function coanaFix(
7177
fixConfig: FixConfig,
72-
): Promise<CResult<{ data?: unknown; fixed: boolean }>> {
78+
): Promise<CResult<{ fixedAll: boolean; ghsaDetails: GhsaFixResult[] }>> {
7379
const {
7480
all,
7581
applyFixes,
7682
autopilot,
7783
coanaVersion,
7884
cwd,
7985
debug: debugFlag,
86+
disableExternalToolChecks,
8087
disableMajorUpdates,
8188
ecosystems,
8289
exclude,
@@ -188,7 +195,7 @@ export async function coanaFix(
188195
: ghsas.slice(0, prLimit)
189196
if (!idsToProcess.length) {
190197
spinner?.stop()
191-
return { ok: true, data: { fixed: false } }
198+
return { ok: true, data: { fixedAll: false, ghsaDetails: [] } }
192199
}
193200

194201
// Create a temporary file for the output.
@@ -217,6 +224,9 @@ export async function coanaFix(
217224
'--output-file',
218225
tmpFile,
219226
...(debugFlag ? ['--debug'] : []),
227+
...(disableExternalToolChecks
228+
? ['--disable-external-tool-checks']
229+
: []),
220230
...(disableMajorUpdates ? ['--disable-major-updates'] : []),
221231
...(showAffectedDirectDependencies
222232
? ['--show-affected-direct-dependencies']
@@ -233,17 +243,23 @@ export async function coanaFix(
233243
return fixCResult
234244
}
235245

236-
// Read the temporary file to get the actual fixes result.
237-
const fixesResultJson = readJsonSync(tmpFile, { throws: false })
238-
239246
// Copy to outputFile if provided.
240247
if (outputFile) {
241248
logger.info(`Copying fixes result to ${outputFile}`)
242249
const tmpContent = await fs.readFile(tmpFile, 'utf8')
243250
await fs.writeFile(outputFile, tmpContent, 'utf8')
244251
}
245252

246-
return { ok: true, data: { data: fixesResultJson, fixed: true } }
253+
return {
254+
ok: true,
255+
data: {
256+
fixedAll: true,
257+
ghsaDetails: idsToProcess.map(id => ({
258+
ghsaId: id,
259+
fixed: true,
260+
})),
261+
},
262+
}
247263
} finally {
248264
// Clean up the temporary file.
249265
await cleanupTempFile(tmpFile)
@@ -334,7 +350,7 @@ export async function coanaFix(
334350

335351
if (!ids?.length || !fixEnv.repoInfo) {
336352
spinner?.stop()
337-
return { ok: true, data: { fixed: false } }
353+
return { ok: true, data: { fixedAll: false, ghsaDetails: [] } }
338354
}
339355

340356
const displayIds =
@@ -390,6 +406,7 @@ export async function coanaFix(
390406

391407
let count = 0
392408
let overallFixed = false
409+
const ghsaFixResults: GhsaFixResult[] = []
393410

394411
// Process each GHSA ID individually.
395412
// Use unprocessedIds instead of ids to skip already-fixed GHSAs.
@@ -417,6 +434,9 @@ export async function coanaFix(
417434
...(exclude.length ? ['--exclude', ...exclude] : []),
418435
...(ecosystems.length ? ['--purl-types', ...ecosystems] : []),
419436
...(debugFlag ? ['--debug'] : []),
437+
...(disableExternalToolChecks
438+
? ['--disable-external-tool-checks']
439+
: []),
420440
...(disableMajorUpdates ? ['--disable-major-updates'] : []),
421441
...(showAffectedDirectDependencies
422442
? ['--show-affected-direct-dependencies']
@@ -609,6 +629,13 @@ export async function coanaFix(
609629
logger.info(`PR URL: ${data.html_url}`)
610630
logPrEvent('created', data.number, ghsaId, data.html_url)
611631

632+
ghsaFixResults.push({
633+
fixed: true,
634+
ghsaId,
635+
pullRequestLink: data.html_url,
636+
pullRequestNumber: data.number,
637+
})
638+
612639
// Mark GHSA as fixed in tracker.
613640
// eslint-disable-next-line no-await-in-loop
614641
await markGhsaFixed(cwd, ghsaId, data.number, branch)
@@ -707,6 +734,6 @@ export async function coanaFix(
707734

708735
return {
709736
ok: true,
710-
data: { fixed: overallFixed },
737+
data: { fixedAll: overallFixed, ghsaDetails: ghsaFixResults },
711738
}
712739
}

packages/cli/src/commands/fix/handle-fix.mts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export async function handleFix({
110110
coanaVersion,
111111
cwd,
112112
debug: debugFlag,
113+
disableExternalToolChecks,
113114
disableMajorUpdates,
114115
ecosystems,
115116
exclude,
@@ -136,6 +137,7 @@ export async function handleFix({
136137
coanaVersion,
137138
cwd,
138139
debug: debugFlag,
140+
disableExternalToolChecks,
139141
disableMajorUpdates,
140142
ecosystems,
141143
exclude,
@@ -160,6 +162,7 @@ export async function handleFix({
160162
coanaVersion,
161163
cwd,
162164
debug: debugFlag,
165+
disableExternalToolChecks,
163166
disableMajorUpdates,
164167
ecosystems,
165168
exclude,

packages/cli/src/commands/fix/types.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type FixConfig = {
1010
coanaVersion: string | undefined
1111
cwd: string
1212
debug: boolean
13+
disableExternalToolChecks: boolean
1314
disableMajorUpdates: boolean
1415
ecosystems: PURL_Type[]
1516
exclude: string[]

packages/cli/src/commands/scan/cmd-scan-create.mts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,16 @@ interface ScanCreateFlags {
6262
reachAnalysisTimeout: number
6363
reachConcurrency: number
6464
reachDebug: boolean
65-
reachDisableAnalysisSplitting: boolean
65+
reachDetailedAnalysisLogFile: boolean
6666
reachDisableAnalytics: boolean
67+
reachDisableExternalToolChecks: boolean
68+
reachEnableAnalysisSplitting: boolean
6769
reachLazyMode: boolean
6870
reachMinSeverity: string
6971
reachSkipCache: boolean
7072
reachUseOnlyPregeneratedSboms: boolean
7173
reachUseUnreachableFromPrecomputation: boolean
74+
reachVersion: string
7275
readOnly: boolean
7376
repo: string
7477
report?: boolean | undefined
@@ -292,13 +295,16 @@ async function run(
292295
reachAnalysisTimeout,
293296
reachConcurrency,
294297
reachDebug,
295-
reachDisableAnalysisSplitting,
298+
reachDetailedAnalysisLogFile,
296299
reachDisableAnalytics,
300+
reachDisableExternalToolChecks,
301+
reachEnableAnalysisSplitting,
297302
reachLazyMode,
298303
reachMinSeverity,
299304
reachSkipCache,
300305
reachUseOnlyPregeneratedSboms,
301306
reachUseUnreachableFromPrecomputation,
307+
reachVersion,
302308
readOnly,
303309
reportLevel,
304310
setAsAlertsPage: pendingHeadFlag,
@@ -484,9 +490,9 @@ async function run(
484490
isUsingNonDefaultAnalytics ||
485491
hasReachEcosystems ||
486492
hasReachExcludePaths ||
493+
reachEnableAnalysisSplitting ||
487494
reachLazyMode ||
488-
reachSkipCache ||
489-
reachDisableAnalysisSplitting
495+
reachSkipCache
490496

491497
// Validate target constraints when --reach is enabled.
492498
const reachTargetValidation = reach
@@ -650,8 +656,10 @@ async function run(
650656
reachAnalysisTimeout: validatedReachAnalysisTimeout,
651657
reachConcurrency: validatedReachConcurrency,
652658
reachDebug: Boolean(reachDebug),
659+
reachDetailedAnalysisLogFile: Boolean(reachDetailedAnalysisLogFile),
653660
reachDisableAnalytics: Boolean(reachDisableAnalytics),
654-
reachDisableAnalysisSplitting: Boolean(reachDisableAnalysisSplitting),
661+
reachDisableExternalToolChecks: Boolean(reachDisableExternalToolChecks),
662+
reachEnableAnalysisSplitting: Boolean(reachEnableAnalysisSplitting),
655663
reachEcosystems,
656664
reachExcludePaths,
657665
reachLazyMode: Boolean(reachLazyMode),
@@ -661,6 +669,7 @@ async function run(
661669
reachUseUnreachableFromPrecomputation: Boolean(
662670
reachUseUnreachableFromPrecomputation,
663671
),
672+
reachVersion: reachVersion || undefined,
664673
},
665674
readOnly: Boolean(readOnly),
666675
repoName,

0 commit comments

Comments
 (0)