From a19bcdc41bd03653b554d79d4fd1e95c6be310bb Mon Sep 17 00:00:00 2001 From: Assaf Attias <49212512+attiasas@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:39:49 +0300 Subject: [PATCH] Apply Min-Severity filter on Jas results (#192) --- commands/audit/audit.go | 2 +- commands/scan/scan.go | 2 +- jas/applicability/applicabilitymanager.go | 2 +- .../applicabilitymanager_test.go | 2 +- jas/common.go | 29 +++++++++++++++++-- jas/iac/iacscanner.go | 2 +- jas/iac/iacscanner_test.go | 4 +-- jas/runner/jasrunner_test.go | 6 ++-- jas/sast/sastscanner.go | 2 +- jas/sast/sastscanner_test.go | 4 +-- jas/secrets/secretsscanner.go | 2 +- jas/secrets/secretsscanner_test.go | 7 +++-- .../other/secrets-scan/contain-secrets.sarif | 1 + 13 files changed, 45 insertions(+), 20 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 99d5c77d..85ec44f2 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -248,7 +248,7 @@ func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams err = fmt.Errorf("failed to get server details: %s", err.Error()) return } - jasScanner, err = jas.CreateJasScanner(jfrogAppsConfig, serverDetails, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, results.ExtendedScanResults.SecretValidation, results.GetScaScannedTechnologies()...), auditParams.Exclusions()...) + jasScanner, err = jas.CreateJasScanner(jfrogAppsConfig, serverDetails, auditParams.minSeverityFilter, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, results.ExtendedScanResults.SecretValidation, results.GetScaScannedTechnologies()...), auditParams.Exclusions()...) if err != nil { err = fmt.Errorf("failed to create jas scanner: %s", err.Error()) return diff --git a/commands/scan/scan.go b/commands/scan/scan.go index ac4af6ab..d6c93667 100644 --- a/commands/scan/scan.go +++ b/commands/scan/scan.go @@ -451,7 +451,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, entitledFo log.Error(fmt.Sprintf("failed to create JFrogAppsConfig: %s", err.Error())) indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()}) } - scanner, err := jas.CreateJasScanner(jfrogAppsConfig, scanCmd.serverDetails, jas.GetAnalyzerManagerXscEnvVars(scanResults.MultiScanId, validateSecrets, techutils.Technology(graphScanResults.ScannedPackageType))) + scanner, err := jas.CreateJasScanner(jfrogAppsConfig, scanCmd.serverDetails, scanCmd.minSeverityFilter, jas.GetAnalyzerManagerXscEnvVars(scanResults.MultiScanId, validateSecrets, techutils.Technology(graphScanResults.ScannedPackageType))) if err != nil { log.Error(fmt.Sprintf("failed to create jas scanner: %s", err.Error())) indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()}) diff --git a/jas/applicability/applicabilitymanager.go b/jas/applicability/applicabilitymanager.go index 0850c573..45b26ece 100644 --- a/jas/applicability/applicabilitymanager.go +++ b/jas/applicability/applicabilitymanager.go @@ -135,7 +135,7 @@ func (asm *ApplicabilityScanManager) Run(module jfrogappsconfig.Module) (err err if err = asm.runAnalyzerManager(); err != nil { return } - workingDirResults, err := jas.ReadJasScanRunsFromFile(asm.resultsFileName, module.SourceRoot, applicabilityDocsUrlSuffix) + workingDirResults, err := jas.ReadJasScanRunsFromFile(asm.resultsFileName, module.SourceRoot, applicabilityDocsUrlSuffix, asm.scanner.MinSeverity) if err != nil { return } diff --git a/jas/applicability/applicabilitymanager_test.go b/jas/applicability/applicabilitymanager_test.go index b0797b48..55da459e 100644 --- a/jas/applicability/applicabilitymanager_test.go +++ b/jas/applicability/applicabilitymanager_test.go @@ -310,7 +310,7 @@ func TestParseResults_NewApplicabilityStatuses(t *testing.T) { t.Run(tc.name, func(t *testing.T) { applicabilityManager.resultsFileName = filepath.Join(jas.GetTestDataPath(), "applicability-scan", tc.fileName) var err error - applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, applicabilityDocsUrlSuffix) + applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, applicabilityDocsUrlSuffix, scanner.MinSeverity) if assert.NoError(t, err) && assert.NotNil(t, applicabilityManager.applicabilityScanResults) { assert.Len(t, applicabilityManager.applicabilityScanResults, 1) assert.Len(t, applicabilityManager.applicabilityScanResults[0].Results, tc.expectedResults) diff --git a/jas/common.go b/jas/common.go index d5b28b20..5acdb987 100644 --- a/jas/common.go +++ b/jas/common.go @@ -44,9 +44,10 @@ type JasScanner struct { ScannerDirCleanupFunc func() error EnvVars map[string]string Exclusions []string + MinSeverity severityutils.Severity } -func CreateJasScanner(jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig, serverDetails *config.ServerDetails, envVars map[string]string, exclusions ...string) (scanner *JasScanner, err error) { +func CreateJasScanner(jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig, serverDetails *config.ServerDetails, minSeverity severityutils.Severity, envVars map[string]string, exclusions ...string) (scanner *JasScanner, err error) { if serverDetails == nil { err = errors.New(NoServerDetailsError) return @@ -70,6 +71,7 @@ func CreateJasScanner(jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig, serverDe scanner.ServerDetails = serverDetails scanner.JFrogAppsConfig = jfrogAppsConfig scanner.Exclusions = exclusions + scanner.MinSeverity = minSeverity return } @@ -121,7 +123,7 @@ func (a *JasScanner) Run(scannerCmd ScannerCmd, module jfrogappsconfig.Module) ( return } -func ReadJasScanRunsFromFile(fileName, wd, informationUrlSuffix string) (sarifRuns []*sarif.Run, err error) { +func ReadJasScanRunsFromFile(fileName, wd, informationUrlSuffix string, minSeverity severityutils.Severity) (sarifRuns []*sarif.Run, err error) { if sarifRuns, err = sarifutils.ReadScanRunsFromFile(fileName); err != nil { return } @@ -136,6 +138,7 @@ func ReadJasScanRunsFromFile(fileName, wd, informationUrlSuffix string) (sarifRu // Process runs values fillMissingRequiredDriverInformation(utils.BaseDocumentationURL+informationUrlSuffix, GetAnalyzerManagerVersion(), sarifRun) sarifRun.Results = excludeSuppressResults(sarifRun.Results) + sarifRun.Results = excludeMinSeverityResults(sarifRun.Results, minSeverity) addScoreToRunRules(sarifRun) } return @@ -171,6 +174,26 @@ func excludeSuppressResults(sarifResults []*sarif.Result) []*sarif.Result { return results } +func excludeMinSeverityResults(sarifResults []*sarif.Result, minSeverity severityutils.Severity) []*sarif.Result { + if minSeverity == "" { + // No minimum severity to exclude + return sarifResults + } + results := []*sarif.Result{} + for _, sarifResult := range sarifResults { + resultSeverity, err := severityutils.ParseSeverity(sarifutils.GetResultLevel(sarifResult), true) + if err != nil { + log.Warn(fmt.Sprintf("Failed to parse Sarif level %s: %s", sarifutils.GetResultLevel(sarifResult), err.Error())) + resultSeverity = severityutils.Unknown + } + // Exclude results with severity lower than the minimum severity + if severityutils.GetSeverityPriority(resultSeverity, jasutils.ApplicabilityUndetermined) >= severityutils.GetSeverityPriority(minSeverity, jasutils.ApplicabilityUndetermined) { + results = append(results, sarifResult) + } + } + return results +} + func addScoreToRunRules(sarifRun *sarif.Run) { for _, sarifResult := range sarifRun.Results { if rule, err := sarifRun.GetRuleById(*sarifResult.RuleID); err == nil { @@ -225,7 +248,7 @@ func InitJasTest(t *testing.T, workingDirs ...string) (*JasScanner, func()) { assert.NoError(t, DownloadAnalyzerManagerIfNeeded(0)) jfrogAppsConfigForTest, err := CreateJFrogAppsConfig(workingDirs) assert.NoError(t, err) - scanner, err := CreateJasScanner(jfrogAppsConfigForTest, &FakeServerDetails, GetAnalyzerManagerXscEnvVars("", false)) + scanner, err := CreateJasScanner(jfrogAppsConfigForTest, &FakeServerDetails, "", GetAnalyzerManagerXscEnvVars("", false)) assert.NoError(t, err) return scanner, func() { assert.NoError(t, scanner.ScannerDirCleanupFunc()) diff --git a/jas/iac/iacscanner.go b/jas/iac/iacscanner.go index 49aaa7f4..67d0e98f 100644 --- a/jas/iac/iacscanner.go +++ b/jas/iac/iacscanner.go @@ -67,7 +67,7 @@ func (iac *IacScanManager) Run(module jfrogappsconfig.Module) (err error) { if err = iac.runAnalyzerManager(); err != nil { return } - workingDirResults, err := jas.ReadJasScanRunsFromFile(iac.resultsFileName, module.SourceRoot, iacDocsUrlSuffix) + workingDirResults, err := jas.ReadJasScanRunsFromFile(iac.resultsFileName, module.SourceRoot, iacDocsUrlSuffix, iac.scanner.MinSeverity) if err != nil { return } diff --git a/jas/iac/iacscanner_test.go b/jas/iac/iacscanner_test.go index de49351e..e1acc362 100644 --- a/jas/iac/iacscanner_test.go +++ b/jas/iac/iacscanner_test.go @@ -65,7 +65,7 @@ func TestIacParseResults_EmptyResults(t *testing.T) { // Act var err error - iacScanManager.iacScannerResults, err = jas.ReadJasScanRunsFromFile(iacScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, iacDocsUrlSuffix) + iacScanManager.iacScannerResults, err = jas.ReadJasScanRunsFromFile(iacScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, iacDocsUrlSuffix, scanner.MinSeverity) if assert.NoError(t, err) && assert.NotNil(t, iacScanManager.iacScannerResults) { assert.Len(t, iacScanManager.iacScannerResults, 1) assert.Empty(t, iacScanManager.iacScannerResults[0].Results) @@ -81,7 +81,7 @@ func TestIacParseResults_ResultsContainIacViolations(t *testing.T) { // Act var err error - iacScanManager.iacScannerResults, err = jas.ReadJasScanRunsFromFile(iacScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, iacDocsUrlSuffix) + iacScanManager.iacScannerResults, err = jas.ReadJasScanRunsFromFile(iacScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, iacDocsUrlSuffix, scanner.MinSeverity) if assert.NoError(t, err) && assert.NotNil(t, iacScanManager.iacScannerResults) { assert.Len(t, iacScanManager.iacScannerResults, 1) assert.Len(t, iacScanManager.iacScannerResults[0].Results, 4) diff --git a/jas/runner/jasrunner_test.go b/jas/runner/jasrunner_test.go index e5e9f03e..a6c2f446 100644 --- a/jas/runner/jasrunner_test.go +++ b/jas/runner/jasrunner_test.go @@ -26,7 +26,7 @@ func TestJasRunner_AnalyzerManagerNotExist(t *testing.T) { defer func() { assert.NoError(t, os.Unsetenv(coreutils.HomeDir)) }() - scanner, err := jas.CreateJasScanner(nil, &jas.FakeServerDetails, jas.GetAnalyzerManagerXscEnvVars("", false)) + scanner, err := jas.CreateJasScanner(nil, &jas.FakeServerDetails, "", jas.GetAnalyzerManagerXscEnvVars("", false)) assert.NoError(t, err) if scanner.AnalyzerManager.AnalyzerManagerFullPath, err = jas.GetAnalyzerManagerExecutable(); err != nil { return @@ -42,7 +42,7 @@ func TestJasRunner(t *testing.T) { jfrogAppsConfigForTest, err := jas.CreateJFrogAppsConfig(nil) assert.NoError(t, err) - jasScanner, err := jas.CreateJasScanner(jfrogAppsConfigForTest, &jas.FakeServerDetails, jas.GetAnalyzerManagerXscEnvVars("", false, scanResults.GetScaScannedTechnologies()...)) + jasScanner, err := jas.CreateJasScanner(jfrogAppsConfigForTest, &jas.FakeServerDetails, "", jas.GetAnalyzerManagerXscEnvVars("", false, scanResults.GetScaScannedTechnologies()...)) assert.NoError(t, err) err = AddJasScannersTasks(securityParallelRunnerForTest, scanResults, &[]string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, false, jasScanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, securityParallelRunnerForTest.AddErrorToChan, utils.GetAllSupportedScans(), nil, "") assert.NoError(t, err) @@ -52,7 +52,7 @@ func TestJasRunner_AnalyzerManagerReturnsError(t *testing.T) { assert.NoError(t, jas.DownloadAnalyzerManagerIfNeeded(0)) jfrogAppsConfigForTest, _ := jas.CreateJFrogAppsConfig(nil) - scanner, _ := jas.CreateJasScanner(nil, &jas.FakeServerDetails, jas.GetAnalyzerManagerXscEnvVars("", false)) + scanner, _ := jas.CreateJasScanner(nil, &jas.FakeServerDetails, "", jas.GetAnalyzerManagerXscEnvVars("", false)) _, err := applicability.RunApplicabilityScan(jas.FakeBasicXrayResults, []string{"issueId_2_direct_dependency", "issueId_1_direct_dependency"}, scanner, false, applicability.ApplicabilityScannerType, jfrogAppsConfigForTest.Modules[0], 0) // Expect error: diff --git a/jas/sast/sastscanner.go b/jas/sast/sastscanner.go index ce58fc8c..e5747179 100644 --- a/jas/sast/sastscanner.go +++ b/jas/sast/sastscanner.go @@ -60,7 +60,7 @@ func (ssm *SastScanManager) Run(module jfrogappsconfig.Module) (err error) { if err = ssm.runAnalyzerManager(filepath.Dir(ssm.scanner.AnalyzerManager.AnalyzerManagerFullPath)); err != nil { return } - workingDirRuns, err := jas.ReadJasScanRunsFromFile(ssm.resultsFileName, module.SourceRoot, sastDocsUrlSuffix) + workingDirRuns, err := jas.ReadJasScanRunsFromFile(ssm.resultsFileName, module.SourceRoot, sastDocsUrlSuffix, ssm.scanner.MinSeverity) if err != nil { return } diff --git a/jas/sast/sastscanner_test.go b/jas/sast/sastscanner_test.go index a6e21a5c..af154e74 100644 --- a/jas/sast/sastscanner_test.go +++ b/jas/sast/sastscanner_test.go @@ -36,7 +36,7 @@ func TestSastParseResults_EmptyResults(t *testing.T) { // Act var err error - sastScanManager.sastScannerResults, err = jas.ReadJasScanRunsFromFile(sastScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, sastDocsUrlSuffix) + sastScanManager.sastScannerResults, err = jas.ReadJasScanRunsFromFile(sastScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, sastDocsUrlSuffix, scanner.MinSeverity) // Assert if assert.NoError(t, err) && assert.NotNil(t, sastScanManager.sastScannerResults) { @@ -57,7 +57,7 @@ func TestSastParseResults_ResultsContainIacViolations(t *testing.T) { // Act var err error - sastScanManager.sastScannerResults, err = jas.ReadJasScanRunsFromFile(sastScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, sastDocsUrlSuffix) + sastScanManager.sastScannerResults, err = jas.ReadJasScanRunsFromFile(sastScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, sastDocsUrlSuffix, scanner.MinSeverity) // Assert if assert.NoError(t, err) && assert.NotNil(t, sastScanManager.sastScannerResults) { diff --git a/jas/secrets/secretsscanner.go b/jas/secrets/secretsscanner.go index 391491b0..eaa29334 100644 --- a/jas/secrets/secretsscanner.go +++ b/jas/secrets/secretsscanner.go @@ -74,7 +74,7 @@ func (ssm *SecretScanManager) Run(module jfrogappsconfig.Module) (err error) { if err = ssm.runAnalyzerManager(); err != nil { return } - workingDirRuns, err := jas.ReadJasScanRunsFromFile(ssm.resultsFileName, module.SourceRoot, secretsDocsUrlSuffix) + workingDirRuns, err := jas.ReadJasScanRunsFromFile(ssm.resultsFileName, module.SourceRoot, secretsDocsUrlSuffix, ssm.scanner.MinSeverity) if err != nil { return } diff --git a/jas/secrets/secretsscanner_test.go b/jas/secrets/secretsscanner_test.go index c6473e54..37745a6b 100644 --- a/jas/secrets/secretsscanner_test.go +++ b/jas/secrets/secretsscanner_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/jfrog/jfrog-cli-security/utils/jasutils" + "github.com/jfrog/jfrog-cli-security/utils/severityutils" "github.com/stretchr/testify/require" jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go" @@ -72,7 +73,7 @@ func TestParseResults_EmptyResults(t *testing.T) { // Act var err error - secretScanManager.secretsScannerResults, err = jas.ReadJasScanRunsFromFile(secretScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, secretsDocsUrlSuffix) + secretScanManager.secretsScannerResults, err = jas.ReadJasScanRunsFromFile(secretScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, secretsDocsUrlSuffix, scanner.MinSeverity) // Assert if assert.NoError(t, err) && assert.NotNil(t, secretScanManager.secretsScannerResults) { @@ -95,7 +96,7 @@ func TestParseResults_ResultsContainSecrets(t *testing.T) { // Act var err error - secretScanManager.secretsScannerResults, err = jas.ReadJasScanRunsFromFile(secretScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, secretsDocsUrlSuffix) + secretScanManager.secretsScannerResults, err = jas.ReadJasScanRunsFromFile(secretScanManager.resultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot, secretsDocsUrlSuffix, severityutils.Medium) // Assert if assert.NoError(t, err) && assert.NotNil(t, secretScanManager.secretsScannerResults) { @@ -103,7 +104,7 @@ func TestParseResults_ResultsContainSecrets(t *testing.T) { assert.NotEmpty(t, secretScanManager.secretsScannerResults[0].Results) secretScanManager.secretsScannerResults = processSecretScanRuns(secretScanManager.secretsScannerResults) assert.Len(t, secretScanManager.secretsScannerResults, 1) - assert.Len(t, secretScanManager.secretsScannerResults[0].Results, 7) + assert.Len(t, secretScanManager.secretsScannerResults[0].Results, 6) } assert.NoError(t, err) diff --git a/tests/testdata/other/secrets-scan/contain-secrets.sarif b/tests/testdata/other/secrets-scan/contain-secrets.sarif index af3f378e..1f2f2b7f 100644 --- a/tests/testdata/other/secrets-scan/contain-secrets.sarif +++ b/tests/testdata/other/secrets-scan/contain-secrets.sarif @@ -177,6 +177,7 @@ "message": { "text": "Hardcoded secrets were found in source files" }, + "level": "note", "locations": [ { "physicalLocation": {