-
Notifications
You must be signed in to change notification settings - Fork 334
/
check.go
156 lines (119 loc) · 4.58 KB
/
check.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package local
import (
"fmt"
"os"
"path"
"github.com/google/osv-scanner/pkg/lockfile"
"github.com/google/osv-scanner/pkg/models"
"github.com/google/osv-scanner/pkg/osv"
"github.com/google/osv-scanner/pkg/reporter"
)
const zippedDBRemoteHost = "https://osv-vulnerabilities.storage.googleapis.com"
const envKeyLocalDBCacheDirectory = "OSV_SCANNER_LOCAL_DB_CACHE_DIRECTORY"
func loadDB(dbBasePath string, ecosystem lockfile.Ecosystem, offline bool) (*ZipDB, error) {
return NewZippedDB(dbBasePath, string(ecosystem), fmt.Sprintf("%s/%s/all.zip", zippedDBRemoteHost, ecosystem), offline)
}
func toPackageDetails(query *osv.Query) (lockfile.PackageDetails, error) {
if query.Package.PURL != "" {
pkg, err := models.PURLToPackage(query.Package.PURL)
if err != nil {
return lockfile.PackageDetails{}, err
}
return lockfile.PackageDetails{
Name: pkg.Name,
Version: pkg.Version,
Ecosystem: lockfile.Ecosystem(pkg.Ecosystem),
CompareAs: lockfile.Ecosystem(pkg.Ecosystem),
}, nil
}
return lockfile.PackageDetails{
Name: query.Package.Name,
Version: query.Version,
Commit: query.Commit,
Ecosystem: lockfile.Ecosystem(query.Package.Ecosystem),
CompareAs: lockfile.Ecosystem(query.Package.Ecosystem),
}, nil
}
// setupLocalDBDirectory attempts to set up the directory the scanner should
// use to store local databases.
//
// if a local path is explicitly provided either by the localDBPath parameter
// or via the envKeyLocalDBCacheDirectory environment variable, the scanner will
// attempt to use the user cache directory if possible or otherwise the temp directory
//
// if an error occurs at any point when a local path is not explicitly provided,
// the scanner will fall back to the temp directory first before finally erroring
func setupLocalDBDirectory(localDBPath string) (string, error) {
var err error
// fallback to the env variable if a local database path has not been provided
if localDBPath == "" {
if p, envSet := os.LookupEnv(envKeyLocalDBCacheDirectory); envSet {
localDBPath = p
}
}
implicitPath := localDBPath == ""
// if we're implicitly picking a path, use the user cache directory if available
if implicitPath {
localDBPath, err = os.UserCacheDir()
if err != nil {
localDBPath = os.TempDir()
}
}
err = os.MkdirAll(path.Join(localDBPath, "osv-scanner"), 0750)
if err == nil {
return path.Join(localDBPath, "osv-scanner"), nil
}
// if we're implicitly picking a path, try the temp directory before giving up
if implicitPath && localDBPath != os.TempDir() {
return setupLocalDBDirectory(os.TempDir())
}
return "", err
}
func MakeRequest(r reporter.Reporter, query osv.BatchedQuery, offline bool, localDBPath string) (*osv.HydratedBatchedResponse, error) {
results := make([]osv.Response, 0, len(query.Queries))
dbs := make(map[lockfile.Ecosystem]*ZipDB)
dbBasePath, err := setupLocalDBDirectory(localDBPath)
if err != nil {
return &osv.HydratedBatchedResponse{}, fmt.Errorf("could not create %s: %w", dbBasePath, err)
}
loadDBFromCache := func(ecosystem lockfile.Ecosystem) (*ZipDB, error) {
if db, ok := dbs[ecosystem]; ok {
return db, nil
}
db, err := loadDB(dbBasePath, ecosystem, offline)
if err != nil {
return nil, err
}
r.PrintText(fmt.Sprintf("Loaded %s local db from %s\n", db.Name, db.StoredAt))
dbs[ecosystem] = db
return db, nil
}
for _, query := range query.Queries {
pkg, err := toPackageDetails(query)
if err != nil {
// currently, this will actually only error if the PURL cannot be parses
r.PrintError(fmt.Sprintf("skipping %s as it is not a valid PURL: %v\n", query.Package.PURL, err))
results = append(results, osv.Response{Vulns: []models.Vulnerability{}})
continue
}
if pkg.Ecosystem == "" {
if pkg.Commit == "" {
// The only time this can happen should be when someone passes in their own OSV-Scanner-Results file.
return nil, fmt.Errorf("ecosystem is empty and there is no commit hash")
}
// Is a commit based query, skip local scanning
results = append(results, osv.Response{})
r.PrintText(fmt.Sprintf("Skipping commit scanning for: %s\n", pkg.Commit))
continue
}
db, err := loadDBFromCache(pkg.Ecosystem)
if err != nil {
// currently, this will actually only error if the PURL cannot be parses
r.PrintError(fmt.Sprintf("could not load db for %s ecosystem: %v\n", pkg.Ecosystem, err))
results = append(results, osv.Response{Vulns: []models.Vulnerability{}})
continue
}
results = append(results, osv.Response{Vulns: db.VulnerabilitiesAffectingPackage(pkg)})
}
return &osv.HydratedBatchedResponse{Results: results}, nil
}