Skip to content

Commit

Permalink
[SDC-1140] - fix(vex): allow VEX matching when no subcomponents (#124)
Browse files Browse the repository at this point in the history
* fix(vex): allow VEX matching when no subcomponents

Signed-off-by: felipecruz91 <[email protected]>

* Apply suggestions from code review

* Apply suggestions from code review

---------

Signed-off-by: felipecruz91 <[email protected]>
  • Loading branch information
felipecruz91 authored Jul 15, 2024
1 parent 4721790 commit b1f233f
Show file tree
Hide file tree
Showing 2 changed files with 376 additions and 17 deletions.
88 changes: 71 additions & 17 deletions policy/data/vulnerabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package data
import (
"context"

"github.com/openvex/go-vex/pkg/vex"
govex "github.com/openvex/go-vex/pkg/vex"

"github.com/atomist-skills/go-skill/policy/data/query"
Expand Down Expand Up @@ -43,23 +44,7 @@ func (ds *DataSource) GetImageVulnerabilities(ctx context.Context, evalCtx goals
normalization.DenormalizeSBOM(&vulnsResponse, purlMapping)

for _, vulnsByPurl := range vulnsResponse.VulnerabilitiesByPackage {
affected := true
for _, v := range imageSbom.VexDocuments {
for _, stmt := range v.Statements {
purl, upstreamPurl := normalization.NormalizePURL(vulnsByPurl.Purl, nil)
for _, p := range stmt.Products {
if normalization.ContainsPurl(p.Subcomponents, purl) || normalization.ContainsPurl(p.Subcomponents, upstreamPurl) {
if stmt.Status == govex.StatusNotAffected || stmt.Status == govex.StatusFixed {
affected = false
}
}
}
}
}

if affected {
vulns[vulnsByPurl.Purl] = vulnsByPurl.Vulnerabilities
}
vulns[vulnsByPurl.Purl] = applyVEX(vulnsByPurl, imageSbom.VexDocuments)
}
} else {
var response jynx.ImagePackagesByDigestResponse
Expand All @@ -80,3 +65,72 @@ func (ds *DataSource) GetImageVulnerabilities(ctx context.Context, evalCtx goals

return &query.QueryResponse{}, packages, vulns, nil
}

// applyVEX returns the CVEs that remain relevant after cross-referencing them with VEX documents.
func applyVEX(vulnsByPurl types.VulnerabilitiesByPurl, vexDocs []vex.VEX) []types.Vulnerability {
filteredOutCVEs := []types.Vulnerability{}

for _, cve := range vulnsByPurl.Vulnerabilities {
for _, v := range vexDocs {
for _, stmt := range v.Statements {
if cveMatch(cve.SourceId, stmt) {
if purlMatch(vulnsByPurl.Purl, stmt) {
if notAffectedOrFixed(stmt) {
filteredOutCVEs = append(filteredOutCVEs, cve)
}
}
}
}
}
}

vexedCVEsMap := make(map[string]bool, len(filteredOutCVEs))
for _, cve := range filteredOutCVEs {
vexedCVEsMap[cve.SourceId] = true
}

// Filter out the VEXed CVEs
cves := make([]types.Vulnerability, 0, len(vulnsByPurl.Vulnerabilities))
for _, cve := range vulnsByPurl.Vulnerabilities {
if !vexedCVEsMap[cve.SourceId] {
cves = append(cves, cve)
}
}
return cves
}

// cveMatch checks whether a CVE is present in a VEX statement
func cveMatch(cveID string, stmt govex.Statement) bool {
return stmt.Vulnerability.ID == cveID || string(stmt.Vulnerability.Name) == cveID
}

// purlMatch checks whether a purl is present in at least one of the following locations:
// - Component
// - Subcomponent(s)
// - Special case for image-scoped exceptions.
func purlMatch(purl string, stmt govex.Statement) bool {
purl, upstreamPurl := normalization.NormalizePURL(purl, nil)

for _, p := range stmt.Products {
// Check if purl is defined as the top-level component
if purl == p.Component.ID {
return true
}
// Check if purl is defined as one of the subcomponents
if normalization.ContainsPurl(p.Subcomponents, purl) || normalization.ContainsPurl(p.Subcomponents, upstreamPurl) {
return true
}
// If none of the previous conditions matched, we add this special case to support image-scoped exceptions.
// The purpose of this is to align with how VEX works in the platform side.
if len(p.Subcomponents) == 0 {
return true
}
}

return false
}

// notAffectedOrFixed checks whether the statement status is not affected or fixed.
func notAffectedOrFixed(stmt govex.Statement) bool {
return stmt.Status == govex.StatusNotAffected || stmt.Status == govex.StatusFixed
}
Loading

0 comments on commit b1f233f

Please sign in to comment.