From c682f75648e1481bed6137bc9a186c0e4adacf96 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 2 Dec 2025 12:48:09 +0100 Subject: [PATCH 1/4] change discoverGhsaIds to use coana cli command 'find-vulnerabilities' bump coana version --- CHANGELOG.md | 8 ++++++ package.json | 4 +-- pnpm-lock.yaml | 10 ++++---- src/commands/fix/coana-fix.mts | 30 +++++----------------- src/commands/fix/handle-fix-limit.test.mts | 8 +++--- 5 files changed, 25 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c8bfe98f..56f96ffad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [1.1.40](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.40) - 2025-12-02 + +### Fixed +- Fix a bug where vulnerabilities were not found correctly during `socket fix`. + +### Changed +- Updated the Coana CLI to v `14.12.110`. + ## [1.1.39](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.39) - 2025-12-01 ### Added diff --git a/package.json b/package.json index d5917a8d3..4deacffd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket", - "version": "1.1.39", + "version": "1.1.40", "description": "CLI for Socket.dev", "homepage": "https://github.com/SocketDev/socket-cli", "license": "MIT AND OFL-1.1", @@ -94,7 +94,7 @@ "@babel/preset-typescript": "7.27.1", "@babel/runtime": "7.28.4", "@biomejs/biome": "2.2.4", - "@coana-tech/cli": "14.12.107", + "@coana-tech/cli": "14.12.110", "@cyclonedx/cdxgen": "11.11.0", "@dotenvx/dotenvx": "1.49.0", "@eslint/compat": "1.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 02285d706..7e0c130b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -124,8 +124,8 @@ importers: specifier: 2.2.4 version: 2.2.4 '@coana-tech/cli': - specifier: 14.12.107 - version: 14.12.107 + specifier: 14.12.110 + version: 14.12.110 '@cyclonedx/cdxgen': specifier: 11.11.0 version: 11.11.0 @@ -677,8 +677,8 @@ packages: '@bufbuild/protobuf@2.6.3': resolution: {integrity: sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ==} - '@coana-tech/cli@14.12.107': - resolution: {integrity: sha512-MGmd0xY2q5grsPfDgKjFXmaZsAwwLQhtS+sCpDAt3EUfVUGDBQdZ4dJVONUifzvo3YqPCKNwU1fw9WDmic0fGA==} + '@coana-tech/cli@14.12.110': + resolution: {integrity: sha512-I+SAm9VKoZpLsI0yz4qTIKJIGkN5qbTtp/fxhWaOgjC01riCcAdm0cIqsJZJZgp6xYlR401G86efeauIsSlQsA==} hasBin: true '@colors/colors@1.5.0': @@ -5315,7 +5315,7 @@ snapshots: '@bufbuild/protobuf@2.6.3': optional: true - '@coana-tech/cli@14.12.107': {} + '@coana-tech/cli@14.12.110': {} '@colors/colors@1.5.0': optional: true diff --git a/src/commands/fix/coana-fix.mts b/src/commands/fix/coana-fix.mts index a566052ae..3a86002e4 100644 --- a/src/commands/fix/coana-fix.mts +++ b/src/commands/fix/coana-fix.mts @@ -27,7 +27,6 @@ import { GQL_PR_STATE_OPEN, } from '../../constants.mts' import { handleApiCall } from '../../utils/api.mts' -import { cmdFlagValueToArray } from '../../utils/cmd.mts' import { spawnCoanaDlx } from '../../utils/dlx.mts' import { getErrorCause } from '../../utils/errors.mts' import { @@ -66,7 +65,6 @@ type DiscoverGhsaIdsOptions = { async function discoverGhsaIds( orgSlug: string, tarHash: string, - fixConfig: FixConfig, options?: DiscoverGhsaIdsOptions | undefined, ): Promise { const { @@ -79,31 +77,15 @@ async function discoverGhsaIds( } as DiscoverGhsaIdsOptions const foundCResult = await spawnCoanaDlx( - [ - 'compute-fixes-and-upgrade-purls', - cwd, - '--manifests-tar-hash', - tarHash, - ...(fixConfig.rangeStyle ? ['--range-style', fixConfig.rangeStyle] : []), - ...(fixConfig.minimumReleaseAge - ? ['--minimum-release-age', fixConfig.minimumReleaseAge] - : []), - ...(fixConfig.include.length ? ['--include', ...fixConfig.include] : []), - ...(fixConfig.exclude.length ? ['--exclude', ...fixConfig.exclude] : []), - ...(fixConfig.disableMajorUpdates ? ['--disable-major-updates'] : []), - ...(fixConfig.showAffectedDirectDependencies - ? ['--show-affected-direct-dependencies'] - : []), - ...fixConfig.unknownFlags, - ], + ['find-vulnerabilities', cwd, '--manifests-tar-hash', tarHash], orgSlug, { cwd, spinner }, + { stdio: 'pipe' }, ) if (foundCResult.ok) { - const foundIds = cmdFlagValueToArray( - /(?<=Vulnerabilities found:).*/.exec(foundCResult.data), - ) + // Coana prints ghsaIds as json-formatted string on the final line of the output + const foundIds = JSON.parse(foundCResult.data.split('\n').pop() || '[]') return limit !== undefined ? foundIds.slice(0, limit) : foundIds } return [] @@ -206,7 +188,7 @@ export async function coanaFix( let ids: string[] if (isAll && limit > 0) { - ids = await discoverGhsaIds(orgSlug, tarHash, fixConfig, { + ids = await discoverGhsaIds(orgSlug, tarHash, { cwd, limit, spinner, @@ -312,7 +294,7 @@ export async function coanaFix( let ids: string[] | undefined if (shouldSpawnCoana && isAll) { - ids = await discoverGhsaIds(orgSlug, tarHash, fixConfig, { + ids = await discoverGhsaIds(orgSlug, tarHash, { cwd, limit: adjustedLimit, spinner, diff --git a/src/commands/fix/handle-fix-limit.test.mts b/src/commands/fix/handle-fix-limit.test.mts index 25a703cbd..238452541 100644 --- a/src/commands/fix/handle-fix-limit.test.mts +++ b/src/commands/fix/handle-fix-limit.test.mts @@ -223,7 +223,7 @@ describe('socket fix --limit behavior verification', () => { // First call is for discovery (returns vulnerability IDs). mockSpawnCoanaDlx.mockResolvedValueOnce({ ok: true, - data: 'Vulnerabilities found: GHSA-aaaa-aaaa-aaaa,GHSA-bbbb-bbbb-bbbb', + data: JSON.stringify(['GHSA-aaaa-aaaa-aaaa', 'GHSA-bbbb-bbbb-bbbb']), }) // Second call is to apply fixes to the discovered IDs. @@ -245,7 +245,7 @@ describe('socket fix --limit behavior verification', () => { // First call is discovery (no --apply-fixes-to). const discoveryArgs = mockSpawnCoanaDlx.mock.calls[0]?.[0] as string[] - expect(discoveryArgs).toContain('compute-fixes-and-upgrade-purls') + expect(discoveryArgs).toContain('find-vulnerabilities') expect(discoveryArgs).not.toContain('--apply-fixes-to') // Second call applies fixes to discovered IDs. @@ -284,7 +284,7 @@ describe('socket fix --limit behavior verification', () => { // First call returns the IDs to process. mockSpawnCoanaDlx.mockResolvedValueOnce({ ok: true, - data: `Vulnerabilities found: ${ghsas.join(',')}`, + data: JSON.stringify(ghsas.join(',')), }) // Subsequent calls are for individual GHSA fixes. @@ -327,7 +327,7 @@ describe('socket fix --limit behavior verification', () => { mockSpawnCoanaDlx.mockResolvedValueOnce({ ok: true, - data: `Vulnerabilities found: ${ghsas.join(',')}`, + data: JSON.stringify(ghsas.join(',')), }) mockSpawnCoanaDlx.mockResolvedValue({ From b68af651aba8160643543b414c03d1f5e369b3ea Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 2 Dec 2025 12:57:32 +0100 Subject: [PATCH 2/4] trim before split in discoverGhsaIds --- src/commands/fix/coana-fix.mts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/fix/coana-fix.mts b/src/commands/fix/coana-fix.mts index 3a86002e4..28f30602b 100644 --- a/src/commands/fix/coana-fix.mts +++ b/src/commands/fix/coana-fix.mts @@ -85,7 +85,9 @@ async function discoverGhsaIds( if (foundCResult.ok) { // Coana prints ghsaIds as json-formatted string on the final line of the output - const foundIds = JSON.parse(foundCResult.data.split('\n').pop() || '[]') + const foundIds = JSON.parse( + foundCResult.data.trim().split('\n').pop() || '[]', + ) return limit !== undefined ? foundIds.slice(0, limit) : foundIds } return [] From e74ab7add5ab378ade52ee4bc4dd8adfd4a6233a Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 2 Dec 2025 13:09:08 +0100 Subject: [PATCH 3/4] fix unit test mock data --- src/commands/fix/handle-fix-limit.test.mts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/fix/handle-fix-limit.test.mts b/src/commands/fix/handle-fix-limit.test.mts index 238452541..0d8183071 100644 --- a/src/commands/fix/handle-fix-limit.test.mts +++ b/src/commands/fix/handle-fix-limit.test.mts @@ -284,7 +284,7 @@ describe('socket fix --limit behavior verification', () => { // First call returns the IDs to process. mockSpawnCoanaDlx.mockResolvedValueOnce({ ok: true, - data: JSON.stringify(ghsas.join(',')), + data: JSON.stringify(ghsas), }) // Subsequent calls are for individual GHSA fixes. @@ -327,7 +327,7 @@ describe('socket fix --limit behavior verification', () => { mockSpawnCoanaDlx.mockResolvedValueOnce({ ok: true, - data: JSON.stringify(ghsas.join(',')), + data: JSON.stringify(ghsas), }) mockSpawnCoanaDlx.mockResolvedValue({ From 7dcf13e28a0ad9cebbb38eb3a0900f76e1b3e7c1 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Tue, 2 Dec 2025 13:24:24 +0100 Subject: [PATCH 4/4] catch errors when parsing output of coana cmd 'find-vulnerabilities' --- src/commands/fix/coana-fix.mts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/commands/fix/coana-fix.mts b/src/commands/fix/coana-fix.mts index 28f30602b..db7956401 100644 --- a/src/commands/fix/coana-fix.mts +++ b/src/commands/fix/coana-fix.mts @@ -85,9 +85,13 @@ async function discoverGhsaIds( if (foundCResult.ok) { // Coana prints ghsaIds as json-formatted string on the final line of the output - const foundIds = JSON.parse( - foundCResult.data.trim().split('\n').pop() || '[]', - ) + const foundIds: string[] = [] + try { + const ghsaIdsRaw = foundCResult.data.trim().split('\n').pop() + if (ghsaIdsRaw) { + foundIds.push(...JSON.parse(ghsaIdsRaw)) + } + } catch {} return limit !== undefined ? foundIds.slice(0, limit) : foundIds } return []