Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unite relative path conversion #947

Merged
merged 14 commits into from
Sep 12, 2023
2 changes: 1 addition & 1 deletion xray/formats/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func ConvertToSecretsTableRow(rows []SourceCodeRow) (tableRows []secretsTableRow
tableRows = append(tableRows, secretsTableRow{
severity: rows[i].Severity,
file: rows[i].File,
lineColumn: (strconv.Itoa(rows[i].StartLine) + ":" + strconv.Itoa(rows[i].StartColumn)),
lineColumn: strconv.Itoa(rows[i].StartLine) + ":" + strconv.Itoa(rows[i].StartColumn),
text: rows[i].Snippet,
})
}
Expand Down
2 changes: 1 addition & 1 deletion xray/utils/analyzermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
EntitlementsMinVersion = "3.66.5"
ApplicabilityFeatureId = "contextual_analysis"
AnalyzerManagerZipName = "analyzerManager.zip"
defaultAnalyzerManagerVersion = "1.2.4.1953469"
defaultAnalyzerManagerVersion = "1.2.4.2000151"
minAnalyzerManagerVersionForSast = "1.3"
analyzerManagerDownloadPath = "xsc-gen-exe-analyzer-manager-local/v1"
analyzerManagerDirName = "analyzerManager"
Expand Down
51 changes: 26 additions & 25 deletions xray/utils/resultstable.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,23 +302,23 @@ func PrepareSecrets(secrets []*sarif.Run) []formats.SourceCodeRow {
func prepareSecrets(secrets []*sarif.Run, isTable bool) []formats.SourceCodeRow {
var secretsRows []formats.SourceCodeRow
for _, secretRun := range secrets {
for _, secret := range secretRun.Results {
currSeverity := GetSeverity(GetResultSeverity(secret), Applicable)
for _, location := range secret.Locations {
for _, secretResult := range secretRun.Results {
currSeverity := GetSeverity(GetResultSeverity(secretResult), Applicable)
for _, location := range secretResult.Locations {
secretsRows = append(secretsRows,
formats.SourceCodeRow{
Severity: currSeverity.printableTitle(isTable),
Finding: GetResultMsgText(secret),
Finding: GetResultMsgText(secretResult),
SeverityNumValue: currSeverity.numValue,
Location: formats.Location{
File: GetLocationFileName(location),
File: getRelativeLocationFileName(location, secretRun.Invocations),
StartLine: GetLocationStartLine(location),
StartColumn: GetLocationStartColumn(location),
EndLine: GetLocationEndLine(location),
EndColumn: GetLocationEndColumn(location),
Snippet: GetLocationSnippet(location),
},
Type: *secret.RuleID,
Type: *secretResult.RuleID,
},
)
}
Expand Down Expand Up @@ -350,28 +350,28 @@ func PrepareIacs(iacs []*sarif.Run) []formats.SourceCodeRow {
func prepareIacs(iacs []*sarif.Run, isTable bool) []formats.SourceCodeRow {
var iacRows []formats.SourceCodeRow
for _, iacRun := range iacs {
for _, iac := range iacRun.Results {
for _, iacResult := range iacRun.Results {
scannerDescription := ""
if rule, err := iacRun.GetRuleById(*iac.RuleID); err == nil {
if rule, err := iacRun.GetRuleById(*iacResult.RuleID); err == nil {
scannerDescription = GetRuleFullDescription(rule)
}
currSeverity := GetSeverity(GetResultSeverity(iac), Applicable)
for _, location := range iac.Locations {
currSeverity := GetSeverity(GetResultSeverity(iacResult), Applicable)
for _, location := range iacResult.Locations {
iacRows = append(iacRows,
formats.SourceCodeRow{
Severity: currSeverity.printableTitle(isTable),
Finding: GetResultMsgText(iac),
Finding: GetResultMsgText(iacResult),
ScannerDescription: scannerDescription,
SeverityNumValue: currSeverity.numValue,
Location: formats.Location{
File: GetLocationFileName(location),
File: getRelativeLocationFileName(location, iacRun.Invocations),
StartLine: GetLocationStartLine(location),
StartColumn: GetLocationStartColumn(location),
EndLine: GetLocationEndLine(location),
EndColumn: GetLocationEndColumn(location),
Snippet: GetLocationSnippet(location),
},
Type: *iac.RuleID,
Type: *iacResult.RuleID,
},
)
}
Expand Down Expand Up @@ -402,30 +402,31 @@ func PrepareSast(sasts []*sarif.Run) []formats.SourceCodeRow {
func prepareSast(sasts []*sarif.Run, isTable bool) []formats.SourceCodeRow {
var sastRows []formats.SourceCodeRow
for _, sastRun := range sasts {
for _, sast := range sastRun.Results {
for _, sastResult := range sastRun.Results {
scannerDescription := ""
if rule, err := sastRun.GetRuleById(*sast.RuleID); err == nil {
if rule, err := sastRun.GetRuleById(*sastResult.RuleID); err == nil {
scannerDescription = GetRuleFullDescription(rule)
}
currSeverity := GetSeverity(GetResultSeverity(sast), Applicable)
flows := toSourceCodeCodeFlowRow(sast.CodeFlows, isTable)
for _, location := range sast.Locations {
currSeverity := GetSeverity(GetResultSeverity(sastResult), Applicable)

for _, location := range sastResult.Locations {
codeFlows := GetLocationRelatedCodeFlowsFromResult(location, sastResult)
sastRows = append(sastRows,
formats.SourceCodeRow{
Severity: currSeverity.printableTitle(isTable),
Finding: GetResultMsgText(sast),
Finding: GetResultMsgText(sastResult),
ScannerDescription: scannerDescription,
SeverityNumValue: currSeverity.numValue,
Location: formats.Location{
File: GetLocationFileName(location),
File: getRelativeLocationFileName(location, sastRun.Invocations),
StartLine: GetLocationStartLine(location),
StartColumn: GetLocationStartColumn(location),
EndLine: GetLocationEndLine(location),
EndColumn: GetLocationEndColumn(location),
Snippet: GetLocationSnippet(location),
},
Type: *sast.RuleID,
CodeFlow: flows,
Type: *sastResult.RuleID,
CodeFlow: codeFlowToLocationFlow(codeFlows, sastRun.Invocations, isTable),
},
)
}
Expand All @@ -439,7 +440,7 @@ func prepareSast(sasts []*sarif.Run, isTable bool) []formats.SourceCodeRow {
return sastRows
}

func toSourceCodeCodeFlowRow(flows []*sarif.CodeFlow, isTable bool) (flowRows [][]formats.Location) {
func codeFlowToLocationFlow(flows []*sarif.CodeFlow, invocations []*sarif.Invocation, isTable bool) (flowRows [][]formats.Location) {
if isTable {
// Not displaying in table
return
Expand All @@ -449,7 +450,7 @@ func toSourceCodeCodeFlowRow(flows []*sarif.CodeFlow, isTable bool) (flowRows []
rowFlow := []formats.Location{}
for _, stackTraceEntry := range stackTrace.Locations {
rowFlow = append(rowFlow, formats.Location{
File: GetLocationFileName(stackTraceEntry.Location),
File: getRelativeLocationFileName(stackTraceEntry.Location, invocations),
StartLine: GetLocationStartLine(stackTraceEntry.Location),
StartColumn: GetLocationStartColumn(stackTraceEntry.Location),
EndLine: GetLocationEndLine(stackTraceEntry.Location),
Expand Down Expand Up @@ -979,7 +980,7 @@ func getCveApplicability(cve formats.CveRow, applicabilityScanResults []*sarif.R
for _, location := range foundResult.Locations {
applicability.Evidence = append(applicability.Evidence, formats.Evidence{
Location: formats.Location{
File: GetLocationFileName(location),
File: getRelativeLocationFileName(location, applicabilityRun.Invocations),
StartLine: GetLocationStartLine(location),
StartColumn: GetLocationStartColumn(location),
EndLine: GetLocationEndLine(location),
Expand Down
32 changes: 0 additions & 32 deletions xray/utils/resultwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,50 +92,18 @@ func printScanResultsTables(results *ExtendedScanResults, isBinaryScan, includeV
return
}
}
ConvertRunsPathsToRelative(results.SecretsScanResults)
if err = PrintSecretsTable(results.SecretsScanResults, results.EntitledForJas); err != nil {
return
}
ConvertRunsPathsToRelative(results.IacScanResults)
if err = PrintIacTable(results.IacScanResults, results.EntitledForJas); err != nil {
return
}
if !IsSastSupported() {
return
}
ConvertRunsPathsToRelative(results.SastScanResults)
return PrintSastTable(results.SastScanResults, results.EntitledForJas)
}

// The paths at Sarif runs are absolute.
// Use this method if you need to translate the file paths to relative
func ConvertRunsPathsToRelative(runs []*sarif.Run) {
for _, sarifRun := range runs {
for _, invocation := range sarifRun.Invocations {
if wd := GetInvocationWorkingDirectory(invocation); len(wd) > 0 {
ConvertRunPathsToRelative(sarifRun, wd)
}
}
}
}

func ConvertRunPathsToRelative(sarifRun *sarif.Run, wd string) {
for _, sarifResult := range sarifRun.Results {
// Convert paths in locations
for _, location := range sarifResult.Locations {
SetLocationFileName(location, ExtractRelativePath(GetLocationFileName(location), wd))
}
// Convert paths in code flows
for _, codeFlows := range sarifResult.CodeFlows {
for _, threadFlows := range codeFlows.ThreadFlows {
for _, location := range threadFlows.Locations {
SetLocationFileName(location.Location, ExtractRelativePath(GetLocationFileName(location.Location), wd))
}
}
}
}
}

func printMessages(messages []string) {
if len(messages) > 0 {
log.Output()
Expand Down
81 changes: 14 additions & 67 deletions xray/utils/sarifutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"strconv"
"strings"

"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/owenrumney/go-sarif/v2/sarif"
)
Expand Down Expand Up @@ -128,36 +127,6 @@ func GetDiffFromRun(sources []*sarif.Run, targets []*sarif.Run) (runWithNewOnly
return
}

// Calculate new information that exists at the result and not at the source
func GetDiffFromResult(result *sarif.Result, source *sarif.Result) *sarif.Result {
newLocations := datastructures.MakeSet[*sarif.Location]()
newCodeFlows := []*sarif.CodeFlow{}
for _, targetLocation := range result.Locations {
if !IsLocationInResult(targetLocation, source) {
newLocations.Add(targetLocation)
newCodeFlows = append(newCodeFlows, GetLocationRelatedCodeFlowsFromResult(targetLocation, result)...)
continue
}
// Location in result, compare related code flows
for _, targetCodeFlow := range GetLocationRelatedCodeFlowsFromResult(targetLocation, result) {
for _, sourceCodeFlow := range GetLocationRelatedCodeFlowsFromResult(targetLocation, source) {
if !IsSameCodeFlow(targetCodeFlow, sourceCodeFlow) {
// Code flow does not exist at source, add it and it's related location
newLocations.Add(targetLocation)
newCodeFlows = append(newCodeFlows, targetCodeFlow)
}
}
}
}
// Create the result only with new information
return sarif.NewRuleResult(*result.RuleID).
WithKind(*result.Kind).
WithMessage(&result.Message).
WithLevel(*result.Level).
WithLocations(newLocations.ToSlice()).
WithCodeFlows(newCodeFlows)
}

func FilterResultsByRuleIdAndMsgText(source []*sarif.Result, ruleId, msgText string) (results []*sarif.Result) {
for _, result := range source {
if ruleId == *result.RuleID && msgText == GetResultMsgText(result) {
Expand All @@ -172,49 +141,15 @@ func GetLocationRelatedCodeFlowsFromResult(location *sarif.Location, result *sar
for _, stackTrace := range codeFlow.ThreadFlows {
// The threadFlow is reverse stack trace.
// The last location is the location that it relates to.
if IsSameLocation(location, stackTrace.Locations[len(stackTrace.Locations)-1].Location) {
if isSameLocation(location, stackTrace.Locations[len(stackTrace.Locations)-1].Location) {
codeFlows = append(codeFlows, codeFlow)
}
}
}
return
}

func IsSameCodeFlow(codeFlow *sarif.CodeFlow, other *sarif.CodeFlow) bool {
if len(codeFlow.ThreadFlows) != len(other.ThreadFlows) {
return false
}
// ThreadFlows is unordered list of stack trace
for _, stackTrace := range codeFlow.ThreadFlows {
foundMatch := false
for _, otherStackTrace := range other.ThreadFlows {
if len(stackTrace.Locations) != len(otherStackTrace.Locations) {
continue
}
for i, stackTraceLocation := range stackTrace.Locations {
if !IsSameLocation(stackTraceLocation.Location, otherStackTrace.Locations[i].Location) {
continue
}
}
foundMatch = true
}
if !foundMatch {
return false
}
}
return true
}

func IsLocationInResult(location *sarif.Location, result *sarif.Result) bool {
for _, resultLocation := range result.Locations {
if IsSameLocation(location, resultLocation) {
return true
}
}
return false
}

func IsSameLocation(location *sarif.Location, other *sarif.Location) bool {
func isSameLocation(location *sarif.Location, other *sarif.Location) bool {
if location == other {
return true
}
Expand Down Expand Up @@ -290,6 +225,18 @@ func GetLocationFileName(location *sarif.Location) string {
return ""
}

func getRelativeLocationFileName(location *sarif.Location, invocations []*sarif.Invocation) string {
wd := ""
if len(invocations) > 0 {
wd = GetInvocationWorkingDirectory(invocations[0])
}
filePath := location.PhysicalLocation.ArtifactLocation.URI
sverdlov93 marked this conversation as resolved.
Show resolved Hide resolved
if filePath != nil {
return ExtractRelativePath(*filePath, wd)
}
return ""
}

func SetLocationFileName(location *sarif.Location, fileName string) {
if location != nil && location.PhysicalLocation != nil && location.PhysicalLocation.Region != nil && location.PhysicalLocation.Region.Snippet != nil {
location.PhysicalLocation.ArtifactLocation.URI = &fileName
Expand Down