Skip to content

Commit 29e9813

Browse files
authored
feat(local): support resolving git packages that have a version specified (#2209)
Resolves #2014
1 parent ad38629 commit 29e9813

File tree

5 files changed

+159
-15
lines changed

5 files changed

+159
-15
lines changed

cmd/osv-scanner/scan/source/__snapshots__/command_test.snap

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,59 @@ Total 0 packages affected by 0 known vulnerabilities (0 Critical, 0 High, 0 Medi
16971697

16981698
---
16991699

1700+
[TestCommand_CommitSupport/offline_uses_git_tags - 1]
1701+
Scanned <rootdir>/testdata/locks-git/osv-scanner.json file as a osv-scanner and found 4 packages
1702+
Skipping commit scanning for: 45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0
1703+
Loaded GIT local db from <tempdir>/osv-scanner/GIT/all.zip
1704+
Total 2 packages affected by 6 known vulnerabilities (2 Critical, 2 High, 0 Medium, 0 Low, 2 Unknown) from 1 ecosystem.
1705+
0 vulnerabilities can be fixed.
1706+
1707+
1708+
+--------------------------------+------+-----------+--------------------------+--------------------------+---------------+-------------------------------------+
1709+
| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE |
1710+
+--------------------------------+------+-----------+--------------------------+--------------------------+---------------+-------------------------------------+
1711+
| https://osv.dev/CVE-2016-2183 | 7.5 | GIT | https://github.com/openssl/openssl@aea7aaf2 | -- | testdata/locks-git/osv-scanner.json |
1712+
| https://osv.dev/CVE-2025-4575 | | GIT | https://github.com/openssl/openssl@aea7aaf2 | -- | testdata/locks-git/osv-scanner.json |
1713+
| https://osv.dev/CVE-2016-10931 | 8.1 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1714+
| https://osv.dev/CVE-2018-20997 | 9.8 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1715+
| https://osv.dev/CVE-2023-53159 | 9.1 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1716+
| https://osv.dev/CVE-2025-3416 | | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1717+
+--------------------------------+------+-----------+-----------------------------------------------------+---------------+-------------------------------------+
1718+
1719+
---
1720+
1721+
[TestCommand_CommitSupport/offline_uses_git_tags - 2]
1722+
1723+
---
1724+
1725+
[TestCommand_CommitSupport/online_uses_git_commits - 1]
1726+
Scanned <rootdir>/testdata/locks-git/osv-scanner.json file as a osv-scanner and found 4 packages
1727+
Total 3 packages affected by 11 known vulnerabilities (3 Critical, 1 High, 2 Medium, 0 Low, 5 Unknown) from 1 ecosystem.
1728+
0 vulnerabilities can be fixed.
1729+
1730+
1731+
+--------------------------------+------+-----------+----------------------------+-----------------------------+---------------+-------------------------------------+
1732+
| OSV URL | CVSS | ECOSYSTEM | PACKAGE | VERSION | FIXED VERSION | SOURCE |
1733+
+--------------------------------+------+-----------+----------------------------+-----------------------------+---------------+-------------------------------------+
1734+
| https://osv.dev/CVE-2024-12797 | | GIT | https://github.com/openssl/openssl@45fda76b | -- | testdata/locks-git/osv-scanner.json |
1735+
| https://osv.dev/CVE-2024-13176 | | GIT | https://github.com/openssl/openssl@45fda76b | -- | testdata/locks-git/osv-scanner.json |
1736+
| https://osv.dev/CVE-2024-9143 | | GIT | https://github.com/openssl/openssl@45fda76b | -- | testdata/locks-git/osv-scanner.json |
1737+
| https://osv.dev/CVE-2023-53159 | 9.1 | GIT | https://github.com/sfackler-fork/rust-openssl@3b064fdb | -- | testdata/locks-git/osv-scanner.json |
1738+
| https://osv.dev/CVE-2023-6180 | 5.3 | GIT | https://github.com/sfackler-fork/rust-openssl@3b064fdb | -- | testdata/locks-git/osv-scanner.json |
1739+
| https://osv.dev/CVE-2025-3416 | | GIT | https://github.com/sfackler-fork/rust-openssl@3b064fdb | -- | testdata/locks-git/osv-scanner.json |
1740+
| https://osv.dev/CVE-2016-10931 | 8.1 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1741+
| https://osv.dev/CVE-2018-20997 | 9.8 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1742+
| https://osv.dev/CVE-2023-53159 | 9.1 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1743+
| https://osv.dev/CVE-2023-6180 | 5.3 | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1744+
| https://osv.dev/CVE-2025-3416 | | GIT | https://github.com/sfackler/rust-openssl@0f428d19 | -- | testdata/locks-git/osv-scanner.json |
1745+
+--------------------------------+------+-----------+----------------------------------------------------------+---------------+-------------------------------------+
1746+
1747+
---
1748+
1749+
[TestCommand_CommitSupport/online_uses_git_commits - 2]
1750+
1751+
---
1752+
17001753
[TestCommand_ExplicitExtractors_WithDefaults/empty_plugins_flag_does_nothing - 1]
17011754

17021755
---

cmd/osv-scanner/scan/source/command_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,31 @@ func TestCommand_LocalDatabases_AlwaysOffline(t *testing.T) {
972972
}
973973
}
974974

975+
func TestCommand_CommitSupport(t *testing.T) {
976+
t.Parallel()
977+
978+
tests := []testcmd.Case{
979+
{
980+
Name: "online_uses_git_commits",
981+
Args: []string{"", "source", "--lockfile", "osv-scanner:./testdata/locks-git/osv-scanner.json"},
982+
Exit: 1,
983+
},
984+
{
985+
Name: "offline_uses_git_tags",
986+
Args: []string{"", "source", "--offline", "--download-offline-databases", "--lockfile", "osv-scanner:./testdata/locks-git/osv-scanner.json"},
987+
Exit: 1,
988+
},
989+
}
990+
991+
for _, tt := range tests {
992+
t.Run(tt.Name, func(t *testing.T) {
993+
t.Parallel()
994+
995+
testcmd.RunAndMatchSnapshots(t, tt)
996+
})
997+
}
998+
}
999+
9751000
func TestCommand_Licenses(t *testing.T) {
9761001
t.Parallel()
9771002

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"results": [
3+
{
4+
"packages": [
5+
{
6+
"//1": "version and commit are the same, so rust-openssl advisories should be reported",
7+
"//2": "note online reports CVE-2023-6180 as well due to matching commits for an implicit fork",
8+
"package": {
9+
"name": "https://github.com/sfackler/rust-openssl",
10+
"commit": "0f428d190410263e4daa65b917c0e84707a9c0ef",
11+
"version": "openssl-v0.8.1"
12+
}
13+
},
14+
{
15+
"//1": "repo is different to the advisory, so only online checking will report anything",
16+
"package": {
17+
"name": "https://github.com/sfackler-fork/rust-openssl",
18+
"commit": "3b064fdb022912bbb98f5b8d9d111aeb6fec8f79",
19+
"version": "openssl-v0.10.23"
20+
}
21+
},
22+
{
23+
"//1": "no version, so only online checking will report anything",
24+
"package": {
25+
"name": "https://github.com/openssl/openssl",
26+
"commit": "45fda76bc1b9fd74d10e85e0ce9b65a12dcc58b0"
27+
}
28+
},
29+
{
30+
"//1": "version is for 3.5.0 which is vulnerable to CVE-2025-3416, but commit is for 3.5.1 which is not",
31+
"package": {
32+
"name": "https://github.com/openssl/openssl",
33+
"commit": "aea7aaf2abb04789f5868cbabec406ea43aa84bf",
34+
"version": "openssl-3.5.0"
35+
}
36+
}
37+
]
38+
}
39+
]
40+
}

internal/clients/clientimpl/localmatcher/localmatcher.go

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,29 @@ func (matcher *LocalMatcher) MatchVulnerabilities(ctx context.Context, invs []*e
5555
}
5656

5757
pkg := imodels.FromInventory(inv)
58+
eco := pkg.Ecosystem().Ecosystem
59+
5860
if pkg.Ecosystem().IsEmpty() {
5961
if pkg.Commit() == "" {
6062
// This should never happen, as those results will be filtered out before matching
6163
return nil, errors.New("ecosystem is empty and there is no commit hash")
6264
}
6365

64-
// Is a commit based query, skip local scanning
65-
results = append(results, []*osvschema.Vulnerability{})
66-
// TODO (V2 logging):
67-
cmdlogger.Infof("Skipping commit scanning for: %s", pkg.Commit())
66+
// matching ecosystem-less versions can only be attempted if we have a version
67+
if pkg.Version() == "" {
68+
// Is a commit based query, skip local scanning
69+
results = append(results, []*osvschema.Vulnerability{})
6870

69-
continue
71+
// TODO (V2 logging):
72+
cmdlogger.Infof("Skipping commit scanning for: %s", pkg.Commit())
73+
74+
continue
75+
}
76+
77+
eco = "GIT"
7078
}
7179

72-
db, err := matcher.loadDBFromCache(ctx, pkg.Ecosystem())
80+
db, err := matcher.loadDBFromCache(ctx, eco)
7381

7482
if err != nil {
7583
// no logging here as the loader will have already done that
@@ -87,32 +95,32 @@ func (matcher *LocalMatcher) MatchVulnerabilities(ctx context.Context, invs []*e
8795
// LoadEcosystem tries to preload the ecosystem into the cache, and returns an error if the ecosystem
8896
// cannot be loaded.
8997
func (matcher *LocalMatcher) LoadEcosystem(ctx context.Context, eco osvecosystem.Parsed) error {
90-
_, err := matcher.loadDBFromCache(ctx, eco)
98+
_, err := matcher.loadDBFromCache(ctx, eco.Ecosystem)
9199

92100
return err
93101
}
94102

95-
func (matcher *LocalMatcher) loadDBFromCache(ctx context.Context, eco osvecosystem.Parsed) (*ZipDB, error) {
96-
if db, ok := matcher.dbs[eco.Ecosystem]; ok {
103+
func (matcher *LocalMatcher) loadDBFromCache(ctx context.Context, eco osvschema.Ecosystem) (*ZipDB, error) {
104+
if db, ok := matcher.dbs[eco]; ok {
97105
return db, nil
98106
}
99107

100-
if matcher.failedDBs[eco.Ecosystem] != nil {
101-
return nil, matcher.failedDBs[eco.Ecosystem]
108+
if matcher.failedDBs[eco] != nil {
109+
return nil, matcher.failedDBs[eco]
102110
}
103111

104-
db, err := NewZippedDB(ctx, matcher.dbBasePath, string(eco.Ecosystem), fmt.Sprintf("%s/%s/all.zip", zippedDBRemoteHost, eco.Ecosystem), matcher.userAgent, !matcher.downloadDB)
112+
db, err := NewZippedDB(ctx, matcher.dbBasePath, string(eco), fmt.Sprintf("%s/%s/all.zip", zippedDBRemoteHost, eco), matcher.userAgent, !matcher.downloadDB)
105113

106114
if err != nil {
107-
matcher.failedDBs[eco.Ecosystem] = err
108-
cmdlogger.Errorf("could not load db for %s ecosystem: %v", eco.Ecosystem, err)
115+
matcher.failedDBs[eco] = err
116+
cmdlogger.Errorf("could not load db for %s ecosystem: %v", eco, err)
109117

110118
return nil, err
111119
}
112120

113121
cmdlogger.Infof("Loaded %s local db from %s", db.Name, db.StoredAt)
114122

115-
matcher.dbs[eco.Ecosystem] = db
123+
matcher.dbs[eco] = db
116124

117125
return db, nil
118126
}

internal/utility/vulns/vulnerability.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,26 @@ func AffectsEcosystem(v osvschema.Vulnerability, ecosystemAffected osvecosystem.
125125
return false
126126
}
127127

128+
func hasGitRangeForRepo(affected osvschema.Affected, repo string) bool {
129+
for _, r := range affected.Ranges {
130+
if r.Type == "GIT" && r.Repo == repo {
131+
return true
132+
}
133+
}
134+
135+
return false
136+
}
137+
128138
func IsAffected(v osvschema.Vulnerability, pkg imodels.PackageInfo) bool {
129139
for _, affected := range v.Affected {
140+
// assume we're dealing with a git-source package whose name is the git repository, and that the version is the tag
141+
// the underlying commit has been resolved to (somehow), meaning we can check if it's in the versions listed by the advisory
142+
if pkg.Ecosystem().IsEmpty() && pkg.Commit() != "" && pkg.Version() != "" {
143+
if hasGitRangeForRepo(affected, pkg.Name()) && slices.Contains(affected.Versions, pkg.Version()) {
144+
return true
145+
}
146+
}
147+
130148
// Assume vulnerability has already been validated
131149
if osvecosystem.MustParse(affected.Package.Ecosystem).Equal(pkg.Ecosystem()) &&
132150
affected.Package.Name == pkg.Name() {

0 commit comments

Comments
 (0)