@@ -3,7 +3,6 @@ package main
33
44import (
55 "context"
6- "encoding/json"
76 "errors"
87 "flag"
98 "fmt"
@@ -21,6 +20,7 @@ import (
2120 "github.com/google/osv/vulnfeeds/utility/logger"
2221 "github.com/ossf/osv-schema/bindings/go/osvschema"
2322 "google.golang.org/api/iterator"
23+ "google.golang.org/protobuf/encoding/protojson"
2424)
2525
2626const (
@@ -87,7 +87,7 @@ func main() {
8787
8888 vulnerabilities := make ([]* osvschema.Vulnerability , 0 , len (combinedData ))
8989 for _ , v := range combinedData {
90- vulnerabilities = append (vulnerabilities , & v )
90+ vulnerabilities = append (vulnerabilities , v )
9191 }
9292
9393 upload .Upload (ctx , "OSV files" , * uploadToGCS , * outputBucketName , * overridesBucketName , * numWorkers , * osvOutputPath , vulnerabilities , * syncDeletions )
@@ -137,8 +137,8 @@ func listBucketObjects(bucketName string, prefix string) ([]string, error) {
137137// The function returns a map of CVE IDs to their corresponding Vulnerability objects.
138138// Files that are not ".json" files, directories, or files ending in ".metrics.json" are skipped.
139139// The function will log warnings for files that fail to open or decode, and will terminate if it fails to walk the directory.
140- func loadOSV (osvPath string ) map [cves.CVEID ]osvschema.Vulnerability {
141- allVulns := make (map [cves.CVEID ]osvschema.Vulnerability )
140+ func loadOSV (osvPath string ) map [cves.CVEID ]* osvschema.Vulnerability {
141+ allVulns := make (map [cves.CVEID ]* osvschema.Vulnerability )
142142 logger .Info ("Loading OSV records" , slog .String ("path" , osvPath ))
143143 err := filepath .WalkDir (osvPath , func (path string , d fs.DirEntry , err error ) error {
144144 if err != nil {
@@ -148,20 +148,19 @@ func loadOSV(osvPath string) map[cves.CVEID]osvschema.Vulnerability {
148148 return nil
149149 }
150150
151- file , err := os .Open (path )
151+ file , err := os .ReadFile (path )
152152 if err != nil {
153153 logger .Warn ("Failed to open OSV JSON file" , slog .String ("path" , path ), slog .Any ("err" , err ))
154154 return nil
155155 }
156156
157157 var vuln osvschema.Vulnerability
158- decodeErr := json .NewDecoder (file ).Decode (& vuln )
159- file .Close ()
158+ decodeErr := protojson .Unmarshal (file , & vuln )
160159 if decodeErr != nil {
161160 logger .Error ("Failed to decode, skipping" , slog .String ("file" , path ), slog .Any ("err" , decodeErr ))
162161 return nil
163162 }
164- allVulns [cves .CVEID (vuln .ID ) ] = vuln
163+ allVulns [cves .CVEID (vuln .GetId ()) ] = & vuln
165164
166165 return nil
167166 })
@@ -174,12 +173,12 @@ func loadOSV(osvPath string) map[cves.CVEID]osvschema.Vulnerability {
174173}
175174
176175// combineIntoOSV creates OSV entry by combining loaded CVEs from NVD and PackageInfo information from security advisories.
177- func combineIntoOSV (cve5osv map [cves.CVEID ]osvschema.Vulnerability , nvdosv map [cves.CVEID ]osvschema.Vulnerability , mandatoryCVEIDs []string ) map [cves.CVEID ]osvschema.Vulnerability {
178- osvRecords := make (map [cves.CVEID ]osvschema.Vulnerability )
176+ func combineIntoOSV (cve5osv map [cves.CVEID ]* osvschema.Vulnerability , nvdosv map [cves.CVEID ]* osvschema.Vulnerability , mandatoryCVEIDs []string ) map [cves.CVEID ]* osvschema.Vulnerability {
177+ osvRecords := make (map [cves.CVEID ]* osvschema.Vulnerability )
179178
180179 // Iterate through CVEs from security advisories (cve5) as the base
181180 for cveID , cve5 := range cve5osv {
182- var baseOSV osvschema.Vulnerability
181+ var baseOSV * osvschema.Vulnerability
183182 nvd , ok := nvdosv [cveID ]
184183
185184 if ok {
@@ -190,7 +189,7 @@ func combineIntoOSV(cve5osv map[cves.CVEID]osvschema.Vulnerability, nvdosv map[c
190189 baseOSV = cve5
191190 }
192191
193- if len (baseOSV .Affected ) == 0 {
192+ if len (baseOSV .GetAffected () ) == 0 {
194193 // check if part exists.
195194 if ! slices .Contains (mandatoryCVEIDs , string (cveID )) {
196195 continue
@@ -201,7 +200,7 @@ func combineIntoOSV(cve5osv map[cves.CVEID]osvschema.Vulnerability, nvdosv map[c
201200
202201 // Add any remaining CVEs from NVD that were not in the advisory data.
203202 for cveID , nvd := range nvdosv {
204- if len (nvd .Affected ) == 0 {
203+ if len (nvd .GetAffected () ) == 0 {
205204 continue
206205 }
207206 osvRecords [cveID ] = nvd
@@ -211,40 +210,40 @@ func combineIntoOSV(cve5osv map[cves.CVEID]osvschema.Vulnerability, nvdosv map[c
211210}
212211
213212// combineTwoOSVRecords takes two osv records and combines them into one
214- func combineTwoOSVRecords (cve5 osvschema.Vulnerability , nvd osvschema.Vulnerability ) osvschema.Vulnerability {
213+ func combineTwoOSVRecords (cve5 * osvschema.Vulnerability , nvd * osvschema.Vulnerability ) * osvschema.Vulnerability {
215214 baseOSV := cve5
216- combinedAffected := pickAffectedInformation (cve5 .Affected , nvd .Affected )
215+ combinedAffected := pickAffectedInformation (cve5 .GetAffected () , nvd .GetAffected () )
217216
218217 baseOSV .Affected = combinedAffected
219218 // Merge references, ensuring no duplicates.
220219 refMap := make (map [string ]bool )
221- for _ , r := range baseOSV .References {
222- refMap [r .URL ] = true
220+ for _ , r := range baseOSV .GetReferences () {
221+ refMap [r .GetUrl () ] = true
223222 }
224- for _ , r := range nvd .References {
225- if ! refMap [r .URL ] {
223+ for _ , r := range nvd .GetReferences () {
224+ if ! refMap [r .GetUrl () ] {
226225 baseOSV .References = append (baseOSV .References , r )
227- refMap [r .URL ] = true
226+ refMap [r .GetUrl () ] = true
228227 }
229228 }
230229
231230 // Merge timestamps: latest modified, earliest published.
232- cve5Modified := baseOSV .Modified
233- if nvd .Modified . After (cve5Modified ) {
234- baseOSV .Modified = nvd .Modified
231+ cve5Modified := baseOSV .GetModified ()
232+ if nvd .GetModified (). AsTime (). After (cve5Modified . AsTime () ) {
233+ baseOSV .Modified = nvd .GetModified ()
235234 }
236235
237- cve5Published := baseOSV .Published
238- if nvd .Published . Before (cve5Published ) {
239- baseOSV .Published = nvd .Published
236+ cve5Published := baseOSV .GetPublished ()
237+ if nvd .GetPublished (). AsTime (). Before (cve5Published . AsTime () ) {
238+ baseOSV .Published = nvd .GetPublished ()
240239 }
241240
242241 // Merge aliases, ensuring no duplicates.
243242 aliasMap := make (map [string ]bool )
244- for _ , alias := range baseOSV .Aliases {
243+ for _ , alias := range baseOSV .GetAliases () {
245244 aliasMap [alias ] = true
246245 }
247- for _ , alias := range nvd .Aliases {
246+ for _ , alias := range nvd .GetAliases () {
248247 if ! aliasMap [alias ] {
249248 baseOSV .Aliases = append (baseOSV .Aliases , alias )
250249 aliasMap [alias ] = true
@@ -259,7 +258,7 @@ func combineTwoOSVRecords(cve5 osvschema.Vulnerability, nvd osvschema.Vulnerabil
259258// If a match is found, it merges the version range information, preferring the entry
260259// with more ranges. Unmatched nvdAffected packages are appended.
261260// It returns a new slice and does not modify cve5Affected in place.
262- func pickAffectedInformation (cve5Affected []osvschema.Affected , nvdAffected []osvschema.Affected ) []osvschema.Affected {
261+ func pickAffectedInformation (cve5Affected []* osvschema.Affected , nvdAffected []* osvschema.Affected ) []* osvschema.Affected {
263262 if len (nvdAffected ) == 0 {
264263 return cve5Affected
265264 }
@@ -268,31 +267,31 @@ func pickAffectedInformation(cve5Affected []osvschema.Affected, nvdAffected []os
268267 return nvdAffected
269268 }
270269
271- nvdRepoMap := make (map [string ][]osvschema.Range )
270+ nvdRepoMap := make (map [string ][]* osvschema.Range )
272271 for _ , affected := range nvdAffected {
273- for _ , r := range affected .Ranges {
274- if r .Repo != "" {
275- repo := strings .ToLower (r .Repo )
272+ for _ , r := range affected .GetRanges () {
273+ if r .GetRepo () != "" {
274+ repo := strings .ToLower (r .GetRepo () )
276275 nvdRepoMap [repo ] = append (nvdRepoMap [repo ], r )
277276 }
278277 }
279278 }
280279
281- cve5RepoMap := make (map [string ][]osvschema.Range )
280+ cve5RepoMap := make (map [string ][]* osvschema.Range )
282281 for _ , affected := range cve5Affected {
283- for _ , r := range affected .Ranges {
284- if r .Repo != "" {
285- repo := strings .ToLower (r .Repo )
282+ for _ , r := range affected .GetRanges () {
283+ if r .GetRepo () != "" {
284+ repo := strings .ToLower (r .GetRepo () )
286285 cve5RepoMap [repo ] = append (cve5RepoMap [repo ], r )
287286 }
288287 }
289288 }
290289
291- newRepoAffectedMap := make (map [string ]osvschema.Affected )
290+ newRepoAffectedMap := make (map [string ]* osvschema.Affected )
292291
293292 for repo , cveRanges := range cve5RepoMap {
294293 if nvdRanges , ok := nvdRepoMap [repo ]; ok {
295- var newAffectedRanges []osvschema.Range
294+ var newAffectedRanges []* osvschema.Range
296295
297296 // Found a match. If NVD has more ranges, use its ranges.
298297 if len (nvdRanges ) > len (cveRanges ) {
@@ -301,8 +300,8 @@ func pickAffectedInformation(cve5Affected []osvschema.Affected, nvdAffected []os
301300 } else if len (nvdRanges ) < len (cveRanges ) {
302301 newAffectedRanges = cveRanges
303302 } else if len (cveRanges ) == 1 && len (nvdRanges ) == 1 {
304- c5Intro , c5Fixed := getRangeBoundaryVersions (cveRanges [0 ].Events )
305- nvdIntro , nvdFixed := getRangeBoundaryVersions (nvdRanges [0 ].Events )
303+ c5Intro , c5Fixed := getRangeBoundaryVersions (cveRanges [0 ].GetEvents () )
304+ nvdIntro , nvdFixed := getRangeBoundaryVersions (nvdRanges [0 ].GetEvents () )
306305
307306 // Prefer cve5 data, but use nvd data if cve5 data is missing.
308307 if c5Intro == "" {
@@ -315,30 +314,30 @@ func pickAffectedInformation(cve5Affected []osvschema.Affected, nvdAffected []os
315314 if c5Intro != "" || c5Fixed != "" {
316315 newRange := cves .BuildVersionRange (c5Intro , "" , c5Fixed )
317316 newRange .Repo = repo
318- newRange .Type = osvschema .RangeGit // Preserve the repo
317+ newRange .Type = osvschema .Range_GIT // Preserve the repo
319318 newAffectedRanges = append (newAffectedRanges , newRange )
320319 }
321320 }
322321 // Remove from map so we know which NVD packages are left.
323322 delete (nvdRepoMap , repo )
324- newRepoAffectedMap [repo ] = osvschema.Affected {
323+ newRepoAffectedMap [repo ] = & osvschema.Affected {
325324 Ranges : newAffectedRanges ,
326325 }
327326 } else {
328- newRepoAffectedMap [repo ] = osvschema.Affected {
327+ newRepoAffectedMap [repo ] = & osvschema.Affected {
329328 Ranges : cveRanges ,
330329 }
331330 }
332331 }
333332
334333 // Add remaining NVD packages that were not in cve5.
335334 for repo , nvdRange := range nvdRepoMap {
336- newRepoAffectedMap [repo ] = osvschema.Affected {
335+ newRepoAffectedMap [repo ] = & osvschema.Affected {
337336 Ranges : nvdRange ,
338337 }
339338 }
340339
341- var combinedAffected []osvschema.Affected //nolint:prealloc
340+ var combinedAffected []* osvschema.Affected //nolint:prealloc
342341 for _ , aff := range newRepoAffectedMap {
343342 combinedAffected = append (combinedAffected , aff )
344343 }
@@ -348,13 +347,13 @@ func pickAffectedInformation(cve5Affected []osvschema.Affected, nvdAffected []os
348347
349348// getRangeBoundaryVersions extracts the introduced and fixed versions from a slice of OSV events.
350349// It iterates through the events and returns the last non-empty "introduced" and "fixed" versions found.
351- func getRangeBoundaryVersions (events []osvschema.Event ) (introduced , fixed string ) {
350+ func getRangeBoundaryVersions (events []* osvschema.Event ) (introduced , fixed string ) {
352351 for _ , e := range events {
353- if e .Introduced != "0" && e .Introduced != "" {
354- introduced = e .Introduced
352+ if e .GetIntroduced () != "0" && e .GetIntroduced () != "" {
353+ introduced = e .GetIntroduced ()
355354 }
356- if e .Fixed != "" {
357- fixed = e .Fixed
355+ if e .GetFixed () != "" {
356+ fixed = e .GetFixed ()
358357 }
359358 }
360359
0 commit comments