diff --git a/scanrepository/scanrepository.go b/scanrepository/scanrepository.go index 2f2daee07..6db5732ca 100644 --- a/scanrepository/scanrepository.go +++ b/scanrepository/scanrepository.go @@ -161,7 +161,6 @@ func (sr *ScanRepositoryCmd) scanAndFixBranch(repository *utils.Repository) (tot log.Info(fmt.Sprintf("This command is running in detection mode only. To enable automatic fixing of issues, set the '%s' flag under the repository's configuration settings in Jfrog platform", createAutoFixPrConfigNameInProfile)) return totalFindings, nil } - vulnerabilitiesByPathMap, err := sr.createVulnerabilitiesMap(repository.GeneralConfig.FailUponAnyScannerError, scanResults) if err != nil { if err = utils.CreateErrorIfFailUponScannerErrorEnabled(repository.GeneralConfig.FailUponAnyScannerError, fmt.Sprintf("An error occurred while preparing the vulnerabilities map for branch '%s'.", sr.scanDetails.BaseBranch()), err); err != nil { @@ -498,6 +497,10 @@ func (sr *ScanRepositoryCmd) switchToTempWorkingDir() (tempWd string, restoreDir // Create a vulnerabilities map - a map with 'impacted package' as a key and all the necessary information of this vulnerability as value. func (sr *ScanRepositoryCmd) createVulnerabilitiesMap(failUponError bool, scanResults *results.SecurityCommandResults) (map[string]*utils.VulnerabilityDetails, error) { + if scanResults == nil { + log.Info("No scan results found") + return nil, nil + } vulnerabilitiesMap := map[string]*utils.VulnerabilityDetails{} simpleJsonResult, err := conversion.NewCommandResultsConvertor(conversion.ResultConvertParams{IncludeVulnerabilities: scanResults.IncludesVulnerabilities(), HasViolationContext: scanResults.HasViolationContext()}).ConvertToSimpleJson(scanResults) if err != nil { diff --git a/scanrepository/scanrepository_test.go b/scanrepository/scanrepository_test.go index 6ed441f31..d966bc8ee 100644 --- a/scanrepository/scanrepository_test.go +++ b/scanrepository/scanrepository_test.go @@ -486,6 +486,11 @@ func TestCreateVulnerabilitiesMap(t *testing.T) { scanResults *results.SecurityCommandResults expectedMap map[string]*utils.VulnerabilityDetails }{ + { + name: "No results", + scanResults: nil, + expectedMap: map[string]*utils.VulnerabilityDetails{}, + }, { name: "Scan results with no violations and vulnerabilities", scanResults: &results.SecurityCommandResults{Targets: []*results.TargetResults{{ @@ -638,6 +643,116 @@ func loadTestSBOM(t *testing.T, filename string) *cyclonedx.BOM { return bom } +func TestGetTotalFindingsFromScanResults(t *testing.T) { + testCases := []struct { + name string + scanResults *results.SecurityCommandResults + expectedCount int + }{ + { + name: "Nil scan results", + scanResults: nil, + expectedCount: 0, + }, + { + name: "No violations or vulnerabilities", + scanResults: &results.SecurityCommandResults{Targets: []*results.TargetResults{{ + ScanTarget: results.ScanTarget{Target: "target1"}, + }}}, + expectedCount: 0, + }, + { + name: "Vulnerabilities only", + scanResults: &results.SecurityCommandResults{ + ResultsMetaData: results.ResultsMetaData{ + ResultContext: results.ResultContext{IncludeVulnerabilities: true}}, + Targets: []*results.TargetResults{{ + ScanTarget: results.ScanTarget{Target: "target1", Technologies: []techutils.Technology{techutils.Npm}}, + ScaResults: &results.ScaScanResults{ + Sbom: loadTestSBOM(t, "sbom_with_vulnerabilities.json"), + }, + }}, + }, + expectedCount: 4, + }, + { + name: "Violations only", + scanResults: &results.SecurityCommandResults{ + ResultsMetaData: results.ResultsMetaData{ + ResultContext: results.ResultContext{Watches: []string{"w1"}}}, + Targets: []*results.TargetResults{{ + ScanTarget: results.ScanTarget{Target: "target1", Technologies: []techutils.Technology{techutils.Npm}}, + }}, + Violations: &violationutils.Violations{ + Sca: []violationutils.CveViolation{ + { + ScaViolation: violationutils.ScaViolation{ + ImpactedComponent: cyclonedx.Component{ + BOMRef: "pkg:npm/viol1@1.0.0", + PackageURL: "pkg:npm/viol1@1.0.0", + }, + }, + CveVulnerability: cyclonedx.Vulnerability{BOMRef: "CVE-2023-1234"}, + }, + { + ScaViolation: violationutils.ScaViolation{ + ImpactedComponent: cyclonedx.Component{ + BOMRef: "pkg:npm/viol2@2.0.0", + PackageURL: "pkg:npm/viol2@2.0.0", + }, + }, + CveVulnerability: cyclonedx.Vulnerability{BOMRef: "CVE-2022-1234"}, + }, + }, + }, + }, + expectedCount: 2, + }, + { + name: "Violations take precedence over vulnerabilities", + scanResults: &results.SecurityCommandResults{ + ResultsMetaData: results.ResultsMetaData{ + ResultContext: results.ResultContext{IncludeVulnerabilities: true, Watches: []string{"w1"}}}, + Targets: []*results.TargetResults{{ + ScanTarget: results.ScanTarget{Target: "target1", Technologies: []techutils.Technology{techutils.Npm}}, + ScaResults: &results.ScaScanResults{ + Sbom: loadTestSBOM(t, "sbom_with_vulnerabilities.json"), + }, + }}, + Violations: &violationutils.Violations{ + Sca: []violationutils.CveViolation{ + { + ScaViolation: violationutils.ScaViolation{ + ImpactedComponent: cyclonedx.Component{ + BOMRef: "pkg:npm/viol1@1.0.0", + PackageURL: "pkg:npm/viol1@1.0.0", + }, + }, + CveVulnerability: cyclonedx.Vulnerability{BOMRef: "CVE-2023-1234"}, + }, + { + ScaViolation: violationutils.ScaViolation{ + ImpactedComponent: cyclonedx.Component{ + BOMRef: "pkg:npm/viol2@2.0.0", + PackageURL: "pkg:npm/viol2@2.0.0", + }, + }, + CveVulnerability: cyclonedx.Vulnerability{BOMRef: "CVE-2022-1234"}, + }, + }, + }, + }, + expectedCount: 2, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + assert.Equal(t, testCase.expectedCount, getTotalFindingsFromScanResults(testCase.scanResults)) + }) + } +} + // Verifies unsupported packages return specific error // Other logic is implemented inside each package-handler. func TestUpdatePackageToFixedVersion(t *testing.T) {