diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 4a5f7c049..f0d09a491 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -431,7 +431,7 @@ func detectScanTargets(cmdResults *results.SecurityCommandResults, params *Audit continue } // Detect descriptors and technologies in the requested directory. - techToWorkingDirs, err := techutils.DetectTechnologiesDescriptors(requestedDirectory, params.IsRecursiveScan(), params.Technologies(), getRequestedDescriptors(params), technologies.GetExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...)) + techToWorkingDirs, err := techutils.DetectTechnologiesDescriptors(requestedDirectory, params.IsRecursiveScan(), params.Technologies(), getRequestedDescriptors(params), technologies.GetScaExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...)) if err != nil { log.Warn("Couldn't detect technologies in", requestedDirectory, "directory.", err.Error()) continue diff --git a/commands/audit/auditparams.go b/commands/audit/auditparams.go index ce1fccca8..7c1b3dee0 100644 --- a/commands/audit/auditparams.go +++ b/commands/audit/auditparams.go @@ -196,7 +196,7 @@ func (params *AuditParams) ToBuildInfoBomGenParams() (bomParams technologies.Bui bomParams = technologies.BuildInfoBomGeneratorParams{ XrayVersion: params.GetXrayVersion(), Progress: params.Progress(), - ExclusionPattern: technologies.GetExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...), + ExclusionPattern: technologies.GetScaExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...), AllowPartialResults: params.AllowPartialResults(), // Artifactory repository info ServerDetails: serverDetails, diff --git a/commands/curation/curationaudit.go b/commands/curation/curationaudit.go index 77d3a0fc2..21f9dfa42 100644 --- a/commands/curation/curationaudit.go +++ b/commands/curation/curationaudit.go @@ -405,7 +405,7 @@ func (ca *CurationAuditCommand) getBuildInfoParamsByTech() (technologies.BuildIn serverDetails, err := ca.ServerDetails() return technologies.BuildInfoBomGeneratorParams{ XrayVersion: ca.GetXrayVersion(), - ExclusionPattern: technologies.GetExcludePattern(ca.GetConfigProfile(), ca.IsRecursiveScan(), ca.Exclusions()...), + ExclusionPattern: technologies.GetScaExcludePattern(ca.GetConfigProfile(), ca.IsRecursiveScan(), ca.Exclusions()...), Progress: ca.Progress(), // Artifactory Repository params ServerDetails: serverDetails, diff --git a/jas/common.go b/jas/common.go index df81b7a5e..d040862ae 100644 --- a/jas/common.go +++ b/jas/common.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strconv" "strings" "testing" @@ -12,6 +13,7 @@ import ( "unicode" "github.com/jfrog/gofrog/datastructures" + "github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns" clientservices "github.com/jfrog/jfrog-client-go/xsc/services" jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go" @@ -30,6 +32,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xray" "github.com/jfrog/jfrog-client-go/xray/services" + xscServices "github.com/jfrog/jfrog-client-go/xsc/services" "github.com/owenrumney/go-sarif/v3/pkg/report/v210/sarif" "github.com/stretchr/testify/assert" "golang.org/x/exp/slices" @@ -395,15 +398,67 @@ func GetModule(root string, appConfig *jfrogappsconfig.JFrogAppsConfig) *jfrogap return nil } -func ShouldSkipScanner(module jfrogappsconfig.Module, scanType jasutils.JasScanType) bool { +func ShouldSkipScanner(root string, module jfrogappsconfig.Module, scanType jasutils.JasScanType) bool { lowerScanType := strings.ToLower(string(scanType)) if slices.Contains(module.ExcludeScanners, lowerScanType) { log.Info(fmt.Sprintf("Skipping %s scanning", scanType)) return true } + exclusions := []string{} + switch scanType { + case jasutils.Sast: + if module.Scanners.Sast == nil { + return true + } + exclusions = append(module.ExcludePatterns, module.Scanners.Sast.ExcludePatterns...) + case jasutils.Secrets: + if module.Scanners.Secrets == nil { + return true + } + exclusions = append(module.ExcludePatterns, module.Scanners.Secrets.ExcludePatterns...) + case jasutils.IaC: + if module.Scanners.Iac == nil { + return true + } + exclusions = append(module.ExcludePatterns, module.Scanners.Iac.ExcludePatterns...) + } + // Check if target (root) is excluded in the module exclude patterns + if isPathExcluded(root, exclusions) { + log.Info(fmt.Sprintf("Skipping %s scanning", scanType)) + return true + } + return false +} + +func ShouldSkipScannerByRemoteConfig(root string, module xscServices.Module, scanType jasutils.JasScanType) bool { + exclusions := []string{} + switch scanType { + case jasutils.Sast: + exclusions = append(module.ExcludePatterns, module.ScanConfig.SastScannerConfig.ExcludePatterns...) + case jasutils.Secrets: + exclusions = append(module.ExcludePatterns, module.ScanConfig.SecretsScannerConfig.ExcludePatterns...) + case jasutils.IaC: + exclusions = append(module.ExcludePatterns, module.ScanConfig.IacScannerConfig.ExcludePatterns...) + case jasutils.Applicability: + exclusions = append(module.ExcludePatterns, module.ScanConfig.ContextualAnalysisScannerConfig.ExcludePatterns...) + } + // Check if target (root) is excluded in the module exclude patterns + if isPathExcluded(root, exclusions) { + log.Info(fmt.Sprintf("Skipping %s scanning", scanType)) + return true + } return false } +func isPathExcluded(root string, exclusions []string) bool { + match, err := regexp.MatchString(fspatterns.PrepareExcludePathPattern(exclusions, goclientutils.WildCardPattern, true), root) + if err != nil { + log.Warn("Failed to check if path is excluded:", err.Error()) + return false + } + return match +} + func GetSourceRoots(module jfrogappsconfig.Module, scanner *jfrogappsconfig.Scanner) ([]string, error) { root, err := filepath.Abs(module.SourceRoot) if err != nil { diff --git a/jas/common_test.go b/jas/common_test.go index ac97ac27a..226a7340e 100644 --- a/jas/common_test.go +++ b/jas/common_test.go @@ -67,11 +67,11 @@ func TestCreateJFrogAppsConfigWithConfig(t *testing.T) { func TestShouldSkipScanner(t *testing.T) { module := jfrogAppsConfig.Module{} - assert.False(t, ShouldSkipScanner(module, jasutils.IaC)) + assert.False(t, ShouldSkipScanner("", module, jasutils.IaC)) module = jfrogAppsConfig.Module{ExcludeScanners: []string{"sast"}} - assert.False(t, ShouldSkipScanner(module, jasutils.IaC)) - assert.True(t, ShouldSkipScanner(module, jasutils.Sast)) + assert.False(t, ShouldSkipScanner("", module, jasutils.IaC)) + assert.True(t, ShouldSkipScanner("", module, jasutils.Sast)) } var getSourceRootsCases = []struct { diff --git a/jas/runner/jasrunner.go b/jas/runner/jasrunner.go index 85504859b..52c39cf76 100644 --- a/jas/runner/jasrunner.go +++ b/jas/runner/jasrunner.go @@ -101,14 +101,12 @@ func addJasScanTaskForModuleIfNeeded(params JasRunnerParams, subScan utils.SubSc // In Applicability scanner we must check that Sca is also enabled, since we cannot run CA without Sca results enabled = params.ConfigProfile.Modules[0].ScanConfig.ContextualAnalysisScannerConfig.EnableCaScan && params.ConfigProfile.Modules[0].ScanConfig.ScaScannerConfig.EnableScaScan } - if enabled { - generalError = addModuleJasScanTask(jasType, params.Runner, task, params.ScanResults, params.AllowPartialResults) - } else { + if !enabled || jas.ShouldSkipScannerByRemoteConfig(params.ScanResults.Target, params.ConfigProfile.Modules[0], jasType) { log.Debug(fmt.Sprintf("Skipping %s scan as requested by '%s' config profile...", jasType, params.ConfigProfile.ProfileName)) } - return + return addModuleJasScanTask(jasType, params.Runner, task, params.ScanResults, params.AllowPartialResults) } - if jas.ShouldSkipScanner(params.Module, jasType) { + if jas.ShouldSkipScanner(params.ScanResults.Target, params.Module, jasType) { log.Debug(fmt.Sprintf("Skipping %s scan as requested by local module config...", subScan)) return } diff --git a/sca/bom/buildinfo/technologies/common.go b/sca/bom/buildinfo/technologies/common.go index 71fb5459c..153a63725 100644 --- a/sca/bom/buildinfo/technologies/common.go +++ b/sca/bom/buildinfo/technologies/common.go @@ -75,7 +75,7 @@ func (bbp *BuildInfoBomGeneratorParams) SetConanProfile(file string) *BuildInfoB return bbp } -func GetExcludePattern(configProfile *xscservices.ConfigProfile, isRecursive bool, exclusions ...string) string { +func GetScaExcludePattern(configProfile *xscservices.ConfigProfile, isRecursive bool, exclusions ...string) string { if configProfile != nil { exclusions = append(exclusions, configProfile.Modules[0].ScanConfig.ScaScannerConfig.ExcludePatterns...) } diff --git a/sca/bom/buildinfo/technologies/common_test.go b/sca/bom/buildinfo/technologies/common_test.go index 1dc51bd87..5148b6f92 100644 --- a/sca/bom/buildinfo/technologies/common_test.go +++ b/sca/bom/buildinfo/technologies/common_test.go @@ -71,7 +71,7 @@ func TestGetExcludePattern(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - result := GetExcludePattern(test.configProfile, test.isRecursiveScan, test.exclusions...) + result := GetScaExcludePattern(test.configProfile, test.isRecursiveScan, test.exclusions...) assert.Equal(t, test.expected, result) }) }