/
driver.go
122 lines (108 loc) · 3.87 KB
/
driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package library
import (
"fmt"
"strings"
"github.com/aquasecurity/trivy/pkg/detector/library/compare/maven"
"golang.org/x/xerrors"
"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/detector/library/compare"
"github.com/aquasecurity/trivy/pkg/detector/library/compare/npm"
"github.com/aquasecurity/trivy/pkg/detector/library/compare/pep440"
"github.com/aquasecurity/trivy/pkg/detector/library/compare/rubygems"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
)
// NewDriver returns a driver according to the library type
func NewDriver(libType string) (Driver, error) {
var ecosystem dbTypes.Ecosystem
var comparer compare.Comparer
switch libType {
case ftypes.Bundler, ftypes.GemSpec:
ecosystem = vulnerability.RubyGems
comparer = rubygems.Comparer{}
case ftypes.RustBinary, ftypes.Cargo:
ecosystem = vulnerability.Cargo
comparer = compare.GenericComparer{}
case ftypes.Composer:
ecosystem = vulnerability.Composer
comparer = compare.GenericComparer{}
case ftypes.GoBinary, ftypes.GoModule:
ecosystem = vulnerability.Go
comparer = compare.GenericComparer{}
case ftypes.Jar, ftypes.Pom, ftypes.Gradle:
ecosystem = vulnerability.Maven
comparer = maven.Comparer{}
case ftypes.Npm, ftypes.Yarn, ftypes.Pnpm, ftypes.NodePkg, ftypes.JavaScript:
ecosystem = vulnerability.Npm
comparer = npm.Comparer{}
case ftypes.NuGet, ftypes.DotNetCore:
ecosystem = vulnerability.NuGet
comparer = compare.GenericComparer{}
case ftypes.Pipenv, ftypes.Poetry, ftypes.Pip, ftypes.PythonPkg:
ecosystem = vulnerability.Pip
comparer = pep440.Comparer{}
default:
return Driver{}, xerrors.Errorf("unsupported type %s", libType)
}
return Driver{
ecosystem: ecosystem,
comparer: comparer,
dbc: db.Config{},
}, nil
}
// Driver represents security advisories for each programming language
type Driver struct {
ecosystem dbTypes.Ecosystem
comparer compare.Comparer
dbc db.Config
}
// Type returns the driver ecosystem
func (d *Driver) Type() string {
return string(d.ecosystem)
}
// DetectVulnerabilities scans buckets with the prefix according to the ecosystem.
// If "ecosystem" is pip, it looks for buckets with "pip::" and gets security advisories from those buckets.
// It allows us to add a new data source with the ecosystem prefix (e.g. pip::new-data-source)
// and detect vulnerabilities without specifying a specific bucket name.
func (d *Driver) DetectVulnerabilities(pkgID, pkgName, pkgVer string) ([]types.DetectedVulnerability, error) {
// e.g. "pip::", "npm::"
prefix := fmt.Sprintf("%s::", d.ecosystem)
advisories, err := d.dbc.GetAdvisories(prefix, vulnerability.NormalizePkgName(d.ecosystem, pkgName))
if err != nil {
return nil, xerrors.Errorf("failed to get %s advisories: %w", d.ecosystem, err)
}
var vulns []types.DetectedVulnerability
for _, adv := range advisories {
if !d.comparer.IsVulnerable(pkgVer, adv) {
continue
}
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgID: pkgID,
PkgName: pkgName,
InstalledVersion: pkgVer,
FixedVersion: createFixedVersions(adv),
DataSource: adv.DataSource,
}
vulns = append(vulns, vuln)
}
return vulns, nil
}
func createFixedVersions(advisory dbTypes.Advisory) string {
if len(advisory.PatchedVersions) != 0 {
return strings.Join(advisory.PatchedVersions, ", ")
}
var fixedVersions []string
for _, version := range advisory.VulnerableVersions {
for _, s := range strings.Split(version, ",") {
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, "<=") && strings.HasPrefix(s, "<") {
s = strings.TrimPrefix(s, "<")
fixedVersions = append(fixedVersions, strings.TrimSpace(s))
}
}
}
return strings.Join(fixedVersions, ", ")
}