Skip to content

Commit 80d5c27

Browse files
authored
Improve pull request comment and code scanning view (#228)
1 parent b2fabc2 commit 80d5c27

14 files changed

+195
-318
lines changed

commands/createfixpullrequests.go

+15-17
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,19 @@ func (cfp *CreateFixPullRequestsCmd) scanAndFixRepository(repoConfig *utils.Frog
6060
for projectIndex, project := range repoConfig.Projects {
6161
projectFullPathWorkingDirs := getFullPathWorkingDirs(&repoConfig.Projects[projectIndex], baseWd)
6262
for _, fullPathWd := range projectFullPathWorkingDirs {
63-
scanResults, err := cfp.scan(project, &repoConfig.Server, xrayScanParams, *repoConfig.FailOnSecurityIssues, fullPathWd)
63+
scanResults, isMultipleRoots, err := cfp.scan(project, &repoConfig.Server, xrayScanParams, *repoConfig.FailOnSecurityIssues, fullPathWd)
6464
if err != nil {
6565
return err
6666
}
6767

68-
// Upload scan results to the relevant Git provider code scanning UI
69-
scanResults = utils.SimplifyScanResults(scanResults)
70-
err = utils.UploadScanToGitProvider(scanResults, repoConfig, branch, client)
68+
err = utils.UploadScanToGitProvider(scanResults, repoConfig, branch, client, isMultipleRoots)
7169
if err != nil {
7270
log.Warn(err)
7371
}
7472

7573
// Fix and create PRs
7674
relativeCurrentWd := utils.GetRelativeWd(fullPathWd, baseWd)
77-
if err = cfp.fixImpactedPackagesAndCreatePRs(project, &repoConfig.Git, branch, client, scanResults, relativeCurrentWd); err != nil {
75+
if err = cfp.fixImpactedPackagesAndCreatePRs(project, &repoConfig.Git, branch, client, scanResults, relativeCurrentWd, isMultipleRoots); err != nil {
7876
return err
7977
}
8078
}
@@ -84,19 +82,19 @@ func (cfp *CreateFixPullRequestsCmd) scanAndFixRepository(repoConfig *utils.Frog
8482

8583
// Audit the dependencies of the current commit.
8684
func (cfp *CreateFixPullRequestsCmd) scan(project utils.Project, server *coreconfig.ServerDetails, xrayScanParams services.XrayGraphScanParams,
87-
failOnSecurityIssues bool, currentWorkingDir string) ([]services.ScanResponse, error) {
85+
failOnSecurityIssues bool, currentWorkingDir string) ([]services.ScanResponse, bool, error) {
8886
// Audit commit code
89-
scanResults, err := runInstallAndAudit(xrayScanParams, &project, server, failOnSecurityIssues, currentWorkingDir)
87+
scanResults, isMultipleRoots, err := runInstallAndAudit(xrayScanParams, &project, server, failOnSecurityIssues, currentWorkingDir)
9088
if err != nil {
91-
return nil, err
89+
return nil, false, err
9290
}
9391
log.Info("Xray scan completed")
94-
return scanResults, nil
92+
return scanResults, isMultipleRoots, nil
9593
}
9694

9795
func (cfp *CreateFixPullRequestsCmd) fixImpactedPackagesAndCreatePRs(project utils.Project, repoGitParams *utils.Git, branch string,
98-
client vcsclient.VcsClient, scanResults []services.ScanResponse, currentWd string) (err error) {
99-
fixVersionsMap, err := cfp.createFixVersionsMap(&project, scanResults)
96+
client vcsclient.VcsClient, scanResults []services.ScanResponse, currentWd string, isMultipleRoots bool) (err error) {
97+
fixVersionsMap, err := cfp.createFixVersionsMap(&project, scanResults, isMultipleRoots)
10098
if err != nil {
10199
return err
102100
}
@@ -163,11 +161,11 @@ func (cfp *CreateFixPullRequestsCmd) fixImpactedPackagesAndCreatePRs(project uti
163161
}
164162

165163
// Create fixVersionMap - a map between impacted packages and their fix version
166-
func (cfp *CreateFixPullRequestsCmd) createFixVersionsMap(project *utils.Project, scanResults []services.ScanResponse) (map[string]*FixVersionInfo, error) {
164+
func (cfp *CreateFixPullRequestsCmd) createFixVersionsMap(project *utils.Project, scanResults []services.ScanResponse, isMultipleRoots bool) (map[string]*FixVersionInfo, error) {
167165
fixVersionsMap := map[string]*FixVersionInfo{}
168166
for _, scanResult := range scanResults {
169167
if len(scanResult.Vulnerabilities) > 0 {
170-
vulnerabilities, err := xrayutils.PrepareVulnerabilities(scanResult.Vulnerabilities, false)
168+
vulnerabilities, err := xrayutils.PrepareVulnerabilities(scanResult.Vulnerabilities, isMultipleRoots, true)
171169
if err != nil {
172170
return nil, err
173171
}
@@ -180,19 +178,19 @@ func (cfp *CreateFixPullRequestsCmd) createFixVersionsMap(project *utils.Project
180178
if !fixVulnerability {
181179
continue
182180
}
183-
vulnFixVersion := getMinimalFixVersion(vulnerability.ImpactedPackageVersion, vulnerability.FixedVersions)
181+
vulnFixVersion := getMinimalFixVersion(vulnerability.ImpactedDependencyVersion, vulnerability.FixedVersions)
184182
if vulnFixVersion == "" {
185183
continue
186184
}
187185

188-
fixVersionInfo, exists := fixVersionsMap[vulnerability.ImpactedPackageName]
186+
fixVersionInfo, exists := fixVersionsMap[vulnerability.ImpactedDependencyName]
189187
if exists {
190188
// More than one vulnerability can exist on the same impacted package.
191189
// Among all possible fix versions that fix the above impacted package, we select the maximum fix version.
192190
fixVersionInfo.UpdateFixVersion(vulnFixVersion)
193191
} else {
194192
// First appearance of a version that fixes the current impacted package
195-
fixVersionsMap[vulnerability.ImpactedPackageName] = NewFixVersionInfo(vulnFixVersion, vulnerability.Technology)
193+
fixVersionsMap[vulnerability.ImpactedDependencyName] = NewFixVersionInfo(vulnFixVersion, vulnerability.Technology)
196194
}
197195
}
198196
}
@@ -231,7 +229,7 @@ func (cfp *CreateFixPullRequestsCmd) shouldFixVulnerability(project *utils.Proje
231229
}
232230
}
233231
}
234-
if _, exist := cfp.mavenDepToPropertyMap[vulnerability.ImpactedPackageName]; !exist {
232+
if _, exist := cfp.mavenDepToPropertyMap[vulnerability.ImpactedDependencyName]; !exist {
235233
return false, nil
236234
}
237235
}

commands/createfixpullrequests_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ func getTestDataDir(t *testing.T) (string, string) {
110110
return currentDir, testdataDir
111111
}
112112

113-
/// 1.0 --> 1.0 ≤ x
114-
/// (,1.0] --> x ≤ 1.0
115-
/// (,1.0) --> x < 1.0
116-
/// [1.0] --> x == 1.0
117-
/// (1.0,) --> 1.0 < x
118-
/// (1.0, 2.0) --> 1.0 < x < 2.0
119-
/// [1.0, 2.0] --> 1.0 ≤ x ≤ 2.0
113+
// / 1.0 --> 1.0 ≤ x
114+
// / (,1.0] --> x ≤ 1.0
115+
// / (,1.0) --> x < 1.0
116+
// / [1.0] --> x == 1.0
117+
// / (1.0,) --> 1.0 < x
118+
// / (1.0, 2.0) --> 1.0 < x < 2.0
119+
// / [1.0, 2.0] --> 1.0 ≤ x ≤ 2.0
120120
func TestParseVersionChangeString(t *testing.T) {
121121
tests := []struct {
122122
versionChangeString string
@@ -184,7 +184,7 @@ func TestPackageTypeFromScan(t *testing.T) {
184184
projectPath := filepath.Join("testdata", "projects", pkgType.ToString())
185185
t.Run(pkgType.ToString(), func(t *testing.T) {
186186
frogbotParams.Projects[0].WorkingDirs = []string{projectPath}
187-
scanResponse, err := testScan.scan(frogbotParams.Projects[0], &frogbotParams.Server, services.XrayGraphScanParams{}, false, projectPath)
187+
scanResponse, _, err := testScan.scan(frogbotParams.Projects[0], &frogbotParams.Server, services.XrayGraphScanParams{}, false, projectPath)
188188
assert.NoError(t, err)
189189
verifyTechnologyNaming(t, scanResponse, pkgType)
190190
})

commands/scanpullrequest.go

+57-53
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,29 @@ func scanPullRequest(repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsCl
5959
xrayScanParams := createXrayScanParams(repoConfig.Watches, repoConfig.JFrogProjectKey)
6060
var vulnerabilitiesRows []formats.VulnerabilityOrViolationRow
6161
for _, project := range repoConfig.Projects {
62-
currentScan, err := auditSource(xrayScanParams, project, &repoConfig.Server)
62+
currentScan, isMultipleRoot, err := auditSource(xrayScanParams, project, &repoConfig.Server)
6363
if err != nil {
6464
return err
6565
}
6666
if repoConfig.IncludeAllVulnerabilities {
6767
log.Info("Frogbot is configured to show all vulnerabilities")
68-
allIssuesRows, err := createAllIssuesRows(currentScan)
68+
allIssuesRows, err := createAllIssuesRows(currentScan, isMultipleRoot)
6969
if err != nil {
7070
return err
7171
}
7272
vulnerabilitiesRows = append(vulnerabilitiesRows, allIssuesRows...)
73-
} else {
74-
// Audit target code
75-
previousScan, err := auditTarget(client, xrayScanParams, project, repoConfig.Branches[0], &repoConfig.Git, &repoConfig.Server)
76-
if err != nil {
77-
return err
78-
}
79-
newIssuesRows, err := createNewIssuesRows(previousScan, currentScan)
80-
if err != nil {
81-
return err
82-
}
83-
vulnerabilitiesRows = append(vulnerabilitiesRows, newIssuesRows...)
73+
continue
74+
}
75+
// Audit target code
76+
previousScan, isMultipleRoot, err := auditTarget(client, xrayScanParams, project, repoConfig.Branches[0], &repoConfig.Git, &repoConfig.Server)
77+
if err != nil {
78+
return err
79+
}
80+
newIssuesRows, err := createNewIssuesRows(previousScan, currentScan, isMultipleRoot)
81+
if err != nil {
82+
return err
8483
}
84+
vulnerabilitiesRows = append(vulnerabilitiesRows, newIssuesRows...)
8585
}
8686

8787
log.Info("Xray scan completed")
@@ -142,18 +142,18 @@ func getCommentFunctions(simplifiedOutput bool) (utils.GetTitleFunc, utils.GetSe
142142
}
143143

144144
// Create vulnerabilities rows. The rows should contain only the new issues added by this PR
145-
func createNewIssuesRows(previousScan, currentScan []services.ScanResponse) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) {
145+
func createNewIssuesRows(previousScan, currentScan []services.ScanResponse, isMultipleRoot bool) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) {
146146
previousScanAggregatedResults := aggregateScanResults(previousScan)
147147
currentScanAggregatedResults := aggregateScanResults(currentScan)
148148

149149
if len(currentScanAggregatedResults.Violations) > 0 {
150-
newViolations, err := getNewViolations(previousScanAggregatedResults, currentScanAggregatedResults)
150+
newViolations, err := getNewViolations(previousScanAggregatedResults, currentScanAggregatedResults, isMultipleRoot)
151151
if err != nil {
152152
return vulnerabilitiesRows, err
153153
}
154154
vulnerabilitiesRows = append(vulnerabilitiesRows, newViolations...)
155155
} else if len(currentScanAggregatedResults.Vulnerabilities) > 0 {
156-
newVulnerabilities, err := getNewVulnerabilities(previousScanAggregatedResults, currentScanAggregatedResults)
156+
newVulnerabilities, err := getNewVulnerabilities(previousScanAggregatedResults, currentScanAggregatedResults, isMultipleRoot)
157157
if err != nil {
158158
return vulnerabilitiesRows, err
159159
}
@@ -175,28 +175,22 @@ func aggregateScanResults(scanResults []services.ScanResponse) services.ScanResp
175175
return aggregateResults
176176
}
177177

178-
// Create vulnerabilities rows. The rows should contain All the issues that were found in this module scan.
179-
func getScanVulnerabilitiesRows(currentScan services.ScanResponse) ([]formats.VulnerabilityOrViolationRow, error) {
180-
if len(currentScan.Violations) > 0 {
181-
violationsRows, _, _, err := xrayutils.PrepareViolations(currentScan.Violations, false)
178+
// Create vulnerabilities rows. The rows should contain all the issues that were found in this module scan.
179+
func getScanVulnerabilitiesRows(violations []services.Violation, vulnerabilities []services.Vulnerability, isMultipleRoot bool) ([]formats.VulnerabilityOrViolationRow, error) {
180+
if len(violations) > 0 {
181+
violationsRows, _, _, err := xrayutils.PrepareViolations(violations, isMultipleRoot, true)
182182
return violationsRows, err
183-
} else if len(currentScan.Vulnerabilities) > 0 {
184-
return xrayutils.PrepareVulnerabilities(currentScan.Vulnerabilities, false)
183+
}
184+
if len(vulnerabilities) > 0 {
185+
return xrayutils.PrepareVulnerabilities(vulnerabilities, isMultipleRoot, true)
185186
}
186187
return []formats.VulnerabilityOrViolationRow{}, nil
187188
}
188189

189-
// Create vulnerabilities rows. The rows should contain All the issues that were found in this PR
190-
func createAllIssuesRows(currentScan []services.ScanResponse) ([]formats.VulnerabilityOrViolationRow, error) {
191-
var vulnerabilitiesRows []formats.VulnerabilityOrViolationRow
192-
for i := 0; i < len(currentScan); i += 1 {
193-
newVulnerabilitiesRows, err := getScanVulnerabilitiesRows(currentScan[i])
194-
if err != nil {
195-
return vulnerabilitiesRows, err
196-
}
197-
vulnerabilitiesRows = append(vulnerabilitiesRows, newVulnerabilitiesRows...)
198-
}
199-
return vulnerabilitiesRows, nil
190+
// Create vulnerabilities rows. The rows should contain all the issues that were found in this PR
191+
func createAllIssuesRows(currentScan []services.ScanResponse, isMultipleRoot bool) ([]formats.VulnerabilityOrViolationRow, error) {
192+
violations, vulnerabilities, _ := xrayutils.SplitScanResults(currentScan)
193+
return getScanVulnerabilitiesRows(violations, vulnerabilities, isMultipleRoot)
200194
}
201195

202196
func createXrayScanParams(watches []string, project string) (params services.XrayGraphScanParams) {
@@ -215,10 +209,10 @@ func createXrayScanParams(watches []string, project string) (params services.Xra
215209
return
216210
}
217211

218-
func auditSource(xrayScanParams services.XrayGraphScanParams, project utils.Project, server *coreconfig.ServerDetails) ([]services.ScanResponse, error) {
212+
func auditSource(xrayScanParams services.XrayGraphScanParams, project utils.Project, server *coreconfig.ServerDetails) ([]services.ScanResponse, bool, error) {
219213
wd, err := os.Getwd()
220214
if err != nil {
221-
return []services.ScanResponse{}, err
215+
return []services.ScanResponse{}, false, err
222216
}
223217
fullPathWds := getFullPathWorkingDirs(&project, wd)
224218
return runInstallAndAudit(xrayScanParams, &project, server, true, fullPathWds...)
@@ -240,7 +234,7 @@ func getFullPathWorkingDirs(project *utils.Project, baseWd string) []string {
240234
return fullPathWds
241235
}
242236

243-
func auditTarget(client vcsclient.VcsClient, xrayScanParams services.XrayGraphScanParams, project utils.Project, branch string, git *utils.Git, server *coreconfig.ServerDetails) (res []services.ScanResponse, err error) {
237+
func auditTarget(client vcsclient.VcsClient, xrayScanParams services.XrayGraphScanParams, project utils.Project, branch string, git *utils.Git, server *coreconfig.ServerDetails) (res []services.ScanResponse, isMultipleRoot bool, err error) {
244238
// First download the target repo to temp dir
245239
log.Info("Auditing " + git.RepoName + " " + branch)
246240
wd, cleanup, err := utils.DownloadRepoToTempDir(client, branch, git)
@@ -258,19 +252,19 @@ func auditTarget(client vcsclient.VcsClient, xrayScanParams services.XrayGraphSc
258252
return runInstallAndAudit(xrayScanParams, &project, server, false, fullPathWds...)
259253
}
260254

261-
func runInstallAndAudit(xrayScanParams services.XrayGraphScanParams, project *utils.Project, server *coreconfig.ServerDetails, failOnInstallationErrors bool, workDirs ...string) (results []services.ScanResponse, err error) {
255+
func runInstallAndAudit(xrayScanParams services.XrayGraphScanParams, project *utils.Project, server *coreconfig.ServerDetails, failOnInstallationErrors bool, workDirs ...string) (results []services.ScanResponse, isMultipleRoot bool, err error) {
262256
for _, wd := range workDirs {
263257
if err = runInstallIfNeeded(project, wd, failOnInstallationErrors); err != nil {
264-
return nil, err
258+
return nil, false, err
265259
}
266260
}
267261

268-
results, _, err = audit.GenericAudit(xrayScanParams, server, false, project.UseWrapper, false,
262+
results, isMultipleRoot, err = audit.GenericAudit(xrayScanParams, server, false, project.UseWrapper, false,
269263
nil, nil, project.PipRequirementsFile, false, workDirs, []string{}...)
270264
if err != nil {
271-
return nil, err
265+
return nil, false, err
272266
}
273-
return results, err
267+
return results, isMultipleRoot, err
274268
}
275269

276270
func runInstallIfNeeded(project *utils.Project, workDir string, failOnInstallationErrors bool) (err error) {
@@ -297,16 +291,16 @@ func runInstallIfNeeded(project *utils.Project, workDir string, failOnInstallati
297291
return
298292
}
299293

300-
func getNewViolations(previousScan, currentScan services.ScanResponse) (newViolationsRows []formats.VulnerabilityOrViolationRow, err error) {
294+
func getNewViolations(previousScan, currentScan services.ScanResponse, isMultipleRoot bool) (newViolationsRows []formats.VulnerabilityOrViolationRow, err error) {
301295
existsViolationsMap := make(map[string]formats.VulnerabilityOrViolationRow)
302-
violationsRows, _, _, err := xrayutils.PrepareViolations(previousScan.Violations, false)
296+
violationsRows, _, _, err := xrayutils.PrepareViolations(previousScan.Violations, isMultipleRoot, true)
303297
if err != nil {
304298
return violationsRows, err
305299
}
306300
for _, violation := range violationsRows {
307301
existsViolationsMap[getUniqueID(violation)] = violation
308302
}
309-
violationsRows, _, _, err = xrayutils.PrepareViolations(currentScan.Violations, false)
303+
violationsRows, _, _, err = xrayutils.PrepareViolations(currentScan.Violations, isMultipleRoot, true)
310304
if err != nil {
311305
return newViolationsRows, err
312306
}
@@ -318,16 +312,16 @@ func getNewViolations(previousScan, currentScan services.ScanResponse) (newViola
318312
return
319313
}
320314

321-
func getNewVulnerabilities(previousScan, currentScan services.ScanResponse) (newVulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) {
315+
func getNewVulnerabilities(previousScan, currentScan services.ScanResponse, isMultipleRoot bool) (newVulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) {
322316
existsVulnerabilitiesMap := make(map[string]formats.VulnerabilityOrViolationRow)
323-
vulnerabilitiesRows, err := xrayutils.PrepareVulnerabilities(previousScan.Vulnerabilities, false)
317+
vulnerabilitiesRows, err := xrayutils.PrepareVulnerabilities(previousScan.Vulnerabilities, isMultipleRoot, true)
324318
if err != nil {
325319
return newVulnerabilitiesRows, err
326320
}
327321
for _, vulnerability := range vulnerabilitiesRows {
328322
existsVulnerabilitiesMap[getUniqueID(vulnerability)] = vulnerability
329323
}
330-
vulnerabilitiesRows, err = xrayutils.PrepareVulnerabilities(currentScan.Vulnerabilities, false)
324+
vulnerabilitiesRows, err = xrayutils.PrepareVulnerabilities(currentScan.Vulnerabilities, isMultipleRoot, true)
331325
if err != nil {
332326
return newVulnerabilitiesRows, err
333327
}
@@ -340,7 +334,7 @@ func getNewVulnerabilities(previousScan, currentScan services.ScanResponse) (new
340334
}
341335

342336
func getUniqueID(vulnerability formats.VulnerabilityOrViolationRow) string {
343-
return vulnerability.ImpactedPackageName + vulnerability.ImpactedPackageVersion + vulnerability.IssueId
337+
return vulnerability.ImpactedDependencyName + vulnerability.ImpactedDependencyVersion + vulnerability.IssueId
344338
}
345339

346340
func createPullRequestMessage(vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, getBanner utils.GetTitleFunc, getSeverityTag utils.GetSeverityTagFunc) string {
@@ -349,17 +343,27 @@ func createPullRequestMessage(vulnerabilitiesRows []formats.VulnerabilityOrViola
349343
}
350344
var tableContent string
351345
for _, vulnerability := range vulnerabilitiesRows {
352-
var componentName, componentVersion, cve string
346+
var cve string
347+
var directDependencies, directDependenciesVersions strings.Builder
353348
if len(vulnerability.Components) > 0 {
354-
componentName = vulnerability.ImpactedPackageName
355-
componentVersion = vulnerability.ImpactedPackageVersion
349+
for _, dependency := range vulnerability.Components {
350+
directDependencies.WriteString(fmt.Sprintf("%s; ", dependency.Name))
351+
directDependenciesVersions.WriteString(fmt.Sprintf("%s; ", dependency.Version))
352+
}
356353
}
357354
if len(vulnerability.Cves) > 0 {
358355
cve = vulnerability.Cves[0].Id
359356
}
360357
fixedVersionString := strings.Join(vulnerability.FixedVersions, " ")
361-
tableContent += fmt.Sprintf("\n| %s%8s | %s | %s | %s | %s | %s | %s ", getSeverityTag(utils.IconName(vulnerability.Severity)), vulnerability.Severity, vulnerability.ImpactedPackageName,
362-
vulnerability.ImpactedPackageVersion, fixedVersionString, componentName, componentVersion, cve)
358+
tableContent += fmt.Sprintf("\n| %s%8s | %s | %s | %s | %s | %s | %s ",
359+
getSeverityTag(utils.IconName(vulnerability.Severity)),
360+
vulnerability.Severity,
361+
strings.TrimSuffix(directDependencies.String(), "; "),
362+
strings.TrimSuffix(directDependenciesVersions.String(), "; "),
363+
vulnerability.ImpactedDependencyName,
364+
vulnerability.ImpactedDependencyVersion,
365+
fixedVersionString,
366+
cve)
363367
}
364368
return getBanner(utils.VulnerabilitiesBannerSource) + utils.WhatIsFrogbotMd + utils.TableHeader + tableContent
365369
}

0 commit comments

Comments
 (0)