Skip to content

Commit

Permalink
indirect-cve-whitelist added to the Applicability Scaner YAML confi…
Browse files Browse the repository at this point in the history
…guration (jfrog#1049)
  • Loading branch information
srmish-jfrog authored and guyshe-jfrog committed Nov 30, 2023
1 parent 5baf0b8 commit 8f30a0a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 46 deletions.
73 changes: 39 additions & 34 deletions xray/commands/audit/jas/applicability/applicabilitymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
type ApplicabilityScanManager struct {
applicabilityScanResults []*sarif.Run
directDependenciesCves []string
indirectDependenciesCves []string
xrayResults []services.ScanResponse
scanner *jas.JasScanner
thirdPartyScan bool
Expand Down Expand Up @@ -88,43 +89,49 @@ func newApplicabilityScanManagerCves(xrayScanResults []services.ScanResponse, cv
}

func newApplicabilityScanManager(xrayScanResults []services.ScanResponse, directDependencies []string, scanner *jas.JasScanner, thirdPartyScan bool) (manager *ApplicabilityScanManager) {
directDependenciesCves := extractDirectDependenciesCvesFromScan(xrayScanResults, directDependencies)
directDependenciesCves, indirectDependenciesCves := extractDependenciesCvesFromScan(xrayScanResults, directDependencies)
return &ApplicabilityScanManager{
applicabilityScanResults: []*sarif.Run{},
directDependenciesCves: directDependenciesCves,
indirectDependenciesCves: indirectDependenciesCves,
xrayResults: xrayScanResults,
scanner: scanner,
thirdPartyScan: thirdPartyScan,
commandType: applicabilityScanType,
}
}

// This function gets a list of xray scan responses that contain direct and indirect vulnerabilities and returns only direct
// vulnerabilities of the scanned project, ignoring indirect vulnerabilities
func extractDirectDependenciesCvesFromScan(xrayScanResults []services.ScanResponse, directDependencies []string) []string {
directsCves := datastructures.MakeSet[string]()
func addCvesToSet(cves []services.Cve, set *datastructures.Set[string]) {
for _, cve := range cves {
if cve.Id != "" {
set.Add(cve.Id)
}
}
}

// This function gets a list of xray scan responses that contain direct and indirect vulnerabilities and returns separate
// lists of the direct and indirect CVEs
func extractDependenciesCvesFromScan(xrayScanResults []services.ScanResponse, directDependencies []string) (directCves []string, indirectCves []string) {
directCvesSet := datastructures.MakeSet[string]()
indirectCvesSet := datastructures.MakeSet[string]()
for _, scanResult := range xrayScanResults {
for _, vulnerability := range scanResult.Vulnerabilities {
if isDirectComponents(maps.Keys(vulnerability.Components), directDependencies) {
for _, cve := range vulnerability.Cves {
if cve.Id != "" {
directsCves.Add(cve.Id)
}
}
addCvesToSet(vulnerability.Cves, directCvesSet)
} else {
addCvesToSet(vulnerability.Cves, indirectCvesSet)
}
}
for _, violation := range scanResult.Violations {
if isDirectComponents(maps.Keys(violation.Components), directDependencies) {
for _, cve := range violation.Cves {
if cve.Id != "" {
directsCves.Add(cve.Id)
}
}
addCvesToSet(violation.Cves, directCvesSet)
} else {
addCvesToSet(violation.Cves, indirectCvesSet)
}
}
}

return directsCves.ToSlice()
return directCvesSet.ToSlice(), indirectCvesSet.ToSlice()
}

func isDirectComponents(components []string, directDependencies []string) bool {
Expand Down Expand Up @@ -159,26 +166,23 @@ func (asm *ApplicabilityScanManager) Run(module jfrogappsconfig.Module) (err err
return
}

func (asm *ApplicabilityScanManager) directDependenciesExist() bool {
return len(asm.directDependenciesCves) > 0
}

func (asm *ApplicabilityScanManager) shouldRunApplicabilityScan(technologies []coreutils.Technology) bool {
return asm.directDependenciesExist() && coreutils.ContainsApplicabilityScannableTech(technologies)
return coreutils.ContainsApplicabilityScannableTech(technologies)
}

type applicabilityScanConfig struct {
Scans []scanConfiguration `yaml:"scans"`
}

type scanConfiguration struct {
Roots []string `yaml:"roots"`
Output string `yaml:"output"`
Type string `yaml:"type"`
GrepDisable bool `yaml:"grep-disable"`
CveWhitelist []string `yaml:"cve-whitelist"`
SkippedDirs []string `yaml:"skipped-folders"`
ScanType string `yaml:"scantype"`
Roots []string `yaml:"roots"`
Output string `yaml:"output"`
Type string `yaml:"type"`
GrepDisable bool `yaml:"grep-disable"`
CveWhitelist []string `yaml:"cve-whitelist"`
IndirectCveWhitelist []string `yaml:"indirect-cve-whitelist"`
SkippedDirs []string `yaml:"skipped-folders"`
ScanType string `yaml:"scantype"`
}

func (asm *ApplicabilityScanManager) createConfigFile(module jfrogappsconfig.Module) error {
Expand All @@ -194,12 +198,13 @@ func (asm *ApplicabilityScanManager) createConfigFile(module jfrogappsconfig.Mod
configFileContent := applicabilityScanConfig{
Scans: []scanConfiguration{
{
Roots: roots,
Output: asm.scanner.ResultsFileName,
Type: asm.commandType,
GrepDisable: false,
CveWhitelist: asm.directDependenciesCves,
SkippedDirs: excludePatterns,
Roots: roots,
Output: asm.scanner.ResultsFileName,
Type: asm.commandType,
GrepDisable: false,
CveWhitelist: asm.directDependenciesCves,
IndirectCveWhitelist: asm.indirectDependenciesCves,
SkippedDirs: excludePatterns,
},
},
}
Expand Down
35 changes: 23 additions & 12 deletions xray/commands/audit/jas/applicability/applicabilitymanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func TestApplicabilityScanManager_ShouldRun_ScanResultsAreEmpty(t *testing.T) {
applicabilityManager := newApplicabilityScanManager(nil, mockDirectDependencies, scanner, false)

// Assert
eligible := applicabilityManager.shouldRunApplicabilityScan([]coreutils.Technology{coreutils.Npm})
eligible := applicabilityManager.shouldRunApplicabilityScan([]coreutils.Technology{coreutils.Nuget})
assert.False(t, eligible)
}

Expand All @@ -188,23 +188,28 @@ func TestExtractXrayDirectViolations(t *testing.T) {
}
tests := []struct {
directDependencies []string
cvesCount int
directCvesCount int
indirectCvesCount int
}{
{directDependencies: []string{"issueId_2_direct_dependency", "issueId_1_direct_dependency"},
cvesCount: 2,
directCvesCount: 2,
indirectCvesCount: 0,
},
// Vulnerability dependency, should be ignored by function
{directDependencies: []string{"issueId_1_direct_dependency"},
cvesCount: 0,
directCvesCount: 0,
indirectCvesCount: 2,
},
{directDependencies: []string{},
cvesCount: 0,
directCvesCount: 0,
indirectCvesCount: 2,
},
}

for _, test := range tests {
cves := extractDirectDependenciesCvesFromScan(xrayResponseForDirectViolationsTest, test.directDependencies)
assert.Len(t, cves, test.cvesCount)
directCves, indirectCves := extractDependenciesCvesFromScan(xrayResponseForDirectViolationsTest, test.directDependencies)
assert.Len(t, directCves, test.directCvesCount)
assert.Len(t, indirectCves, test.indirectCvesCount)
}
}

Expand All @@ -228,23 +233,29 @@ func TestExtractXrayDirectVulnerabilities(t *testing.T) {
}
tests := []struct {
directDependencies []string
cvesCount int
directCvesCount int
indirectCvesCount int
}{
{
directDependencies: []string{"issueId_1_direct_dependency"},
cvesCount: 3,
directCvesCount: 3,
indirectCvesCount: 2,
},
{
directDependencies: []string{"issueId_2_direct_dependency"},
cvesCount: 2,
directCvesCount: 2,
indirectCvesCount: 3,
},
{directDependencies: []string{},
cvesCount: 0,
directCvesCount: 0,
indirectCvesCount: 5,
},
}

for _, test := range tests {
assert.Len(t, extractDirectDependenciesCvesFromScan(xrayResponseForDirectVulnerabilitiesTest, test.directDependencies), test.cvesCount)
directCves, indirectCves := extractDependenciesCvesFromScan(xrayResponseForDirectVulnerabilitiesTest, test.directDependencies)
assert.Len(t, directCves, test.directCvesCount)
assert.Len(t, indirectCves, test.indirectCvesCount)
}
}

Expand Down

0 comments on commit 8f30a0a

Please sign in to comment.