Skip to content

Commit f732aa8

Browse files
authored
upgrading coana to version 14.12.203 (#1175)
* upgrading coana to version 14.12.203 * fix: warn about per-vulnerability reachability errors in scan output * fix: improve e2e test diagnostics for reachability errors * upgrading coana to version 14.12.205
1 parent d322973 commit f732aa8

File tree

6 files changed

+120
-31
lines changed

6 files changed

+120
-31
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [1.1.79](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.79) - 2026-04-08
8+
9+
### Changed
10+
- Updated the Coana CLI to v `14.12.205`.
11+
712
## [1.1.78](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.78) - 2026-04-01
813

914
### Fixed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "socket",
3-
"version": "1.1.78",
3+
"version": "1.1.79",
44
"description": "CLI for Socket.dev",
55
"homepage": "https://github.com/SocketDev/socket-cli",
66
"license": "MIT AND OFL-1.1",
@@ -97,7 +97,7 @@
9797
"@babel/preset-typescript": "7.27.1",
9898
"@babel/runtime": "7.28.4",
9999
"@biomejs/biome": "2.2.4",
100-
"@coana-tech/cli": "14.12.201",
100+
"@coana-tech/cli": "14.12.205",
101101
"@cyclonedx/cdxgen": "12.1.2",
102102
"@dotenvx/dotenvx": "1.49.0",
103103
"@eslint/compat": "1.3.2",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/scan/cmd-scan-reach.e2e.test.mts

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,33 @@ function findReachabilityForGhsa(
226226
* Logs stdout and stderr to help diagnose test failures.
227227
*/
228228
function logCommandOutput(code: number, stdout: string, stderr: string): void {
229-
logger.error(`Command failed with code ${code}`)
229+
logger.error(`Command exited with code ${code}`)
230230
logger.error('stdout:', stdout)
231231
logger.error('stderr:', stderr)
232232
}
233233

234+
/**
235+
* Log reachability entries that have type "error" for debugging.
236+
* Helps diagnose Coana analysis failures in CI.
237+
*/
238+
function logReachabilityErrors(facts: SocketFactsJson): void {
239+
for (const component of facts.components) {
240+
if (!component.reachability) {
241+
continue
242+
}
243+
for (const ghsaEntry of component.reachability) {
244+
for (const entry of ghsaEntry.reachability) {
245+
if (entry.type === 'error') {
246+
logger.error(
247+
`Reachability error for ${ghsaEntry.ghsa_id} in ${component.name}@${component.version} ` +
248+
`(subproject: ${entry.subprojectPath}): ${JSON.stringify(entry)}`,
249+
)
250+
}
251+
}
252+
}
253+
}
254+
}
255+
234256
describe('socket scan reach (E2E tests)', async () => {
235257
const { binCliPath } = constants
236258
// Standard timeout for most tests.
@@ -386,8 +408,13 @@ describe('socket scan reach (E2E tests)', async () => {
386408

387409
logger.info('\nReachability analysis completed successfully')
388410
} catch (e) {
389-
if (code !== 0) {
390-
logCommandOutput(code, stdout, stderr)
411+
logCommandOutput(code, stdout, stderr)
412+
// Log reachability errors from the facts file if it was parsed.
413+
try {
414+
const errorFacts = await readSocketFactsJson(tempFixture.path)
415+
logReachabilityErrors(errorFacts)
416+
} catch {
417+
// Facts file may not exist if the failure was earlier.
391418
}
392419
throw e
393420
} finally {
@@ -483,9 +510,7 @@ describe('socket scan reach (E2E tests)', async () => {
483510
'\nReachability analysis with excluded paths completed successfully',
484511
)
485512
} catch (e) {
486-
if (code !== 0) {
487-
logCommandOutput(code, stdout, stderr)
488-
}
513+
logCommandOutput(code, stdout, stderr)
489514
throw e
490515
} finally {
491516
await tempFixture.cleanup()
@@ -595,9 +620,7 @@ describe('socket scan reach (E2E tests)', async () => {
595620
'\nReachability analysis with target restriction completed successfully',
596621
)
597622
} catch (e) {
598-
if (code !== 0) {
599-
logCommandOutput(code, stdout, stderr)
600-
}
623+
logCommandOutput(code, stdout, stderr)
601624
throw e
602625
} finally {
603626
await tempFixture.cleanup()
@@ -673,9 +696,7 @@ describe('socket scan reach (E2E tests)', async () => {
673696
'\nReachability analysis with --cwd flag completed successfully',
674697
)
675698
} catch (e) {
676-
if (code !== 0) {
677-
logCommandOutput(code, stdout, stderr)
678-
}
699+
logCommandOutput(code, stdout, stderr)
679700
throw e
680701
} finally {
681702
await tempFixture.cleanup()
@@ -771,9 +792,7 @@ describe('socket scan reach (E2E tests)', async () => {
771792
'\nReachability analysis with --cwd and target completed successfully',
772793
)
773794
} catch (e) {
774-
if (code !== 0) {
775-
logCommandOutput(code, stdout, stderr)
776-
}
795+
logCommandOutput(code, stdout, stderr)
777796
throw e
778797
} finally {
779798
await tempFixture.cleanup()
@@ -915,9 +934,7 @@ describe('socket scan reach (E2E tests)', async () => {
915934
'\nReachability analysis output location verified successfully',
916935
)
917936
} catch (e) {
918-
if (code !== 0) {
919-
logCommandOutput(code, stdout, stderr)
920-
}
937+
logCommandOutput(code, stdout, stderr)
921938
throw e
922939
} finally {
923940
await tempFixture.cleanup()
@@ -1019,9 +1036,7 @@ describe('socket scan reach (E2E tests)', async () => {
10191036
'\nReachability analysis with pypi ecosystem filter completed successfully',
10201037
)
10211038
} catch (e) {
1022-
if (code !== 0) {
1023-
logCommandOutput(code, stdout, stderr)
1024-
}
1039+
logCommandOutput(code, stdout, stderr)
10251040
throw e
10261041
} finally {
10271042
await tempFixture.cleanup()
@@ -1119,9 +1134,7 @@ describe('socket scan reach (E2E tests)', async () => {
11191134
'\nReachability analysis with npm ecosystem filter completed successfully',
11201135
)
11211136
} catch (e) {
1122-
if (code !== 0) {
1123-
logCommandOutput(code, stdout, stderr)
1124-
}
1137+
logCommandOutput(code, stdout, stderr)
11251138
throw e
11261139
} finally {
11271140
await tempFixture.cleanup()

src/commands/scan/output-scan-reach.mts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { logger } from '@socketsecurity/registry/lib/logger'
2+
import { pluralize } from '@socketsecurity/registry/lib/words'
23

34
import constants from '../../constants.mts'
5+
import { extractReachabilityErrors } from '../../utils/coana.mts'
46
import { failMsgWithBadge } from '../../utils/fail-msg-with-badge.mts'
57
import { serializeResultJson } from '../../utils/serialize-result-json.mts'
68

@@ -29,4 +31,20 @@ export async function outputScanReach(
2931
logger.log('')
3032
logger.success('Reachability analysis completed successfully!')
3133
logger.info(`Reachability report has been written to: ${actualOutputPath}`)
34+
35+
// Warn about individual vulnerabilities where reachability analysis errored.
36+
const errors = extractReachabilityErrors(
37+
result.data.reachabilityReport,
38+
)
39+
if (errors.length) {
40+
logger.log('')
41+
logger.warn(
42+
`Reachability analysis returned ${errors.length} ${pluralize('error', errors.length)} for individual ${pluralize('vulnerability', errors.length)}:`,
43+
)
44+
for (const err of errors) {
45+
logger.warn(
46+
` - ${err.ghsaId} in ${err.componentName}@${err.componentVersion} (${err.subprojectPath})`,
47+
)
48+
}
49+
}
3250
}

src/utils/coana.mts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,59 @@
1313

1414
import { readJsonSync } from '@socketsecurity/registry/lib/fs'
1515

16+
export type ReachabilityError = {
17+
componentName: string
18+
componentVersion: string
19+
ghsaId: string
20+
subprojectPath: string
21+
}
22+
23+
export function extractReachabilityErrors(
24+
socketFactsFile: string,
25+
): ReachabilityError[] {
26+
const json = readJsonSync(socketFactsFile, { throws: false }) as
27+
| {
28+
components?: Array<{
29+
name?: string
30+
reachability?: Array<{
31+
ghsa_id?: string
32+
reachability?: Array<{
33+
subprojectPath?: string
34+
type?: string
35+
}>
36+
}>
37+
version?: string
38+
}>
39+
}
40+
| null
41+
| undefined
42+
if (!json || !Array.isArray(json.components)) {
43+
return []
44+
}
45+
const errors: ReachabilityError[] = []
46+
for (const component of json.components) {
47+
if (!Array.isArray(component.reachability)) {
48+
continue
49+
}
50+
for (const ghsaEntry of component.reachability) {
51+
if (!Array.isArray(ghsaEntry.reachability)) {
52+
continue
53+
}
54+
for (const entry of ghsaEntry.reachability) {
55+
if (entry.type === 'error') {
56+
errors.push({
57+
componentName: String(component.name ?? ''),
58+
componentVersion: String(component.version ?? ''),
59+
ghsaId: String(ghsaEntry.ghsa_id ?? ''),
60+
subprojectPath: String(entry.subprojectPath ?? ''),
61+
})
62+
}
63+
}
64+
}
65+
}
66+
return errors
67+
}
68+
1669
export function extractTier1ReachabilityScanId(
1770
socketFactsFile: string,
1871
): string | undefined {

0 commit comments

Comments
 (0)