diff --git a/CHANGELOG.md b/CHANGELOG.md index 090d23494..31676b597 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/). +## [Unreleased] + +### Fixed +- `socket scan create` now rejects every `--reach-*` modifier when `--reach` is not enabled. Previously flags such as `--reach-debug` were silently ignored, making a plain SBOM scan look like a reachability scan. + ## [1.1.157](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.157) - 2026-08-12 ### Changed diff --git a/src/commands/scan/cmd-scan-create.mts b/src/commands/scan/cmd-scan-create.mts index a7ff50d50..41564b50c 100644 --- a/src/commands/scan/cmd-scan-create.mts +++ b/src/commands/scan/cmd-scan-create.mts @@ -504,30 +504,28 @@ async function run( const isUsingNonDefaultConcurrency = reachConcurrency !== reachabilityFlags['reachConcurrency']?.default - const isUsingNonDefaultAnalytics = - reachDisableAnalytics !== - reachabilityFlags['reachDisableAnalytics']?.default - const isUsingNonDefaultVersion = reachVersion !== reachabilityFlags['reachVersion']?.default + // Compare every boolean reach flag against its declared default so newly + // added flags require --reach automatically instead of relying on a + // hand-maintained list. The deprecated no-op + // --reach-disable-analysis-splitting is excluded on purpose. + const isUsingAnyBooleanReachFlag = Object.entries(reachabilityFlags).some( + ([name, flag]) => + flag.type === 'boolean' && + name !== 'reachDisableAnalysisSplitting' && + cli.flags[name] !== flag.default, + ) + const isUsingAnyReachabilityFlags = - dynamicSbomInference || hasReachEcosystems || hasReachExcludePaths || - isUsingNonDefaultAnalytics || + isUsingAnyBooleanReachFlag || isUsingNonDefaultConcurrency || isUsingNonDefaultMemoryLimit || isUsingNonDefaultTimeout || - isUsingNonDefaultVersion || - reachContinueOnAnalysisErrors || - reachContinueOnInstallErrors || - reachContinueOnMissingLockFiles || - reachContinueOnNoSourceFiles || - reachEnableAnalysisSplitting || - reachLazyMode || - reachSkipCache || - reachUseOnlyPregeneratedSboms + isUsingNonDefaultVersion // Validate target constraints when --reach is enabled. const reachTargetValidation = reach diff --git a/src/commands/scan/cmd-scan-create.test.mts b/src/commands/scan/cmd-scan-create.test.mts index 39e2ab3b8..ddaaa47cd 100644 --- a/src/commands/scan/cmd-scan-create.test.mts +++ b/src/commands/scan/cmd-scan-create.test.mts @@ -187,6 +187,95 @@ describe('socket scan create', async () => { }, ) + cmdit( + [ + 'scan', + 'create', + FLAG_ORG, + 'fakeOrg', + 'target', + FLAG_DRY_RUN, + '--repo', + 'xyz', + '--branch', + 'abc', + '--reach-debug', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should fail when --reach-debug is used without --reach', + async cmd => { + const { code, stderr, stdout } = await spawnSocketCli(binCliPath, cmd) + const output = stdout + stderr + expect(output).toContain( + 'Reachability analysis flags require --reach to be enabled', + ) + expect(output).toContain('add --reach flag to use --reach-* options') + expect( + code, + 'should exit with non-zero code when validation fails', + ).not.toBe(0) + }, + ) + + cmdit( + [ + 'scan', + 'create', + FLAG_ORG, + 'fakeOrg', + 'target', + FLAG_DRY_RUN, + '--repo', + 'xyz', + '--branch', + 'abc', + '--reach-retain-facts-file', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should fail when --reach-retain-facts-file is used without --reach', + async cmd => { + const { code, stderr, stdout } = await spawnSocketCli(binCliPath, cmd) + const output = stdout + stderr + expect(output).toContain( + 'Reachability analysis flags require --reach to be enabled', + ) + expect(output).toContain('add --reach flag to use --reach-* options') + expect( + code, + 'should exit with non-zero code when validation fails', + ).not.toBe(0) + }, + ) + + cmdit( + [ + 'scan', + 'create', + FLAG_ORG, + 'fakeOrg', + 'target', + FLAG_DRY_RUN, + '--repo', + 'xyz', + '--branch', + 'abc', + '--reach-disable-analysis-splitting', + FLAG_CONFIG, + '{"apiToken":"fakeToken"}', + ], + 'should succeed when deprecated no-op --reach-disable-analysis-splitting is used without --reach', + async cmd => { + const { code, stdout } = await spawnSocketCli(binCliPath, cmd) + expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`) + expect( + code, + 'should exit with code 0 for the deprecated no-op flag', + ).toBe(0) + }, + ) + cmdit( [ 'scan',