diff --git a/CHANGELOG.md b/CHANGELOG.md index 58866309c..b1e7273fc 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.124](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.124) - 2026-06-19 + +### Added +- `socket scan create --reach` accepts a new `--reach-retain-facts-file` flag. By default the CLI deletes the `.socket.facts.json` reachability report from the scan directory after a successful scan; pass this flag to keep it (e.g. for inspection or debugging). **Important:** you must delete the retained `.socket.facts.json` before running a fresh tier 1 reachability scan — a stale file left in place is picked up as a pre-generated input and silently overrides fresh analysis, so the new scan results will not be reliable. + +### Changed +- Updated the Coana CLI to v `15.5.4`. + ## [1.1.123](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.123) - 2026-06-18 ### Added diff --git a/package.json b/package.json index bb4cd8449..5a45e7e85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket", - "version": "1.1.123", + "version": "1.1.124", "description": "CLI for Socket.dev", "homepage": "https://github.com/SocketDev/socket-cli", "license": "MIT", @@ -96,7 +96,7 @@ "@babel/preset-typescript": "7.27.1", "@babel/runtime": "7.28.4", "@biomejs/biome": "2.2.4", - "@coana-tech/cli": "15.5.0", + "@coana-tech/cli": "15.5.4", "@cyclonedx/cdxgen": "12.1.2", "@dotenvx/dotenvx": "1.49.0", "@eslint/compat": "1.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08379840d..b49d340f8 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: 15.5.0 - version: 15.5.0 + specifier: 15.5.4 + version: 15.5.4 '@cyclonedx/cdxgen': specifier: 12.1.2 version: 12.1.2 @@ -749,8 +749,8 @@ packages: resolution: {integrity: sha512-hAs5PPKPCQ3/Nha+1fo4A4/gL85fIfxZwHPehsjCJ+BhQH2/yw6/xReuaPA/RfNQr6iz1PcD7BZcE3ctyyl3EA==} cpu: [x64] - '@coana-tech/cli@15.5.0': - resolution: {integrity: sha512-CpFOZ2I5Fb/GM5YPqBwlIN5YjwNBlHPAVpDfO9E6rEk12fTdJ1tVH6brOPmzrpuuRvxQx97VXFpYwjrKCSuHNA==} + '@coana-tech/cli@15.5.4': + resolution: {integrity: sha512-jkfGcTQxlj7B0GfRdxZ4RvreXVAFY5lWBTBNJeAIEhD32zQugrZ0tHs+tG2o3AaPd6QFBipE8AYzY4AJmUUkeA==} hasBin: true '@colors/colors@1.5.0': @@ -5385,7 +5385,7 @@ snapshots: '@cdxgen/cdxgen-plugins-bin@2.0.2': optional: true - '@coana-tech/cli@15.5.0': {} + '@coana-tech/cli@15.5.4': {} '@colors/colors@1.5.0': optional: true diff --git a/src/commands/ci/handle-ci.mts b/src/commands/ci/handle-ci.mts index 52251ed50..d513b86dd 100644 --- a/src/commands/ci/handle-ci.mts +++ b/src/commands/ci/handle-ci.mts @@ -67,6 +67,7 @@ export async function handleCi(autoManifest: boolean): Promise { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/cmd-scan-create.mts b/src/commands/scan/cmd-scan-create.mts index 36d04280c..2ec87b857 100644 --- a/src/commands/scan/cmd-scan-create.mts +++ b/src/commands/scan/cmd-scan-create.mts @@ -264,6 +264,7 @@ async function run( reachDisableExternalToolChecks, reachEnableAnalysisSplitting, reachLazyMode, + reachRetainFactsFile, reachSkipCache, reachUseOnlyPregeneratedSboms, reachVersion, @@ -302,6 +303,7 @@ async function run( reachDisableExternalToolChecks: boolean reachEnableAnalysisSplitting: boolean reachLazyMode: boolean + reachRetainFactsFile: boolean reachSkipCache: boolean reachUseOnlyPregeneratedSboms: boolean reachVersion: string | undefined @@ -659,6 +661,7 @@ async function run( reachEnableAnalysisSplitting: Boolean(reachEnableAnalysisSplitting), reachExcludePaths, reachLazyMode: Boolean(reachLazyMode), + reachRetainFactsFile: Boolean(reachRetainFactsFile), reachSkipCache: Boolean(reachSkipCache), reachUseOnlyPregeneratedSboms: Boolean(reachUseOnlyPregeneratedSboms), reachVersion, diff --git a/src/commands/scan/cmd-scan-create.test.mts b/src/commands/scan/cmd-scan-create.test.mts index 43453c39c..da51e683a 100644 --- a/src/commands/scan/cmd-scan-create.test.mts +++ b/src/commands/scan/cmd-scan-create.test.mts @@ -69,6 +69,7 @@ describe('socket scan create', async () => { --reach-disable-external-tool-checks Disable external tool checks during reachability analysis. --reach-ecosystems List of ecosystems to conduct reachability analysis on, as either a comma separated value or as multiple flags. Defaults to all ecosystems. --reach-enable-analysis-splitting Allow the reachability analysis to partition CVEs into buckets that are processed in separate analysis runs. May improve accuracy, but not recommended by default. + --reach-retain-facts-file Keep the \`.socket.facts.json\` reachability report that the analysis writes to the scan directory instead of deleting it after a successful scan. IMPORTANT: you must delete this file before running a fresh tier 1 reachability scan. A stale \`.socket.facts.json\` left in place is picked up as a pre-generated input and silently overrides fresh analysis, so the new scan results will not be reliable. --reach-skip-cache Skip caching-based optimizations. By default, the reachability analysis will use cached configurations from previous runs to speed up the analysis. --reach-use-only-pregenerated-sboms When using this option, the scan is created based only on pre-generated CDX and SPDX files in your project. --reach-version Override the version of @coana-tech/cli used for reachability analysis. Default: . diff --git a/src/commands/scan/cmd-scan-reach.mts b/src/commands/scan/cmd-scan-reach.mts index ac6f9f265..229759ae1 100644 --- a/src/commands/scan/cmd-scan-reach.mts +++ b/src/commands/scan/cmd-scan-reach.mts @@ -137,6 +137,7 @@ async function run( reachDisableExternalToolChecks, reachEnableAnalysisSplitting, reachLazyMode, + reachRetainFactsFile, reachSkipCache, reachUseOnlyPregeneratedSboms, reachVersion, @@ -161,6 +162,7 @@ async function run( reachDisableExternalToolChecks: boolean reachEnableAnalysisSplitting: boolean reachLazyMode: boolean + reachRetainFactsFile: boolean reachSkipCache: boolean reachUseOnlyPregeneratedSboms: boolean reachVersion: string | undefined @@ -292,6 +294,7 @@ async function run( reachEnableAnalysisSplitting: Boolean(reachEnableAnalysisSplitting), reachExcludePaths, reachLazyMode: Boolean(reachLazyMode), + reachRetainFactsFile: Boolean(reachRetainFactsFile), reachSkipCache: Boolean(reachSkipCache), reachUseOnlyPregeneratedSboms: Boolean(reachUseOnlyPregeneratedSboms), reachVersion, diff --git a/src/commands/scan/cmd-scan-reach.test.mts b/src/commands/scan/cmd-scan-reach.test.mts index 206337051..82c820767 100644 --- a/src/commands/scan/cmd-scan-reach.test.mts +++ b/src/commands/scan/cmd-scan-reach.test.mts @@ -51,6 +51,7 @@ describe('socket scan reach', async () => { --reach-disable-external-tool-checks Disable external tool checks during reachability analysis. --reach-ecosystems List of ecosystems to conduct reachability analysis on, as either a comma separated value or as multiple flags. Defaults to all ecosystems. --reach-enable-analysis-splitting Allow the reachability analysis to partition CVEs into buckets that are processed in separate analysis runs. May improve accuracy, but not recommended by default. + --reach-retain-facts-file Keep the \`.socket.facts.json\` reachability report that the analysis writes to the scan directory instead of deleting it after a successful scan. IMPORTANT: you must delete this file before running a fresh tier 1 reachability scan. A stale \`.socket.facts.json\` left in place is picked up as a pre-generated input and silently overrides fresh analysis, so the new scan results will not be reliable. --reach-skip-cache Skip caching-based optimizations. By default, the reachability analysis will use cached configurations from previous runs to speed up the analysis. --reach-use-only-pregenerated-sboms When using this option, the scan is created based only on pre-generated CDX and SPDX files in your project. --reach-version Override the version of @coana-tech/cli used for reachability analysis. Default: . diff --git a/src/commands/scan/create-scan-from-github.mts b/src/commands/scan/create-scan-from-github.mts index 4f53e86fc..83bb3ec42 100644 --- a/src/commands/scan/create-scan-from-github.mts +++ b/src/commands/scan/create-scan-from-github.mts @@ -266,6 +266,7 @@ async function scanOneRepo( reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/exclude-paths.test.mts b/src/commands/scan/exclude-paths.test.mts index 488c8944c..1478e82ee 100644 --- a/src/commands/scan/exclude-paths.test.mts +++ b/src/commands/scan/exclude-paths.test.mts @@ -30,6 +30,7 @@ function makeReachOptions( reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/handle-create-new-scan.mts b/src/commands/scan/handle-create-new-scan.mts index 10bec0231..f529ad3ef 100644 --- a/src/commands/scan/handle-create-new-scan.mts +++ b/src/commands/scan/handle-create-new-scan.mts @@ -336,8 +336,16 @@ export async function handleCreateNewScan({ // (e.g. from `socket manifest gradle --facts`) are NOT touched here — // those are user-owned input that the user can clean up themselves; in // the --reach path coana overwrites that file with its enriched output - // anyway, so it's the same path that gets removed. - if (fullScanCResult.ok && scanId && reachabilityReport) { + // anyway, so it's the same path that gets removed. `--reach-retain-facts-file` + // opts out of this cleanup so the report can be inspected; the user is then + // responsible for deleting it before the next tier 1 scan (a stale file is + // picked up as pre-generated input and would make those results unreliable). + if ( + fullScanCResult.ok && + scanId && + reachabilityReport && + !reach.reachRetainFactsFile + ) { try { await unlink(path.resolve(cwd, reachabilityReport)) debugFn( diff --git a/src/commands/scan/handle-create-new-scan.test.mts b/src/commands/scan/handle-create-new-scan.test.mts index 3c03048ee..2b271d651 100644 --- a/src/commands/scan/handle-create-new-scan.test.mts +++ b/src/commands/scan/handle-create-new-scan.test.mts @@ -102,6 +102,7 @@ function createConfig( reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -213,6 +214,7 @@ describe('handleCreateNewScan excludePaths', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['dist'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -275,6 +277,7 @@ describe('handleCreateNewScan excludePaths', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -343,6 +346,7 @@ describe('handleCreateNewScan excludePaths', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -401,6 +405,7 @@ describe('handleCreateNewScan excludePaths', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -459,6 +464,7 @@ describe('handleCreateNewScan excludePaths', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/handle-scan-reach.test.mts b/src/commands/scan/handle-scan-reach.test.mts index f845247aa..8f18de4ce 100644 --- a/src/commands/scan/handle-scan-reach.test.mts +++ b/src/commands/scan/handle-scan-reach.test.mts @@ -120,6 +120,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -171,6 +172,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -232,6 +234,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -279,6 +282,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -330,6 +334,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -366,6 +371,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, @@ -415,6 +421,7 @@ describe('handleScanReach', () => { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/perform-reachability-analysis.mts b/src/commands/scan/perform-reachability-analysis.mts index c95fdd93a..b56e30076 100644 --- a/src/commands/scan/perform-reachability-analysis.mts +++ b/src/commands/scan/perform-reachability-analysis.mts @@ -40,6 +40,7 @@ export type ReachabilityOptions = { reachEnableAnalysisSplitting: boolean reachExcludePaths: string[] reachLazyMode: boolean + reachRetainFactsFile: boolean reachSkipCache: boolean reachUseOnlyPregeneratedSboms: boolean reachVersion: string | undefined diff --git a/src/commands/scan/perform-reachability-analysis.test.mts b/src/commands/scan/perform-reachability-analysis.test.mts index 16d4af9dc..7ea16170e 100644 --- a/src/commands/scan/perform-reachability-analysis.test.mts +++ b/src/commands/scan/perform-reachability-analysis.test.mts @@ -91,6 +91,7 @@ function makeReachabilityOptions(): ReachabilityOptions { reachEnableAnalysisSplitting: false, reachExcludePaths: [], reachLazyMode: false, + reachRetainFactsFile: false, reachSkipCache: false, reachUseOnlyPregeneratedSboms: false, reachVersion: undefined, diff --git a/src/commands/scan/reachability-flags.mts b/src/commands/scan/reachability-flags.mts index bdc8931a3..06abfe66d 100644 --- a/src/commands/scan/reachability-flags.mts +++ b/src/commands/scan/reachability-flags.mts @@ -104,6 +104,12 @@ export const reachabilityFlags: MeowFlags = { description: 'Enable lazy mode for reachability analysis.', hidden: true, }, + reachRetainFactsFile: { + type: 'boolean', + default: false, + description: + 'Keep the `.socket.facts.json` reachability report that the analysis writes to the scan directory instead of deleting it after a successful scan. IMPORTANT: you must delete this file before running a fresh tier 1 reachability scan. A stale `.socket.facts.json` left in place is picked up as a pre-generated input and silently overrides fresh analysis, so the new scan results will not be reliable.', + }, reachSkipCache: { type: 'boolean', default: false,