Files
trivy/pkg/vex/openvex.go
2024-03-19 00:51:18 +00:00

68 lines
1.9 KiB
Go

package vex
import (
openvex "github.com/openvex/go-vex/pkg/vex"
"github.com/samber/lo"
"github.com/aquasecurity/trivy/pkg/sbom/core"
"github.com/aquasecurity/trivy/pkg/types"
)
type OpenVEX struct {
vex openvex.VEX
}
func newOpenVEX(vex openvex.VEX) VEX {
return &OpenVEX{
vex: vex,
}
}
func (v *OpenVEX) Filter(result *types.Result, bom *core.BOM) {
result.Vulnerabilities = lo.Filter(result.Vulnerabilities, func(vuln types.DetectedVulnerability, _ int) bool {
if vuln.PkgIdentifier.PURL == nil {
return true
}
stmts := v.Matches(vuln, bom)
if len(stmts) == 0 {
return true
}
// Take the latest statement for a given vulnerability and product
// as a sequence of statements can be overridden by the newer one.
// cf. https://github.com/openvex/spec/blob/fa5ba0c0afedb008dc5ebad418548cacf16a3ca7/OPENVEX-SPEC.md#the-vex-statement
stmt := stmts[len(stmts)-1]
if stmt.Status == openvex.StatusNotAffected || stmt.Status == openvex.StatusFixed {
result.ModifiedFindings = append(result.ModifiedFindings,
types.NewModifiedFinding(vuln, findingStatus(stmt.Status), string(stmt.Justification), "OpenVEX"))
return false
}
return true
})
}
func (v *OpenVEX) Matches(vuln types.DetectedVulnerability, bom *core.BOM) []openvex.Statement {
root := bom.Root()
if root != nil && root.PkgID.PURL != nil {
stmts := v.vex.Matches(vuln.VulnerabilityID, root.PkgID.PURL.String(), []string{vuln.PkgIdentifier.PURL.String()})
if len(stmts) != 0 {
return stmts
}
}
return v.vex.Matches(vuln.VulnerabilityID, vuln.PkgIdentifier.PURL.String(), nil)
}
func findingStatus(status openvex.Status) types.FindingStatus {
switch status {
case openvex.StatusNotAffected:
return types.FindingStatusNotAffected
case openvex.StatusFixed:
return types.FindingStatusFixed
case openvex.StatusUnderInvestigation:
return types.FindingStatusUnderInvestigation
default:
return types.FindingStatusUnknown
}
}