fix(alpine): handle rc version (#289)

* fix(alpine): handle rc version

* chore(mod): update dependencies
This commit is contained in:
Teppei Fukuda
2019-11-21 11:20:24 +02:00
committed by GitHub
parent b6a8af5b20
commit 6cbbb22ab4
4 changed files with 198 additions and 6 deletions

2
go.mod
View File

@@ -5,7 +5,7 @@ go 1.13
require (
github.com/aquasecurity/fanal v0.0.0-20191104115841-1a8ced6845b7
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b
github.com/aquasecurity/trivy-db v0.0.0-20191119124754-552fbb6fff53
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409
github.com/briandowns/spinner v0.0.0-20190319032542-ac46072a5a91
github.com/caarlos0/env/v6 v6.0.0
github.com/genuinetools/reg v0.16.0

4
go.sum
View File

@@ -28,8 +28,8 @@ github.com/aquasecurity/fanal v0.0.0-20191104115841-1a8ced6845b7/go.mod h1:dD1Ny
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b h1:55Ulc/gvfWm4ylhVaR7MxOwujRjA6et7KhmUbSgUFf4=
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b/go.mod h1:BpNTD9vHfrejKsED9rx04ldM1WIbeyXGYxUrqTVwxVQ=
github.com/aquasecurity/trivy v0.1.6/go.mod h1:5hobyhxLzDtxruHzPxpND2PUKOssvGUdE9BocpJUwo4=
github.com/aquasecurity/trivy-db v0.0.0-20191119124754-552fbb6fff53 h1:btY/EEIRVv2SewBP5bzFuTuI0JiTNQK65jUSkt3SV8Q=
github.com/aquasecurity/trivy-db v0.0.0-20191119124754-552fbb6fff53/go.mod h1:vYzX1UhX0o29E+/nuFJTgUJBM5UA7I/NftnbBcYyYRE=
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409 h1:RrFBrw3qZXH/AIEtEYF1WgYhXae3VPPaaPIJic5p1gw=
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409/go.mod h1:vYzX1UhX0o29E+/nuFJTgUJBM5UA7I/NftnbBcYyYRE=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:xbdUfr2KE4THsFx9CFWtWpU91lF+YhgP46moV94nYTA=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ=
github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83 h1:ukTLOeMC0aVxbJWVg6hOsVJ0VPIo8w++PbNsze/pqF8=

View File

@@ -4,7 +4,7 @@ import (
"strings"
"time"
version "github.com/knqyf263/go-rpm-version"
version "github.com/knqyf263/go-deb-version"
"golang.org/x/xerrors"
"github.com/aquasecurity/fanal/analyzer"
@@ -65,10 +65,19 @@ func (s *Scanner) Detect(osVer string, pkgs []analyzer.Package) ([]types.Detecte
}
installed := utils.FormatVersion(pkg)
installedVersion := version.NewVersion(installed)
installedVersion, err := version.NewVersion(installed)
if err != nil {
log.Logger.Debugf("failed to parse Alpine Linux installed package version: %s", err)
continue
}
for _, adv := range advisories {
fixedVersion := version.NewVersion(adv.FixedVersion)
f := strings.Replace(adv.FixedVersion, "_rc", "~rc", 1)
fixedVersion, err := version.NewVersion(f)
if err != nil {
log.Logger.Debugf("failed to parse Alpine Linux fixed version: %s", err)
continue
}
if installedVersion.LessThan(fixedVersion) {
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,

View File

@@ -1,10 +1,17 @@
package alpine
import (
"errors"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/aquasecurity/fanal/analyzer"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/log"
)
@@ -13,6 +20,182 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func TestScanner_Detect(t *testing.T) {
type args struct {
osVer string
pkgs []analyzer.Package
}
type getInput struct {
osVer string
pkgName string
}
type getOutput struct {
advisories []dbTypes.Advisory
err error
}
type get struct {
input getInput
output getOutput
}
type mocks struct {
get []get
}
tests := []struct {
name string
args args
mocks mocks
want []types.DetectedVulnerability
wantErr string
}{
{
name: "happy path",
args: args{
osVer: "3.10.2",
pkgs: []analyzer.Package{
{
Name: "ansible",
Version: "2.6.4",
},
{
Name: "invalid",
Version: "invalid", // skipped
},
},
},
mocks: mocks{
get: []get{
{
input: getInput{
osVer: "3.10",
pkgName: "ansible",
},
output: getOutput{
advisories: []dbTypes.Advisory{
{
VulnerabilityID: "CVE-2018-10875",
FixedVersion: "2.6.3-r0",
},
{
VulnerabilityID: "CVE-2019-10217",
FixedVersion: "2.8.4-r0",
},
{
VulnerabilityID: "CVE-2019-INVALID",
FixedVersion: "invalid", // skipped
},
},
},
},
{
input: getInput{
osVer: "3.10",
pkgName: "invalid",
},
output: getOutput{advisories: []dbTypes.Advisory{{}}},
},
},
},
want: []types.DetectedVulnerability{
{
PkgName: "ansible",
VulnerabilityID: "CVE-2019-10217",
InstalledVersion: "2.6.4",
FixedVersion: "2.8.4-r0",
},
},
},
{
name: "contain rc",
args: args{
osVer: "3.9",
pkgs: []analyzer.Package{
{
Name: "jq",
Version: "1.6-r0",
},
},
},
mocks: mocks{
get: []get{
{
input: getInput{
osVer: "3.9",
pkgName: "jq",
},
output: getOutput{
advisories: []dbTypes.Advisory{
{
VulnerabilityID: "CVE-2016-4074",
FixedVersion: "1.6_rc1-r0",
},
{
VulnerabilityID: "CVE-2019-9999",
FixedVersion: "1.6_rc2",
},
},
},
},
{
input: getInput{
osVer: "3.10",
pkgName: "invalid",
},
output: getOutput{advisories: []dbTypes.Advisory{{}}},
},
},
},
},
{
name: "Get returns an error",
args: args{
osVer: "3.8.1",
pkgs: []analyzer.Package{
{
Name: "jq",
Version: "1.6-r0",
},
},
},
mocks: mocks{
get: []get{
{
input: getInput{
osVer: "3.8",
pkgName: "jq",
},
output: getOutput{err: errors.New("error")},
},
},
},
wantErr: "failed to get alpine advisories",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockVulnSrc := new(dbTypes.MockVulnSrc)
for _, g := range tt.mocks.get {
mockVulnSrc.On("Get", g.input.osVer, g.input.pkgName).Return(
g.output.advisories, g.output.err)
}
s := &Scanner{
vs: mockVulnSrc,
}
got, err := s.Detect(tt.args.osVer, tt.args.pkgs)
switch {
case tt.wantErr != "":
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
default:
assert.NoError(t, err, tt.name)
}
assert.ElementsMatch(t, got, tt.want, tt.name)
})
}
}
func TestScanner_IsSupportedVersion(t *testing.T) {
vectors := map[string]struct {
now time.Time