Skip to content

Commit

Permalink
improve ruby comparison version check. (#552)
Browse files Browse the repository at this point in the history
* Implemented ruby comparison version check.

* Added semver package to validate and check version

* Added more tests

* Replaced go-version with semver

* Removing go-version from dependency

* Added check for ruby gem version format

* Updated semver model and patch rewrite process

* Refactoring
  • Loading branch information
rahul2393 committed Jul 19, 2020
1 parent 43085a8 commit 6eebed3
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 29 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/aquasecurity/trivy
go 1.13

require (
github.com/Masterminds/semver/v3 v3.1.0
github.com/aquasecurity/fanal v0.0.0-20200528202907-79693bf4a058
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b
github.com/aquasecurity/trivy-db v0.0.0-20200715174849-fa5a3ca24b16
Expand All @@ -18,7 +19,6 @@ require (
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936
github.com/knqyf263/go-version v1.1.1
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0 h1:wykTgKwhVr2t2qs+xI020s6W5dt614QqCHV+7W9dg64=
github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
Expand Down Expand Up @@ -279,8 +281,6 @@ github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d/go.mod h1:
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936 h1:HDjRqotkViMNcGMGicb7cgxklx8OwnjtCBmyWEqrRvM=
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0=
github.com/knqyf263/go-rpmdb v0.0.0-20190501070121-10a1c42a10dc/go.mod h1:MrSSvdMpTSymaQWk1yFr9sxFSyQmKMj6jkbvGrchBV8=
github.com/knqyf263/go-version v1.1.1 h1:+MpcBC9b7rk5ihag8Y/FLG8get1H2GjniwKQ+9DxI2o=
github.com/knqyf263/go-version v1.1.1/go.mod h1:0tBvHvOBSf5TqGNcY+/ih9o8qo3R16iZCpB9rP0D3VM=
github.com/knqyf263/nested v0.0.1 h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc=
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand Down
4 changes: 2 additions & 2 deletions pkg/detector/library/bundler/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package bundler
import (
"strings"

"github.com/knqyf263/go-version"
"github.com/Masterminds/semver/v3"
"golang.org/x/xerrors"

bundlerSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/bundler"
Expand Down Expand Up @@ -44,7 +44,7 @@ func NewAdvisory() *Advisory {
}
}

func (a *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (a *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
advisories, err := a.vs.Get(pkgName)
if err != nil {
return nil, xerrors.Errorf("failed to get bundler advisories: %w", err)
Expand Down
5 changes: 3 additions & 2 deletions pkg/detector/library/bundler/advisory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import (

"github.com/aquasecurity/trivy/pkg/log"

"github.com/Masterminds/semver/v3"

bundlerSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/bundler"
"github.com/knqyf263/go-version"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
Expand Down Expand Up @@ -53,7 +54,7 @@ func TestScanner_Detect(t *testing.T) {
versionStr := "1.9.25-x64-mingw32"
versionStr = platformReplacer.Replace(versionStr)

v, _ := version.NewVersion(versionStr)
v, _ := semver.NewVersion(versionStr)

vulns, err := s.DetectVulnerabilities("ffi", v)

Expand Down
4 changes: 2 additions & 2 deletions pkg/detector/library/cargo/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (

"github.com/aquasecurity/trivy/pkg/types"

"github.com/Masterminds/semver/v3"
cargoSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/cargo"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/knqyf263/go-version"
"golang.org/x/xerrors"
)

Expand All @@ -21,7 +21,7 @@ func NewAdvisory() *Advisory {
}
}

func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
advisories, err := s.vs.Get(pkgName)
if err != nil {
return nil, xerrors.Errorf("failed to get cargo advisories: %w", err)
Expand Down
5 changes: 3 additions & 2 deletions pkg/detector/library/composer/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (

"golang.org/x/xerrors"

"github.com/Masterminds/semver/v3"

composerSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/composer"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/knqyf263/go-version"
)

type Advisory struct {
Expand All @@ -23,7 +24,7 @@ func NewAdvisory() *Advisory {
}
}

func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
ref := fmt.Sprintf("composer://%s", pkgName)
advisories, err := s.vs.Get(ref)
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions pkg/detector/library/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (

"github.com/google/wire"

"github.com/Masterminds/semver/v3"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/knqyf263/go-version"

"golang.org/x/xerrors"

"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/aquasecurity/trivy/pkg/types"
)

Expand Down Expand Up @@ -54,7 +55,7 @@ func detect(driver Driver, libs []ftypes.LibraryInfo) ([]types.DetectedVulnerabi
log.Logger.Infof("Detecting %s vulnerabilities...", driver.Type())
var vulnerabilities []types.DetectedVulnerability
for _, lib := range libs {
v, err := version.NewVersion(lib.Library.Version)
v, err := semver.NewVersion(utils.FormatPatchVersion(lib.Library.Version))
if err != nil {
log.Logger.Debugf("invalid version, library: %s, version: %s, error: %s\n",
lib.Library.Name, lib.Library.Version, err)
Expand Down
6 changes: 3 additions & 3 deletions pkg/detector/library/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package library
import (
"fmt"

"github.com/Masterminds/semver/v3"
"github.com/aquasecurity/fanal/analyzer/library"
ecosystem "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
"github.com/aquasecurity/trivy/pkg/detector/library/bundler"
Expand All @@ -12,7 +13,6 @@ import (
"github.com/aquasecurity/trivy/pkg/detector/library/node"
"github.com/aquasecurity/trivy/pkg/detector/library/python"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/knqyf263/go-version"
"golang.org/x/xerrors"
)

Expand All @@ -21,7 +21,7 @@ type Factory interface {
}

type advisory interface {
DetectVulnerabilities(string, *version.Version) ([]types.DetectedVulnerability, error)
DetectVulnerabilities(string, *semver.Version) ([]types.DetectedVulnerability, error)
}

type DriverFactory struct{}
Expand Down Expand Up @@ -59,7 +59,7 @@ func NewDriver(p string, advisories ...advisory) Driver {
return Driver{pkgManager: p, advisories: advisories}
}

func (driver *Driver) Detect(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (driver *Driver) Detect(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
var detectedVulnerabilities []types.DetectedVulnerability
uniqVulnIdMap := make(map[string]struct{})
for _, d := range driver.advisories {
Expand Down
4 changes: 2 additions & 2 deletions pkg/detector/library/ghsa/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package ghsa
import (
"strings"

"github.com/knqyf263/go-version"
"github.com/Masterminds/semver/v3"
"golang.org/x/xerrors"

"github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
Expand All @@ -25,7 +25,7 @@ func NewAdvisory(ecosystem ghsa.Ecosystem) *Advisory {
}
}

func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
advisories, err := s.vs.Get(pkgName)
if err != nil {
return nil, xerrors.Errorf("failed to get ghsa advisories: %w", err)
Expand Down
5 changes: 3 additions & 2 deletions pkg/detector/library/node/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package node
import (
"strings"

version "github.com/knqyf263/go-version"
"golang.org/x/xerrors"

"github.com/Masterminds/semver/v3"

"github.com/aquasecurity/trivy-db/pkg/vulnsrc/node"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/aquasecurity/trivy/pkg/types"
Expand All @@ -21,7 +22,7 @@ func NewAdvisory() *Advisory {
}
}

func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
replacer := strings.NewReplacer(".alpha", "-alpha", ".beta", "-beta", ".rc", "-rc", " <", ", <", " >", ", >")
advisories, err := s.vs.Get(pkgName)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/detector/library/python/advisory.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (

"golang.org/x/xerrors"

"github.com/Masterminds/semver/v3"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/knqyf263/go-version"
)

type Advisory struct {
Expand All @@ -22,7 +22,7 @@ func NewAdvisory() *Advisory {
}
}

func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *version.Version) ([]types.DetectedVulnerability, error) {
func (s *Advisory) DetectVulnerabilities(pkgName string, pkgVer *semver.Version) ([]types.DetectedVulnerability, error) {
advisories, err := s.vs.Get(pkgName)
if err != nil {
return nil, xerrors.Errorf("failed to get python advisories: %w", err)
Expand Down
47 changes: 40 additions & 7 deletions pkg/scanner/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,50 @@ package utils

import (
"fmt"
"strconv"
"strings"

"github.com/Masterminds/semver/v3"

"github.com/aquasecurity/fanal/types"

"github.com/aquasecurity/trivy/pkg/log"
"github.com/knqyf263/go-version"
)

var (
replacer = strings.NewReplacer(".alpha", "-alpha", ".beta", "-beta", ".rc", "-rc")
)

func MatchVersions(currentVersion *version.Version, rangeVersions []string) bool {
for _, p := range rangeVersions {
c, err := version.NewConstraint(replacer.Replace(p))
func MatchVersions(currentVersion *semver.Version, rangeVersions []string) bool {
for _, v := range rangeVersions {
v = replacer.Replace(v)
constraintParts := strings.Split(v, ",")
for j := range constraintParts {
constraintParts[j] = FormatPatchVersion(constraintParts[j])
}
v = strings.Join(constraintParts, ",")
c, err := semver.NewConstraint(v)
if err != nil {
log.Logger.Debug("NewConstraint", "error", err)
return false
log.Logger.Error("NewConstraint", "error", err)
continue
}
if c.Check(currentVersion) {
// Validate a version against a constraint.
valid, msgs := c.Validate(currentVersion)
if valid {
return true
}
for _, m := range msgs {
// re-validate after removing the patch version
if strings.HasSuffix(m.Error(), "is a prerelease version and the constraint is only looking for release versions") {
v2, err := semver.NewVersion(fmt.Sprintf("%v.%v.%v", currentVersion.Major(), currentVersion.Minor(), currentVersion.Patch()))
if err == nil {
valid, _ = c.Validate(v2)
if valid {
return true
}
}
}
}
}
return false
}
Expand All @@ -35,6 +58,16 @@ func FormatSrcVersion(pkg types.Package) string {
return formatVersion(pkg.SrcEpoch, pkg.SrcVersion, pkg.SrcRelease)
}

func FormatPatchVersion(version string) string {
part := strings.Split(version, ".")
if len(part) > 3 {
if _, err := strconv.Atoi(part[2]); err == nil {
version = strings.Join(part[:3], ".") + "-" + strings.Join(part[3:], ".")
}
}
return version
}

func formatVersion(epoch int, version, release string) string {
v := version
if release != "" {
Expand Down

0 comments on commit 6eebed3

Please sign in to comment.