Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(debian): support the versions that reached EOL #1237

Merged
merged 3 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492
github.com/aquasecurity/trivy-db v0.0.0-20210907100132-2ec74c43526d
github.com/aquasecurity/trivy-db v0.0.0-20210916043317-726b7b72a47b
github.com/caarlos0/env/v6 v6.0.0
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cheggaaa/pb/v3 v3.0.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 h1:moQmzbp
github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516/go.mod h1:gTd97VdQ0rg8Mkiic3rPgNOQdprZ7feTAhiD5mGQjgM=
github.com/aquasecurity/tfsec v0.46.0 h1:R9djHTpk+YrFuFv2GRdfU4rRz6uk5wLrgfx1fp9K1es=
github.com/aquasecurity/tfsec v0.46.0/go.mod h1:Dafx5dX/1QV1d5en62shpzEXfq5F31IG6oNNxhleV5Y=
github.com/aquasecurity/trivy-db v0.0.0-20210907100132-2ec74c43526d h1:AMuCVa54YX5wVmvqeUZY/PSfMbHtiX1PukVZHocCLr0=
github.com/aquasecurity/trivy-db v0.0.0-20210907100132-2ec74c43526d/go.mod h1:lcUx+KZjKYLu7gCe8Gwe3ZUBUsxeRUg3mwkvzikP6kQ=
github.com/aquasecurity/trivy-db v0.0.0-20210916043317-726b7b72a47b h1:RaS93vlHzgreZk3CYqcNgoqukwbsBEYhAiE6qmhLwB0=
github.com/aquasecurity/trivy-db v0.0.0-20210916043317-726b7b72a47b/go.mod h1:5h8GV7Qxp/SMJ4awWHs0KRxwVkKzcwOnRkORWOnCXRU=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ=
github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down
69 changes: 33 additions & 36 deletions pkg/detector/ospkg/debian/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"k8s.io/utils/clock"

ftypes "github.com/aquasecurity/fanal/types"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/debian"
debianoval "github.com/aquasecurity/trivy-db/pkg/vulnsrc/debian-oval"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/scanner/utils"
"github.com/aquasecurity/trivy/pkg/types"
Expand Down Expand Up @@ -53,8 +54,7 @@ func WithClock(clock clock.Clock) option {

// Scanner implements the Debian scanner
type Scanner struct {
ovalVs debianoval.VulnSrc
vs debian.VulnSrc
vs debian.VulnSrc
*options
}

Expand All @@ -68,7 +68,6 @@ func NewScanner(opts ...option) *Scanner {
opt(o)
}
return &Scanner{
ovalVs: debianoval.NewVulnSrc(),
vs: debian.NewVulnSrc(),
options: o,
}
Expand All @@ -86,55 +85,53 @@ func (s *Scanner) Detect(osVer string, pkgs []ftypes.Package) ([]types.DetectedV

var vulns []types.DetectedVulnerability
for _, pkg := range pkgs {
// This bucket has only fixed vulnerabilities.
// To detect vulnerabilities, it is necessary to compare versions between the installed version and the patched version.
advisories, err := s.ovalVs.Get(osVer, pkg.SrcName)
if err != nil {
return nil, xerrors.Errorf("failed to get debian OVAL: %w", err)
}

installed := utils.FormatSrcVersion(pkg)
installedVersion, err := version.NewVersion(installed)
if err != nil {
log.Logger.Debugf("failed to parse Debian installed package version: %w", err)
log.Logger.Debugf("Debian installed package version error: %s", err)
continue
}

advisories, err := s.vs.Get(osVer, pkg.SrcName)
if err != nil {
return nil, xerrors.Errorf("failed to get debian advisories: %w", err)
}

for _, adv := range advisories {
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
VendorIDs: adv.VendorIDs,
PkgName: pkg.Name,
InstalledVersion: installed,
FixedVersion: adv.FixedVersion,
Layer: pkg.Layer,
}

if adv.Severity != dbTypes.SeverityUnknown {
// Package-specific severity
vuln.SeveritySource = vulnerability.Debian
vuln.Vulnerability = dbTypes.Vulnerability{
Severity: adv.Severity.String(),
}
}

// It means unfixed vulnerability. We don't have to compare versions.
if adv.FixedVersion == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vulns = append(vulns, vuln)
continue
}

var fixedVersion version.Version
fixedVersion, err = version.NewVersion(adv.FixedVersion)
if err != nil {
log.Logger.Debugf("failed to parse Debian package version: %w", err)
log.Logger.Debugf("Debian advisory package version error: %s", err)
continue
}

if installedVersion.LessThan(fixedVersion) {
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgName: pkg.Name,
InstalledVersion: installed,
FixedVersion: adv.FixedVersion,
Layer: pkg.Layer,
}
vulns = append(vulns, vuln)
}
}

// This bucket has only unfixed vulnerabilities which don't have a patched version.
// It is unnecessary to compare versions since it should be always vulnerable to an unfixed vulnerability.
advisories, err = s.vs.Get(osVer, pkg.SrcName)
if err != nil {
return nil, xerrors.Errorf("failed to get debian advisory: %w", err)
}
for _, adv := range advisories {
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgName: pkg.Name,
InstalledVersion: installed,
Layer: pkg.Layer,
}
vulns = append(vulns, vuln)
}
}
return vulns, nil
}
Expand Down
16 changes: 11 additions & 5 deletions pkg/detector/ospkg/debian/debian_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import (
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
fake "k8s.io/utils/clock/testing"

ftypes "github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/trivy-db/pkg/db"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/debian"
"github.com/aquasecurity/trivy/pkg/types"

fake "k8s.io/utils/clock/testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestScanner_Detect(t *testing.T) {
Expand Down Expand Up @@ -49,6 +50,7 @@ func TestScanner_Detect(t *testing.T) {
{
PkgName: "htpasswd",
VulnerabilityID: "CVE-2020-11985",
VendorIDs: []string{"DSA-4884-1"},
InstalledVersion: "2.4.24",
FixedVersion: "2.4.25-1",
Layer: ftypes.Layer{
Expand All @@ -59,6 +61,10 @@ func TestScanner_Detect(t *testing.T) {
PkgName: "htpasswd",
VulnerabilityID: "CVE-2021-31618",
InstalledVersion: "2.4.24",
SeveritySource: vulnerability.Debian,
Vulnerability: dbTypes.Vulnerability{
Severity: dbTypes.SeverityMedium.String(),
},
Layer: ftypes.Layer{
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
},
Expand Down
3 changes: 3 additions & 0 deletions pkg/detector/ospkg/debian/testdata/fixtures/debian.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- key: CVE-2021-31618
value:
FixedVersion: ""
Severity: 2
- bucket: debian oval 9
pairs:
- bucket: apache2
Expand All @@ -15,3 +16,5 @@
- key: CVE-2020-11985
value:
FixedVersion: "2.4.25-1"
VendorIDs:
- DSA-4884-1
28 changes: 22 additions & 6 deletions pkg/result/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,34 @@ func NewClient(dbc db.Config) Client {

// FillVulnerabilityInfo fills extra info in vulnerability objects
func (c Client) FillVulnerabilityInfo(vulns []types.DetectedVulnerability, reportType string) {
var err error

for i := range vulns {
vulns[i].Vulnerability, err = c.dbc.GetVulnerability(vulns[i].VulnerabilityID)
vulnID := vulns[i].VulnerabilityID
vuln, err := c.dbc.GetVulnerability(vulnID)
if err != nil {
log.Logger.Warnf("Error while getting vulnerability details: %s\n", err)
continue
}

// Detect which data source should be used.
source := c.detectSource(reportType)
vulns[i].Severity, vulns[i].SeveritySource = c.getVendorSeverity(&vulns[i], source)
vulns[i].PrimaryURL = c.getPrimaryURL(vulns[i].VulnerabilityID, vulns[i].References, source)

// Select the severity according to the detected source.
severity, severitySource := c.getVendorSeverity(&vuln, source)

// The vendor might provide package-specific severity like Debian.
// For example, CVE-2015-2328 in Debian has "unimportant" for mongodb and "low" for pcre3.
// In that case, we keep the severity as is.
if vulns[i].SeveritySource != "" {
severity = vulns[i].Severity
severitySource = vulns[i].SeveritySource
}

// Add the vulnerability detail
vulns[i].Vulnerability = vuln

vulns[i].Severity = severity
vulns[i].SeveritySource = severitySource
vulns[i].PrimaryURL = c.getPrimaryURL(vulnID, vuln.References, source)
vulns[i].Vulnerability.VendorSeverity = nil // Remove VendorSeverity from Results
}
}
Expand Down Expand Up @@ -98,7 +114,7 @@ func (c Client) detectSource(reportType string) string {
return source
}

func (c Client) getVendorSeverity(vuln *types.DetectedVulnerability, source string) (string, string) {
func (c Client) getVendorSeverity(vuln *dbTypes.Vulnerability, source string) (string, string) {
if vs, ok := vuln.VendorSeverity[source]; ok {
return vs.String(), source
}
Expand Down
31 changes: 31 additions & 0 deletions pkg/result/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,37 @@ func TestClient_FillVulnerabilityInfo(t *testing.T) {
},
},
},
{
name: "happy path, with package-specific severity",
fixtures: []string{"testdata/fixtures/full.yaml"},
args: args{
vulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
SeveritySource: vulnerability.Debian,
Vulnerability: dbTypes.Vulnerability{
Severity: dbTypes.SeverityLow.String(),
},
},
},
reportType: vulnerability.Debian,
},
expectedVulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
SeveritySource: vulnerability.Debian,
Vulnerability: dbTypes.Vulnerability{
Title: "dos",
Description: "dos vulnerability",
Severity: dbTypes.SeverityLow.String(),
References: []string{"http://example.com"},
LastModifiedDate: utils.MustTimeParse("2020-01-01T01:01:00Z"),
PublishedDate: utils.MustTimeParse("2001-01-01T01:01:00Z"),
},
PrimaryURL: "https://avd.aquasec.com/nvd/cve-2019-0001",
},
},
},
{
name: "GetVulnerability returns an error",
fixtures: []string{"testdata/fixtures/sad.yaml"},
Expand Down
1 change: 1 addition & 0 deletions pkg/types/vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
// DetectedVulnerability holds the information of detected vulnerabilities
type DetectedVulnerability struct {
VulnerabilityID string `json:",omitempty"`
VendorIDs []string `json:",omitempty"`
PkgName string `json:",omitempty"`
PkgPath string `json:",omitempty"` // It will be filled in the case of language-specific packages such as egg/wheel and gemspec
InstalledVersion string `json:",omitempty"`
Expand Down