From 514229ffb0daf3c5c5d41f98183a7c41716af54d Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Fri, 23 Oct 2026 15:07:51 +0200 Subject: [PATCH] fix(scan): upload the analyzed facts files next to the reachability report A --reach scan uploaded Coana's report in place of every facts file. depscan drops the report's components without public metadata, so private libraries and build modules went missing from the stored SBOM and their dependencies lost their parent. Upload the facts files Coana analyzed, minus earlier reports, as --reach-use-only-pregenerated-sboms already does. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + src/commands/scan/handle-create-new-scan.mts | 34 ++++++++----------- .../scan/handle-create-new-scan.test.mts | 9 +++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee828fd3c..8594a501a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Fixed - With `--dynamic-sbom-inference`, an sbt build that fails before writing its results is reported as failed instead of reusing another build's results. +- `socket scan create --reach` keeps the private libraries and build modules of Socket facts files in the stored SBOM, with their dependencies under them. ## [1.10.0](https://github.com/SocketDev/socket-cli/releases/tag/v1.10.0) - 2026-10-22 diff --git a/src/commands/scan/handle-create-new-scan.mts b/src/commands/scan/handle-create-new-scan.mts index 98ecd3152..e55a05c07 100644 --- a/src/commands/scan/handle-create-new-scan.mts +++ b/src/commands/scan/handle-create-new-scan.mts @@ -20,7 +20,6 @@ import { checkCommandInput } from '../../utils/check-input.mts' import { compressSocketFactsForUpload, isReachabilityReportPath, - isSocketFactsFile, snapshotSocketFacts, } from '../../utils/coana.mts' import { findSocketYmlSync } from '../../utils/config.mts' @@ -360,25 +359,22 @@ async function createNewScan( reachabilityReport = reachResult.data?.reachabilityReport - // Mirror the SBOM inputs Coana analyzed; otherwise its fresh report - // (appended below) supersedes every facts file. - const pathsForScan = reach.reachUseOnlyPregeneratedSboms - ? filterToPregeneratedSboms(packagePaths, supportedFiles).filter( - p => - !isReachabilityReportPath(p, { - cwd, - outputPath: constants.DOT_SOCKET_DOT_FACTS_JSON, - }), - ) - : packagePaths.filter(p => !isSocketFactsFile(p)) - - // Append coana's reachability report, but not twice: a pre-generated facts - // input can resolve to the same path coana wrote its report to. - const reportPath = reachabilityReport - ? path.resolve(cwd, reachabilityReport) - : undefined + // Upload Coana's inputs next to its report: depscan drops the report's + // components without public metadata, such as private libraries. + const pathsForScan = ( + reach.reachUseOnlyPregeneratedSboms + ? filterToPregeneratedSboms(packagePaths, supportedFiles) + : packagePaths + ).filter( + p => + !isReachabilityReportPath(p, { + cwd, + outputPath: constants.DOT_SOCKET_DOT_FACTS_JSON, + }), + ) + scanPaths = [ - ...pathsForScan.filter(p => path.resolve(cwd, p) !== reportPath), + ...pathsForScan, ...(reachabilityReport ? [reachabilityReport] : []), ] diff --git a/src/commands/scan/handle-create-new-scan.test.mts b/src/commands/scan/handle-create-new-scan.test.mts index 6a86ff950..ab056e05e 100644 --- a/src/commands/scan/handle-create-new-scan.test.mts +++ b/src/commands/scan/handle-create-new-scan.test.mts @@ -263,7 +263,7 @@ describe('handleCreateNewScan excludePaths', () => { expect(cleanup).toHaveBeenCalledOnce() }) - it('replaces every facts file input with the reachability report', async () => { + it('keeps build facts but not earlier reports next to the reachability report', async () => { const cleanup = vi.fn() const files = [ '/repo/pom.xml.socket.facts.json', @@ -284,7 +284,12 @@ describe('handleCreateNewScan excludePaths', () => { }) await handleCreateNewScan(config) expect(mockFetchCreateOrgFullScan).toHaveBeenCalledWith( - ['/repo/package-lock.json', '.socket.facts.json'], + [ + '/repo/pom.xml.socket.facts.json', + '/repo/gradle.socket.facts.json', + '/repo/package-lock.json', + '.socket.facts.json', + ], 'fakeOrg', expect.anything(), expect.anything(),