From 3839f85b6acba1e6a22340880a2914d7ea7efd7e Mon Sep 17 00:00:00 2001 From: Michael Sverdlov Date: Mon, 11 Sep 2023 20:31:04 +0300 Subject: [PATCH] Add missing applicability fields from json (#945) --- xray/formats/simplejsonapi.go | 2 +- xray/utils/analyzermanager.go | 10 +++++-- xray/utils/resultstable.go | 50 ++++++++++++++++++--------------- xray/utils/resultstable_test.go | 8 +++--- xray/utils/sarifutils.go | 12 ++++---- 5 files changed, 47 insertions(+), 35 deletions(-) diff --git a/xray/formats/simplejsonapi.go b/xray/formats/simplejsonapi.go index 5a2aa1ff1..e547e09c8 100644 --- a/xray/formats/simplejsonapi.go +++ b/xray/formats/simplejsonapi.go @@ -101,7 +101,7 @@ type CveRow struct { } type Applicability struct { - Status bool `json:"status"` + Status string `json:"status"` ScannerDescription string `json:"scannerDescription,omitempty"` Evidence []Evidence `json:"evidence,omitempty"` } diff --git a/xray/utils/analyzermanager.go b/xray/utils/analyzermanager.go index 0f11cbb4d..26a24bc13 100644 --- a/xray/utils/analyzermanager.go +++ b/xray/utils/analyzermanager.go @@ -8,6 +8,7 @@ import ( "os/exec" "path" "path/filepath" + "strings" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -94,7 +95,7 @@ type AnalyzerManager struct { func (am *AnalyzerManager) Exec(configFile, scanCommand, workingDir string, serverDetails *config.ServerDetails) (err error) { if err = SetAnalyzerManagerEnvVariables(serverDetails); err != nil { - return err + return } cmd := exec.Command(am.AnalyzerManagerFullPath, scanCommand, configFile, am.MultiScanId) defer func() { @@ -105,8 +106,11 @@ func (am *AnalyzerManager) Exec(configFile, scanCommand, workingDir string, serv } }() cmd.Dir = workingDir - err = cmd.Run() - return errorutils.CheckError(err) + output, err := cmd.CombinedOutput() + if err != nil { + err = errorutils.CheckErrorf("running %q in directory: %q failed: %s - %s", strings.Join(cmd.Args, " "), workingDir, err.Error(), string(output)) + } + return } func GetAnalyzerManagerDownloadPath() (string, error) { diff --git a/xray/utils/resultstable.go b/xray/utils/resultstable.go index 42f20a864..49b124791 100644 --- a/xray/utils/resultstable.go +++ b/xray/utils/resultstable.go @@ -89,8 +89,10 @@ func prepareViolations(violations []services.Violation, extendedResults *Extende case "security": cves := convertCves(violation.Cves) applicableValue := getApplicableCveValue(extendedResults, cves) - for _, cve := range cves { - cve.Applicability = getCveApplicability(cve, extendedResults.ApplicabilityScanResults) + if extendedResults.EntitledForJas { + for i := range cves { + cves[i].Applicability = getCveApplicability(cves[i], extendedResults.ApplicabilityScanResults) + } } currSeverity := GetSeverity(violation.Severity, applicableValue) jfrogResearchInfo := convertJfrogResearchInformation(violation.ExtendedInformation) @@ -209,8 +211,10 @@ func prepareVulnerabilities(vulnerabilities []services.Vulnerability, extendedRe } cves := convertCves(vulnerability.Cves) applicableValue := getApplicableCveValue(extendedResults, cves) - for _, cve := range cves { - cve.Applicability = getCveApplicability(cve, extendedResults.ApplicabilityScanResults) + if extendedResults.EntitledForJas { + for i := range cves { + cves[i].Applicability = getCveApplicability(cves[i], extendedResults.ApplicabilityScanResults) + } } currSeverity := GetSeverity(vulnerability.Severity, applicableValue) jfrogResearchInfo := convertJfrogResearchInformation(vulnerability.ExtendedInformation) @@ -910,7 +914,7 @@ func getApplicableCveValue(extendedResults *ExtendedScanResults, xrayCves []form finalApplicableValue := NotApplicable for _, applicabilityRun := range extendedResults.ApplicabilityScanResults { for _, cve := range xrayCves { - relatedResults := GetResultsByRuleId(applicabilityRun, GetRuleIdFromCveId(cve.Id)) + relatedResults := GetResultsByRuleId(applicabilityRun, CveToApplicabilityRuleId(cve.Id)) if len(relatedResults) == 0 { finalApplicableValue = ApplicabilityUndetermined } @@ -928,37 +932,39 @@ func getApplicableCveValue(extendedResults *ExtendedScanResults, xrayCves []form return ApplicabilityUndetermined } -func getCveApplicability(cve formats.CveRow, applicabilityScanResults []*sarif.Run) (applicability *formats.Applicability) { - if len(applicabilityScanResults) == 0 { - return nil - } +func getCveApplicability(cve formats.CveRow, applicabilityScanResults []*sarif.Run) *formats.Applicability { + applicability := &formats.Applicability{Status: string(ApplicabilityUndetermined)} for _, applicabilityRun := range applicabilityScanResults { - description := "" - if relatedRule, _ := applicabilityRun.GetRuleById(GetRuleIdFromCveId(cve.Id)); relatedRule != nil { - description = GetRuleFullDescription(relatedRule) - } - relatedResult, _ := applicabilityRun.GetResultByRuleId(GetRuleIdFromCveId(cve.Id)) - if relatedResult == nil { + foundResult, _ := applicabilityRun.GetResultByRuleId(CveToApplicabilityRuleId(cve.Id)) + if foundResult == nil { continue } - // Set applicable details - applicability = &formats.Applicability{ - Status: isApplicableResult(relatedResult), - ScannerDescription: description, + applicability = &formats.Applicability{} + if isApplicableResult(foundResult) { + applicability.Status = string(Applicable) + } else { + applicability.Status = string(NotApplicable) } + + foundRule, _ := applicabilityRun.GetRuleById(CveToApplicabilityRuleId(cve.Id)) + if foundRule != nil { + applicability.ScannerDescription = GetRuleFullDescription(foundRule) + } + // Add new evidences from locations - for _, location := range relatedResult.Locations { + for _, location := range foundResult.Locations { applicability.Evidence = append(applicability.Evidence, formats.Evidence{ SourceCodeLocationRow: formats.SourceCodeLocationRow{ File: GetLocationFileName(location), LineColumn: GetStartLocationInFile(location), Snippet: GetLocationSnippet(location), }, - Reason: GetResultMsgText(relatedResult), + Reason: GetResultMsgText(foundResult), }) } + break } - return + return applicability } func printApplicableCveValue(applicableValue ApplicabilityStatus, isTable bool) string { diff --git a/xray/utils/resultstable_test.go b/xray/utils/resultstable_test.go index 8dad92cef..7ed50f24f 100644 --- a/xray/utils/resultstable_test.go +++ b/xray/utils/resultstable_test.go @@ -462,7 +462,7 @@ func TestGetApplicableCveValue(t *testing.T) { }, cves: []services.Cve{{Id: "testCve2"}}, expectedResult: Applicable, - expectedCves: []formats.CveRow{{Id: "testCve2", Applicability: &formats.Applicability{Status: true}}}, + expectedCves: []formats.CveRow{{Id: "testCve2", Applicability: &formats.Applicability{Status: string(Applicable)}}}, }, { scanResults: &ExtendedScanResults{ @@ -490,7 +490,7 @@ func TestGetApplicableCveValue(t *testing.T) { }, cves: []services.Cve{{Id: "testCve1"}, {Id: "testCve2"}}, expectedResult: NotApplicable, - expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: false}}, {Id: "testCve2", Applicability: &formats.Applicability{Status: false}}}, + expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: string(NotApplicable)}}, {Id: "testCve2", Applicability: &formats.Applicability{Status: string(NotApplicable)}}}, }, { scanResults: &ExtendedScanResults{ @@ -504,7 +504,7 @@ func TestGetApplicableCveValue(t *testing.T) { }, cves: []services.Cve{{Id: "testCve1"}, {Id: "testCve2"}}, expectedResult: Applicable, - expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: false}}, {Id: "testCve2", Applicability: &formats.Applicability{Status: true}}}, + expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: string(NotApplicable)}}, {Id: "testCve2", Applicability: &formats.Applicability{Status: string(Applicable)}}}, }, { scanResults: &ExtendedScanResults{ @@ -514,7 +514,7 @@ func TestGetApplicableCveValue(t *testing.T) { EntitledForJas: true}, cves: []services.Cve{{Id: "testCve1"}, {Id: "testCve2"}}, expectedResult: ApplicabilityUndetermined, - expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: false}}, {Id: "testCve2"}}, + expectedCves: []formats.CveRow{{Id: "testCve1", Applicability: &formats.Applicability{Status: string(NotApplicable)}}, {Id: "testCve2"}}, }, } diff --git a/xray/utils/sarifutils.go b/xray/utils/sarifutils.go index 420243441..2864d1335 100644 --- a/xray/utils/sarifutils.go +++ b/xray/utils/sarifutils.go @@ -20,6 +20,8 @@ const ( noneLevel SarifLevel = "none" SeverityDefaultValue = "Medium" + + applicabilityRuleIdPrefix = "applic_" ) var ( @@ -137,7 +139,7 @@ func GetDiffFromResult(result *sarif.Result, source *sarif.Result) *sarif.Result for _, targetCodeFlow := range GetLocationRelatedCodeFlowsFromResult(targetLocation, result) { for _, sourceCodeFlow := range GetLocationRelatedCodeFlowsFromResult(targetLocation, source) { if !IsSameCodeFlow(targetCodeFlow, sourceCodeFlow) { - // Code flow does not exists at source, add it and it's related location + // Code flow does not exist at source, add it and it's related location newLocations.Add(targetLocation) newCodeFlows = append(newCodeFlows, targetCodeFlow) } @@ -372,12 +374,12 @@ func GetRuleFullDescription(rule *sarif.ReportingDescriptor) string { return "" } -func GetRuleIdFromCveId(cveId string) string { - return "applic_" + cveId +func CveToApplicabilityRuleId(cveId string) string { + return applicabilityRuleIdPrefix + cveId } -func GetCveIdFromRuleId(sarifRuleId string) string { - return strings.TrimPrefix(sarifRuleId, "applic_") +func ApplicabilityRuleIdToCve(sarifRuleId string) string { + return strings.TrimPrefix(sarifRuleId, applicabilityRuleIdPrefix) } func GetRunRules(run *sarif.Run) []*sarif.ReportingDescriptor {