diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index bcfb60319..8ffad2fe2 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -26,6 +26,9 @@ jobs: with: node-version: ${{ matrix.node-version }} + - name: Install uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Build run: pnpm run build diff --git a/CHANGELOG.md b/CHANGELOG.md index f7daf353a..d12bc9de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ 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.70](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.70) - 2026-03-11 + +### Changed +- Updated the Coana CLI to v `14.12.194`. + ## [1.1.69](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.69) - 2026-03-10 ### Changed diff --git a/package.json b/package.json index f1989efd9..9284f4e85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket", - "version": "1.1.69", + "version": "1.1.70", "description": "CLI for Socket.dev", "homepage": "https://github.com/SocketDev/socket-cli", "license": "MIT AND OFL-1.1", @@ -97,7 +97,7 @@ "@babel/preset-typescript": "7.27.1", "@babel/runtime": "7.28.4", "@biomejs/biome": "2.2.4", - "@coana-tech/cli": "14.12.192", + "@coana-tech/cli": "14.12.194", "@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 217fbae4d..8d44814e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,8 +128,8 @@ importers: specifier: 2.2.4 version: 2.2.4 '@coana-tech/cli': - specifier: 14.12.192 - version: 14.12.192 + specifier: 14.12.194 + version: 14.12.194 '@cyclonedx/cdxgen': specifier: 11.11.0 version: 11.11.0 @@ -681,8 +681,8 @@ packages: '@bufbuild/protobuf@2.6.3': resolution: {integrity: sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ==} - '@coana-tech/cli@14.12.192': - resolution: {integrity: sha512-l7YrnVhnzkB4iGmg20y7TrXADoveF3GTcLErLXr91z/d8JvZAC2vrLHEzHoOkFbpJZe9rYYeXH6ATpET3jTarA==} + '@coana-tech/cli@14.12.194': + resolution: {integrity: sha512-hQqt0f0eGNNL8hsaBqMKbcvVQ5xK+cgk9Wuyk921h+3jHjKGqxSbvHjlx1bAU5oi9chYsz5aCmztc+dgSIO8hg==} hasBin: true '@colors/colors@1.5.0': @@ -5375,7 +5375,7 @@ snapshots: '@bufbuild/protobuf@2.6.3': optional: true - '@coana-tech/cli@14.12.192': {} + '@coana-tech/cli@14.12.194': {} '@colors/colors@1.5.0': optional: true diff --git a/src/commands/ci/handle-ci.mts b/src/commands/ci/handle-ci.mts index 812785c7a..d7e38341a 100644 --- a/src/commands/ci/handle-ci.mts +++ b/src/commands/ci/handle-ci.mts @@ -57,6 +57,7 @@ export async function handleCi(autoManifest: boolean): Promise { reachDebug: false, reachDetailedAnalysisLogFile: false, reachDisableAnalytics: false, + reachDisableExternalToolChecks: false, reachEcosystems: [], reachEnableAnalysisSplitting: false, reachExcludePaths: [], diff --git a/src/commands/fix/cmd-fix.mts b/src/commands/fix/cmd-fix.mts index 5003be255..5d26e40fd 100644 --- a/src/commands/fix/cmd-fix.mts +++ b/src/commands/fix/cmd-fix.mts @@ -154,6 +154,11 @@ Available styles: 'Enable debug logging in the Coana-based Socket Fix CLI invocation.', shortFlag: 'd', }, + disableExternalToolChecks: { + type: 'boolean', + default: false, + description: 'Disable external tool checks during fix analysis.', + }, ecosystems: { type: 'string', default: [], @@ -294,6 +299,7 @@ async function run( applyFixes, autopilot, debug, + disableExternalToolChecks, ecosystems, exclude, fixVersion, @@ -317,6 +323,7 @@ async function run( applyFixes: boolean autopilot: boolean debug: boolean + disableExternalToolChecks: boolean ecosystems: string[] exclude: string[] fixVersion: string | undefined @@ -426,6 +433,7 @@ async function run( coanaVersion: fixVersion, cwd, debug, + disableExternalToolChecks, disableMajorUpdates, ecosystems: validatedEcosystems, exclude: excludePatterns, diff --git a/src/commands/fix/coana-fix.mts b/src/commands/fix/coana-fix.mts index 70f09bec2..c6dcf693f 100644 --- a/src/commands/fix/coana-fix.mts +++ b/src/commands/fix/coana-fix.mts @@ -119,6 +119,7 @@ export async function coanaFix( coanaVersion, cwd, debug, + disableExternalToolChecks, disableMajorUpdates, ecosystems, exclude, @@ -266,6 +267,9 @@ export async function coanaFix( '--output-file', tmpFile, ...(debug ? ['--debug'] : []), + ...(disableExternalToolChecks + ? ['--disable-external-tool-checks'] + : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] @@ -418,6 +422,9 @@ export async function coanaFix( ...(exclude.length ? ['--exclude', ...exclude] : []), ...(ecosystems.length ? ['--purl-types', ...ecosystems] : []), ...(debug ? ['--debug'] : []), + ...(disableExternalToolChecks + ? ['--disable-external-tool-checks'] + : []), ...(disableMajorUpdates ? ['--disable-major-updates'] : []), ...(showAffectedDirectDependencies ? ['--show-affected-direct-dependencies'] diff --git a/src/commands/fix/handle-fix.mts b/src/commands/fix/handle-fix.mts index 8d3244782..c008c4dab 100644 --- a/src/commands/fix/handle-fix.mts +++ b/src/commands/fix/handle-fix.mts @@ -120,6 +120,7 @@ export async function handleFix({ coanaVersion, cwd, debug, + disableExternalToolChecks, disableMajorUpdates, ecosystems, exclude, @@ -146,6 +147,7 @@ export async function handleFix({ coanaVersion, cwd, debug, + disableExternalToolChecks, disableMajorUpdates, ecosystems, exclude, @@ -171,6 +173,7 @@ export async function handleFix({ coanaVersion, cwd, debug, + disableExternalToolChecks, disableMajorUpdates, ecosystems, exclude, diff --git a/src/commands/fix/types.mts b/src/commands/fix/types.mts index 6420ea88e..2109e5f89 100644 --- a/src/commands/fix/types.mts +++ b/src/commands/fix/types.mts @@ -9,6 +9,7 @@ export type FixConfig = { coanaVersion: string | undefined cwd: string debug: boolean + disableExternalToolChecks: boolean disableMajorUpdates: boolean ecosystems: PURL_Type[] exclude: string[] diff --git a/src/commands/scan/cmd-scan-create.mts b/src/commands/scan/cmd-scan-create.mts index 2251438bc..a74260f53 100644 --- a/src/commands/scan/cmd-scan-create.mts +++ b/src/commands/scan/cmd-scan-create.mts @@ -244,6 +244,7 @@ async function run( reachDetailedAnalysisLogFile, reachDisableAnalysisSplitting: _reachDisableAnalysisSplitting, reachDisableAnalytics, + reachDisableExternalToolChecks, reachEnableAnalysisSplitting, reachLazyMode, reachSkipCache, @@ -277,6 +278,7 @@ async function run( reachDetailedAnalysisLogFile: boolean reachDisableAnalysisSplitting: boolean reachDisableAnalytics: boolean + reachDisableExternalToolChecks: boolean reachEnableAnalysisSplitting: boolean reachLazyMode: boolean reachSkipCache: boolean @@ -580,6 +582,7 @@ async function run( reachDebug: Boolean(reachDebug), reachDetailedAnalysisLogFile: Boolean(reachDetailedAnalysisLogFile), reachDisableAnalytics: Boolean(reachDisableAnalytics), + reachDisableExternalToolChecks: Boolean(reachDisableExternalToolChecks), reachEcosystems, reachEnableAnalysisSplitting: Boolean(reachEnableAnalysisSplitting), reachExcludePaths, diff --git a/src/commands/scan/cmd-scan-reach.e2e.test.mts b/src/commands/scan/cmd-scan-reach.e2e.test.mts index e966e6b6a..220f409e2 100644 --- a/src/commands/scan/cmd-scan-reach.e2e.test.mts +++ b/src/commands/scan/cmd-scan-reach.e2e.test.mts @@ -394,7 +394,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: longTestTimeout }, + { retry: 2, timeout: longTestTimeout }, ) cmdit( @@ -491,7 +491,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) }) @@ -603,7 +603,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) cmdit( @@ -681,7 +681,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) cmdit( @@ -779,7 +779,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) cmdit( @@ -836,7 +836,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) cmdit( @@ -923,7 +923,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) }) @@ -1027,7 +1027,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) cmdit( @@ -1127,7 +1127,7 @@ describe('socket scan reach (E2E tests)', async () => { await tempFixture.cleanup() } }, - { timeout: testTimeout }, + { retry: 2, timeout: testTimeout }, ) }) }) diff --git a/src/commands/scan/cmd-scan-reach.mts b/src/commands/scan/cmd-scan-reach.mts index 60350ca54..924e7b169 100644 --- a/src/commands/scan/cmd-scan-reach.mts +++ b/src/commands/scan/cmd-scan-reach.mts @@ -128,6 +128,7 @@ async function run( reachDetailedAnalysisLogFile, reachDisableAnalysisSplitting: _reachDisableAnalysisSplitting, reachDisableAnalytics, + reachDisableExternalToolChecks, reachEnableAnalysisSplitting, reachLazyMode, reachSkipCache, @@ -147,6 +148,7 @@ async function run( reachDetailedAnalysisLogFile: boolean reachDisableAnalysisSplitting: boolean reachDisableAnalytics: boolean + reachDisableExternalToolChecks: boolean reachEnableAnalysisSplitting: boolean reachLazyMode: boolean reachSkipCache: boolean @@ -268,6 +270,7 @@ async function run( reachDebug: Boolean(reachDebug), reachDetailedAnalysisLogFile: Boolean(reachDetailedAnalysisLogFile), reachDisableAnalytics: Boolean(reachDisableAnalytics), + reachDisableExternalToolChecks: Boolean(reachDisableExternalToolChecks), reachEcosystems, reachEnableAnalysisSplitting: Boolean(reachEnableAnalysisSplitting), reachExcludePaths, diff --git a/src/commands/scan/create-scan-from-github.mts b/src/commands/scan/create-scan-from-github.mts index 0012dd432..2a5b55c55 100644 --- a/src/commands/scan/create-scan-from-github.mts +++ b/src/commands/scan/create-scan-from-github.mts @@ -255,6 +255,7 @@ async function scanOneRepo( reachDebug: false, reachDetailedAnalysisLogFile: false, reachDisableAnalytics: false, + reachDisableExternalToolChecks: false, reachEcosystems: [], reachEnableAnalysisSplitting: false, reachExcludePaths: [], diff --git a/src/commands/scan/perform-reachability-analysis.mts b/src/commands/scan/perform-reachability-analysis.mts index ba5bdcbbd..19644321a 100644 --- a/src/commands/scan/perform-reachability-analysis.mts +++ b/src/commands/scan/perform-reachability-analysis.mts @@ -1,5 +1,7 @@ import path from 'node:path' +import { logger } from '@socketsecurity/registry/lib/logger' + import constants from '../../constants.mts' import { handleApiCall } from '../../utils/api.mts' import { extractTier1ReachabilityScanId } from '../../utils/coana.mts' @@ -19,6 +21,7 @@ export type ReachabilityOptions = { reachConcurrency: number reachDebug: boolean reachDetailedAnalysisLogFile: boolean + reachDisableExternalToolChecks: boolean reachDisableAnalytics: boolean reachEcosystems: PURL_Type[] reachEnableAnalysisSplitting: boolean @@ -179,6 +182,9 @@ export async function performReachabilityAnalysis( ...(reachabilityOptions.reachDisableAnalytics ? ['--disable-analytics-sharing'] : []), + ...(reachabilityOptions.reachDisableExternalToolChecks + ? ['--disable-external-tool-checks'] + : []), ...(reachabilityOptions.reachEnableAnalysisSplitting ? [] : ['--disable-analysis-splitting']), @@ -223,15 +229,25 @@ export async function performReachabilityAnalysis( spinner.start() } - return coanaResult.ok - ? { - ok: true, - data: { - // Use the actual output filename for the scan. - reachabilityReport: outputFilePath, - tier1ReachabilityScanId: - extractTier1ReachabilityScanId(outputFilePath), - }, - } - : coanaResult + if (!coanaResult.ok) { + const coanaVersion = + reachabilityOptions.reachVersion || + constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION + logger.error( + `Coana reachability analysis failed. Version: ${coanaVersion}, target: ${analysisTarget}, cwd: ${cwd}`, + ) + if (coanaResult.message) { + logger.error(`Details: ${coanaResult.message}`) + } + return coanaResult + } + + return { + ok: true, + data: { + // Use the actual output filename for the scan. + reachabilityReport: outputFilePath, + tier1ReachabilityScanId: extractTier1ReachabilityScanId(outputFilePath), + }, + } } diff --git a/src/commands/scan/reachability-flags.mts b/src/commands/scan/reachability-flags.mts index ecd2145f4..979ac30db 100644 --- a/src/commands/scan/reachability-flags.mts +++ b/src/commands/scan/reachability-flags.mts @@ -25,6 +25,12 @@ export const reachabilityFlags: MeowFlags = { description: 'Set the maximum number of concurrent reachability analysis runs. It is recommended to choose a concurrency level that ensures each analysis run has at least the --reach-analysis-memory-limit amount of memory available. NPM reachability analysis does not support concurrent execution, so the concurrency level is ignored for NPM.', }, + reachDisableExternalToolChecks: { + type: 'boolean', + default: false, + description: + 'Disable external tool checks during reachability analysis.', + }, reachDebug: { type: 'boolean', default: false, diff --git a/src/utils/dlx.mts b/src/utils/dlx.mts index 10f996799..92972db10 100644 --- a/src/utils/dlx.mts +++ b/src/utils/dlx.mts @@ -278,8 +278,21 @@ export async function spawnCoanaDlx( return { ok: true, data: output.stdout } } catch (e) { const stderr = (e as any)?.stderr + const exitCode = (e as any)?.code + const signal = (e as any)?.signal const cause = getErrorCause(e) - const message = stderr || cause + // Build a descriptive error message with exit code and signal details. + const details: string[] = [] + if (typeof exitCode === 'number') { + details.push(`exit code ${exitCode}`) + } + if (signal) { + details.push(`signal ${signal}`) + } + const detailSuffix = details.length ? ` (${details.join(', ')})` : '' + const message = stderr + ? `Coana command failed${detailSuffix}: ${stderr}` + : `Coana command failed${detailSuffix}: ${cause}` return { ok: false, data: e,