Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions policy/enforcer/policyenforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,11 @@
return utils.ScaScan
}

func convertToScaViolation(cmdResults *results.SecurityCommandResults, impactedComponentXrayId string, violation services.XrayViolation) (affectedComponent *cyclonedx.Component, scaViolation violationutils.ScaViolation) {

Check failure on line 192 in policy/enforcer/policyenforcer.go

View workflow job for this annotation

GitHub Actions / Static-Check

convertToScaViolation - result affectedComponent is always nil (unparam)
scaViolation = violationutils.ScaViolation{
Violation: convertToBasicViolation(getScaViolationType(violation), violation),
}
affectedComponent, scaViolation.DirectComponents, scaViolation.ImpactPaths = locateBomComponentInfo(cmdResults, impactedComponentXrayId, violation)
if affectedComponent == nil {
return
}
scaViolation.ImpactedComponent = *affectedComponent
scaViolation.ImpactedComponent, scaViolation.DirectComponents, scaViolation.ImpactPaths = locateBomComponentInfo(cmdResults, impactedComponentXrayId, violation)
return
}

Expand Down
61 changes: 49 additions & 12 deletions policy/local/localconvertor.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func getScaViolationType(violation services.Violation) violationutils.ViolationI
return ""
}

func convertToScaViolation(violation services.Violation, severity severityutils.Severity, affectedComponent cyclonedx.Component, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) violationutils.ScaViolation {
func convertToScaViolation(violation services.Violation, severity severityutils.Severity, affectedComponent *cyclonedx.Component, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) violationutils.ScaViolation {
return violationutils.ScaViolation{
Violation: convertToBasicViolation(violation, severity),
ImpactedComponent: affectedComponent,
Expand All @@ -231,8 +231,13 @@ func convertToScaViolation(violation services.Violation, severity severityutils.
func convertScaSecurityViolationToPolicyViolation(convertedViolations *violationutils.Violations) ParseScanGraphViolationFunc {
xrayService := results.GetXrayService()
return func(violation services.Violation, cves []formats.CveRow, applicabilityStatus jasutils.ApplicabilityStatus, severity severityutils.Severity, impactedPackagesId string, fixedVersion []string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) (err error) {
// Create the CycloneDX component for the impacted package
affectedComponent := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
var affectedComponent *cyclonedx.Component
var fixedVersions *[]cyclonedx.AffectedVersions
if impactedPackagesId != "" {
// Create the CycloneDX component for the impacted package
component := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
affectedComponent = &component
}
// Extract the vulnerability CVE's information and create the SCA vulnerability for each
cveIds, applicability, cwes, ratings := results.ExtractIssuesInfoForCdx(violation.IssueId, cves, severity, applicabilityStatus, xrayService)
extendedInformation := ""
Expand All @@ -250,15 +255,18 @@ func convertScaSecurityViolationToPolicyViolation(convertedViolations *violation
References: violation.References,
Service: xrayService,
})
// Attach the affected impacted library component to the vulnerability
cdxutils.AttachComponentAffects(&vulnerability, affectedComponent, func(affectedComponent cyclonedx.Component) cyclonedx.Affects {
return cdxutils.CreateScaImpactedAffects(affectedComponent, fixedVersion)
})
if affectedComponent != nil {
// Attach the affected impacted library component to the vulnerability
cdxutils.AttachComponentAffects(&vulnerability, *affectedComponent, func(affectedComponent cyclonedx.Component) cyclonedx.Affects {
return cdxutils.CreateScaImpactedAffects(affectedComponent, fixedVersion)
})
fixedVersions = cdxutils.ConvertToAffectedVersions(*affectedComponent, fixedVersion)
}
convertedViolations.Sca = append(convertedViolations.Sca, violationutils.CveViolation{
ScaViolation: convertToScaViolation(violation, severity, affectedComponent, directComponents, impactPaths),
CveVulnerability: vulnerability,
ContextualAnalysis: applicability[i],
FixedVersions: cdxutils.ConvertToAffectedVersions(affectedComponent, fixedVersion),
FixedVersions: fixedVersions,
JfrogResearchInformation: results.ConvertJfrogResearchInformation(violation.ExtendedInformation),
})
}
Expand All @@ -268,8 +276,12 @@ func convertScaSecurityViolationToPolicyViolation(convertedViolations *violation

func convertScaLicenseViolationToPolicyViolation(convertedViolations *violationutils.Violations) ParseScanGraphViolationFunc {
return func(violation services.Violation, cves []formats.CveRow, applicabilityStatus jasutils.ApplicabilityStatus, severity severityutils.Severity, impactedPackagesId string, fixedVersion []string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) (err error) {
// Create the CycloneDX component for the impacted package
affectedComponent := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
var affectedComponent *cyclonedx.Component
if impactedPackagesId != "" {
// Create the CycloneDX component for the impacted package
component := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
affectedComponent = &component
}
// Add the license violation
convertedViolations.License = append(convertedViolations.License, violationutils.LicenseViolation{
ScaViolation: convertToScaViolation(violation, severity, affectedComponent, directComponents, impactPaths),
Expand All @@ -282,8 +294,12 @@ func convertScaLicenseViolationToPolicyViolation(convertedViolations *violationu

func convertOperationalRiskViolationToPolicyViolation(convertedViolations *violationutils.Violations) ParseScanGraphViolationFunc {
return func(violation services.Violation, cves []formats.CveRow, applicabilityStatus jasutils.ApplicabilityStatus, severity severityutils.Severity, impactedPackagesId string, fixedVersion []string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) (err error) {
// Create the CycloneDX component for the impacted package
affectedComponent := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
var affectedComponent *cyclonedx.Component
if impactedPackagesId != "" {
// Create the CycloneDX component for the impacted package
component := results.CreateScaComponentFromXrayCompId(impactedPackagesId)
affectedComponent = &component
}
// Add the operational risk violation
convertedViolations.OpRisk = append(convertedViolations.OpRisk, violationutils.OperationalRiskViolation{
ScaViolation: convertToScaViolation(violation, severity, affectedComponent, directComponents, impactPaths),
Expand Down Expand Up @@ -331,6 +347,13 @@ func ForEachScanGraphViolation(target results.ScanTarget, descriptors []string,
// No handler was provided for security violations
continue
}
if len(impactedPackagesIds) == 0 {
// Security violation without any impacted packages, we pass an empty string as the impacted package ID
if e := securityHandler(violation, cves, applicabilityStatus, severity, "", []string{}, []formats.ComponentRow{}, [][]formats.ComponentRow{}); e != nil {
err = errors.Join(err, e)
continue
}
}
for compIndex := 0; compIndex < len(impactedPackagesIds); compIndex++ {
if e := securityHandler(violation, cves, applicabilityStatus, severity, impactedPackagesIds[compIndex], fixedVersions[compIndex], directComponents[compIndex], impactPaths[compIndex]); e != nil {
err = errors.Join(err, e)
Expand All @@ -342,6 +365,13 @@ func ForEachScanGraphViolation(target results.ScanTarget, descriptors []string,
// No handler was provided for license violations
continue
}
if len(impactedPackagesIds) == 0 {
// License violation without any impacted packages, we pass an empty string as the impacted package ID
if e := licenseHandler(violation, cves, applicabilityStatus, severity, "", []string{}, []formats.ComponentRow{}, [][]formats.ComponentRow{}); e != nil {
err = errors.Join(err, e)
continue
}
}
for compIndex := range impactedPackagesIds {
if impactedPackagesName, _, _ := techutils.SplitComponentId(impactedPackagesIds[compIndex]); impactedPackagesName == "root" {
// No Need to output 'root' as impacted package for license since we add this as the root node for the scan
Expand All @@ -357,6 +387,13 @@ func ForEachScanGraphViolation(target results.ScanTarget, descriptors []string,
// No handler was provided for operational risk violations
continue
}
if len(impactedPackagesIds) == 0 {
// Operational risk violation without any impacted packages, we pass an empty string as the impacted package ID
if e := operationalRiskHandler(violation, cves, applicabilityStatus, severity, "", []string{}, []formats.ComponentRow{}, [][]formats.ComponentRow{}); e != nil {
err = errors.Join(err, e)
continue
}
}
for compIndex := range impactedPackagesIds {
if e := operationalRiskHandler(violation, cves, applicabilityStatus, severity, impactedPackagesIds[compIndex], fixedVersions[compIndex], directComponents[compIndex], impactPaths[compIndex]); e != nil {
err = errors.Join(err, e)
Expand Down
2 changes: 1 addition & 1 deletion policy/local/localconvertor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func createScaTestViolation(id, component string, vioType violationutils.Violati
Severity: severity,
Watch: watch,
},
ImpactedComponent: cyclonedx.Component{
ImpactedComponent: &cyclonedx.Component{
BOMRef: fmt.Sprintf("pkg:generic/%s", component),
PackageURL: fmt.Sprintf("pkg:generic/%s", component),
Type: cyclonedx.ComponentTypeLibrary,
Expand Down
2 changes: 1 addition & 1 deletion utils/formats/violationutils/violations.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ type JasViolation struct {

type ScaViolation struct {
Violation
ImpactedComponent cyclonedx.Component `json:"impacted_component"`
ImpactedComponent *cyclonedx.Component `json:"impacted_component,omitempty"`
DirectComponents []formats.ComponentRow `json:"direct_components,omitempty"`
ImpactPaths [][]formats.ComponentRow `json:"impact_paths,omitempty"`
}
Expand Down
49 changes: 36 additions & 13 deletions utils/results/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type ParseScanGraphVulnerabilityFunc func(vulnerability services.Vulnerability,
type ParseLicenseFunc func(license services.License, impactedPackagesId string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) error
type ParseJasIssueFunc func(run *sarif.Run, rule *sarif.ReportingDescriptor, severity severityutils.Severity, result *sarif.Result, location *sarif.Location) error
type ParseSbomComponentFunc func(component cyclonedx.Component, relatedDependencies *cyclonedx.Dependency, relation cdxutils.ComponentRelation) error
type ParseBomScaVulnerabilityFunc func(vulnerability cyclonedx.Vulnerability, component cyclonedx.Component, fixedVersion *[]cyclonedx.AffectedVersions, applicability *formats.Applicability, severity severityutils.Severity) error
type ParseBomScaVulnerabilityFunc func(vulnerability cyclonedx.Vulnerability, component *cyclonedx.Component, fixedVersion *[]cyclonedx.AffectedVersions, applicability *formats.Applicability, severity severityutils.Severity) error

// Allows to iterate over the provided SARIF runs and call the provided handler for each issue to process it.
func ForEachJasIssue(runs []*sarif.Run, entitledForJas bool, handler ParseJasIssueFunc) (err error) {
Expand Down Expand Up @@ -110,6 +110,13 @@ func ForEachScanGraphVulnerability(target ScanTarget, descriptors []string, vuln
err = errors.Join(err, e)
continue
}
if len(impactedPackagesIds) == 0 {
// Vulnerability without any impacted packages, we pass an empty string as the impacted package ID
if e := handler(vulnerability, cves, applicabilityStatus, severity, "", []string{}, []formats.ComponentRow{}, [][]formats.ComponentRow{}); e != nil {
err = errors.Join(err, e)
continue
}
}
for compIndex := 0; compIndex < len(impactedPackagesIds); compIndex++ {
if e := handler(vulnerability, cves, applicabilityStatus, severity, impactedPackagesIds[compIndex], fixedVersions[compIndex], directComponents[compIndex], impactPaths[compIndex]); e != nil {
err = errors.Join(err, e)
Expand Down Expand Up @@ -154,13 +161,8 @@ func ForEachScaBomVulnerability(_ ScanTarget, bom *cyclonedx.BOM, entitledForJas
}
// Get the related components for the vulnerability
for _, affectedComponent := range *vulnerability.Affects {
relatedComponent := cdxutils.SearchComponentByRef(bom.Components, affectedComponent.Ref)
if relatedComponent == nil {
log.Verbose(fmt.Sprintf("Skipping vulnerability %s as it has no related component with BOMRef %s", vulnerability.BOMRef, affectedComponent.Ref))
continue
}
// Pass the vulnerability to the handler with its related information
if e := handler(vulnerability, *relatedComponent, GetFixedVersions(affectedComponent), applicability, cdxRatingToSeverity(vulnerability.Ratings)); e != nil {
if e := handler(vulnerability, cdxutils.SearchComponentByRef(bom.Components, affectedComponent.Ref), GetFixedVersions(affectedComponent), applicability, cdxRatingToSeverity(vulnerability.Ratings)); e != nil {
err = errors.Join(err, e)
continue
}
Expand Down Expand Up @@ -216,6 +218,13 @@ func ForEachLicense(target ScanTarget, licenses []services.License, handler Pars
err = errors.Join(err, e)
continue
}
if len(impactedPackagesIds) == 0 {
// License without any impacted packages, we pass an empty string as the impacted package ID
if e := handler(license, "", []formats.ComponentRow{}, [][]formats.ComponentRow{}); e != nil {
err = errors.Join(err, e)
continue
}
}
for compIndex := range impactedPackagesIds {
if e := handler(license, impactedPackagesIds[compIndex], directComponents[compIndex], impactPaths[compIndex]); e != nil {
err = errors.Join(err, e)
Expand Down Expand Up @@ -654,6 +663,10 @@ func GetDependencyId(depName, version string) string {
}

func GetScaIssueId(depName, version, issueId string) string {
if depName == "" && version == "" {
depName = "unknown"
version = "unknown"
}
return fmt.Sprintf("%s_%s_%s", issueId, depName, version)
}

Expand Down Expand Up @@ -1277,6 +1290,11 @@ func ScanResponseToSbom(destination *cyclonedx.BOM, scanResponse services.ScanRe

func ParseScanGraphLicenseToSbom(destination *cyclonedx.BOM) ParseLicenseFunc {
return func(license services.License, impactedPackagesId string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) error {
if impactedPackagesId == "" {
// License without any impacted packages, we skip for now
log.Warn(fmt.Sprintf("License %s without any impacted component, skip attaching it to the SBOM", license.Key))
return nil
}
// Add the license related component if it is not already existing
affectedComponent := GetOrCreateScaComponent(destination, impactedPackagesId)
// Attach the license to the component
Expand All @@ -1298,8 +1316,11 @@ func ParseScanGraphVulnerabilityToSbom(destination *cyclonedx.BOM) ParseScanGrap
// Prepare the information needed to create the SCA vulnerability
xrayService := GetXrayService()
return func(vulnerability services.Vulnerability, cves []formats.CveRow, applicabilityStatus jasutils.ApplicabilityStatus, severity severityutils.Severity, impactedPackagesId string, fixedVersion []string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) error {
// Add the vulnerability related component if it is not already existing
affectedComponent := GetOrCreateScaComponent(destination, impactedPackagesId)
var affectedComponent *cyclonedx.Component
if impactedPackagesId != "" {
// Add the vulnerability related component if it is not already existing
affectedComponent = GetOrCreateScaComponent(destination, impactedPackagesId)
}
// Extract the vulnerability CVE's information and create the SCA vulnerability for each
cveIds, applicability, cwes, ratings := ExtractIssuesInfoForCdx(vulnerability.IssueId, cves, severity, applicabilityStatus, xrayService)
extendedInformation := ""
Expand All @@ -1318,10 +1339,12 @@ func ParseScanGraphVulnerabilityToSbom(destination *cyclonedx.BOM) ParseScanGrap
Service: xrayService,
}
vulnerability := cdxutils.GetOrCreateScaIssue(destination, params)
// Attach the affected impacted library component to the vulnerability
cdxutils.AttachComponentAffects(vulnerability, *affectedComponent, func(affectedComponent cyclonedx.Component) cyclonedx.Affects {
return cdxutils.CreateScaImpactedAffects(affectedComponent, fixedVersion)
})
if affectedComponent != nil {
// Attach the affected impacted library component to the vulnerability
cdxutils.AttachComponentAffects(vulnerability, *affectedComponent, func(affectedComponent cyclonedx.Component) cyclonedx.Affects {
return cdxutils.CreateScaImpactedAffects(affectedComponent, fixedVersion)
})
}
// Attach JAS information to the vulnerability
AttachApplicabilityToVulnerability(destination, vulnerability, applicability[i])
}
Expand Down
8 changes: 4 additions & 4 deletions utils/results/conversion/convertor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func getAuditTestResults(unique bool) (*results.SecurityCommandResults, validati
ViolationId: "XRAY-609848",
Severity: severityutils.Unknown,
},
ImpactedComponent: cyclonedx.Component{
ImpactedComponent: &cyclonedx.Component{
BOMRef: "pkg:npm/async@3.2.4",
PackageURL: "pkg:npm/async@3.2.4",
},
Expand Down Expand Up @@ -462,7 +462,7 @@ func getAuditTestResults(unique bool) (*results.SecurityCommandResults, validati
ViolationId: "98yhnmju7654rfvbnj",
Severity: severityutils.Medium,
},
ImpactedComponent: cyclonedx.Component{
ImpactedComponent: &cyclonedx.Component{
BOMRef: "pkg:npm/lodash@4.17.0",
PackageURL: "pkg:npm/lodash@4.17.0",
},
Expand Down Expand Up @@ -503,7 +503,7 @@ func getAuditTestResults(unique bool) (*results.SecurityCommandResults, validati
ViolationId: "12ee2e134edqwe234",
Severity: severityutils.High,
},
ImpactedComponent: cyclonedx.Component{
ImpactedComponent: &cyclonedx.Component{
BOMRef: "pkg:npm/lodash@4.17.0",
PackageURL: "pkg:npm/lodash@4.17.0",
},
Expand Down Expand Up @@ -751,7 +751,7 @@ func getDockerScanTestResults(unique bool) (*results.SecurityCommandResults, val
ViolationId: "XRAY-632747",
Severity: severityutils.Unknown,
},
ImpactedComponent: cyclonedx.Component{
ImpactedComponent: &cyclonedx.Component{
BOMRef: "pkg:deb/debian/bookworm/libssl3@3.0.13-1~deb12u1",
PackageURL: "pkg:deb/debian/bookworm/libssl3@3.0.13-1~deb12u1",
},
Expand Down
8 changes: 5 additions & 3 deletions utils/results/conversion/cyclonedxparser/cyclonedxparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ func (cdc *CmdResultsCycloneDxConverter) ParseCVEs(enrichedSbom *cyclonedx.BOM,
}
cdc.addJasService(applicableScan)
return results.ForEachScaBomVulnerability(cdc.currentTarget, enrichedSbom, cdc.entitledForJas, results.CollectRuns(applicableScan...),
func(vulnToParse cyclonedx.Vulnerability, compToParse cyclonedx.Component, fixedVersion *[]cyclonedx.AffectedVersions, applicability *formats.Applicability, severity severityutils.Severity) (e error) {
// Add the vulnerability related component if it is not already existing
cdc.getOrCreateScaComponent(compToParse)
func(vulnToParse cyclonedx.Vulnerability, compToParse *cyclonedx.Component, fixedVersion *[]cyclonedx.AffectedVersions, applicability *formats.Applicability, severity severityutils.Severity) (e error) {
if compToParse != nil {
// Add the vulnerability related component if it is not already existing
cdc.getOrCreateScaComponent(*compToParse)
}
// Add the vulnerability to the BOM if it is not already existing
vulnerability := cdc.getOrCreateScaIssue(vulnToParse)
// Attach JAS information to the vulnerability
Expand Down
Loading
Loading