github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/detector/library/compare/compare.go (about) 1 package compare 2 3 import ( 4 "strings" 5 6 "golang.org/x/xerrors" 7 8 "github.com/aquasecurity/go-version/pkg/version" 9 dbTypes "github.com/aquasecurity/trivy-db/pkg/types" 10 "github.com/devseccon/trivy/pkg/log" 11 ) 12 13 // Comparer is an interface for version comparison 14 type Comparer interface { 15 IsVulnerable(currentVersion string, advisory dbTypes.Advisory) bool 16 } 17 18 type matchVersion func(currentVersion, constraint string) (bool, error) 19 20 // IsVulnerable checks if the package version is vulnerable to the advisory. 21 func IsVulnerable(pkgVer string, advisory dbTypes.Advisory, match matchVersion) bool { 22 // If one of vulnerable/patched versions is empty, we should detect it anyway. 23 for _, v := range append(advisory.VulnerableVersions, advisory.PatchedVersions...) { 24 if v == "" { 25 return true 26 } 27 } 28 var matched bool 29 var err error 30 31 if len(advisory.VulnerableVersions) != 0 { 32 matched, err = match(pkgVer, strings.Join(advisory.VulnerableVersions, " || ")) 33 if err != nil { 34 log.Logger.Warn(err) 35 return false 36 } else if !matched { 37 // the version is not vulnerable 38 return false 39 } 40 } 41 42 secureVersions := append(advisory.PatchedVersions, advisory.UnaffectedVersions...) 43 if len(secureVersions) == 0 { 44 // the version matches vulnerable versions and patched/unaffected versions are not provided 45 // or all values are empty 46 return matched 47 } 48 49 matched, err = match(pkgVer, strings.Join(secureVersions, " || ")) 50 if err != nil { 51 log.Logger.Warn(err) 52 return false 53 } 54 return !matched 55 } 56 57 // GenericComparer represents a comparer for semver-like versioning 58 type GenericComparer struct{} 59 60 // IsVulnerable checks if the package version is vulnerable to the advisory. 61 func (v GenericComparer) IsVulnerable(ver string, advisory dbTypes.Advisory) bool { 62 return IsVulnerable(ver, advisory, v.matchVersion) 63 } 64 65 // matchVersion checks if the package version satisfies the given constraint. 66 func (v GenericComparer) matchVersion(currentVersion, constraint string) (bool, error) { 67 ver, err := version.Parse(currentVersion) 68 if err != nil { 69 return false, xerrors.Errorf("version error (%s): %s", currentVersion, err) 70 } 71 72 c, err := version.NewConstraints(constraint) 73 if err != nil { 74 return false, xerrors.Errorf("constraint error (%s): %s", currentVersion, err) 75 } 76 77 return c.Check(ver), nil 78 }