@@ -195,6 +195,8 @@ func toOS(os *v6.OperatingSystem) *OperatingSystem {
195195func FindAffectedPackages (reader interface {
196196 v6.AffectedPackageStoreReader
197197 v6.AffectedCPEStoreReader
198+ v6.UnaffectedPackageStoreReader
199+ v6.UnaffectedCPEStoreReader
198200 v6.VulnerabilityDecoratorStoreReader
199201}, criteria AffectedPackagesOptions ,
200202) ([]AffectedPackage , error ) {
@@ -211,9 +213,11 @@ func FindAffectedPackages(reader interface {
211213 return newAffectedPackageRows (allAffectedPkgs , allAffectedCPEs ), nil
212214}
213215
214- func findAffectedPackages (reader interface { //nolint:funlen,gocognit
216+ func findAffectedPackages (reader interface { //nolint:funlen,gocognit,gocyclo
215217 v6.AffectedPackageStoreReader
216218 v6.AffectedCPEStoreReader
219+ v6.UnaffectedPackageStoreReader
220+ v6.UnaffectedCPEStoreReader
217221 v6.VulnerabilityDecoratorStoreReader
218222}, config AffectedPackagesOptions ,
219223) ([]affectedPackageWithDecorations , []affectedCPEWithDecorations , error ) {
@@ -286,6 +290,33 @@ func findAffectedPackages(reader interface { //nolint:funlen,gocognit
286290 }
287291 return nil , nil , fmt .Errorf ("unable to get affected packages for %s: %w" , vulnSpecs , err )
288292 }
293+
294+ unaffectedPkgs , err := reader .GetUnaffectedPackages (pkgSpec , & v6.GetPackageOptions {
295+ PreloadOS : true ,
296+ PreloadPackage : true ,
297+ PreloadPackageCPEs : false ,
298+ PreloadVulnerability : true ,
299+ PreloadBlob : true ,
300+ OSs : osSpecs ,
301+ Vulnerabilities : vulnSpecs ,
302+ AllowBroadCPEMatching : config .AllowBroadCPEMatching ,
303+ Limit : config .RecordLimit ,
304+ })
305+
306+ for i := range unaffectedPkgs {
307+ p := v6 .AffectedPackageHandle (unaffectedPkgs [i ])
308+ markUnaffected (& p .BlobValue )
309+ allAffectedPkgs = append (allAffectedPkgs , affectedPackageWithDecorations {
310+ AffectedPackageHandle : p ,
311+ })
312+ }
313+
314+ if err != nil {
315+ if errors .Is (err , v6 .ErrLimitReached ) {
316+ return allAffectedPkgs , allAffectedCPEs , err
317+ }
318+ return nil , nil , fmt .Errorf ("unable to get unaffected packages for %s: %w" , vulnSpecs , err )
319+ }
289320 }
290321
291322 if osSpecs .IsAny () {
@@ -319,8 +350,63 @@ func findAffectedPackages(reader interface { //nolint:funlen,gocognit
319350 }
320351 return nil , nil , fmt .Errorf ("unable to get affected cpes for %s: %w" , vulnSpecs , err )
321352 }
353+
354+ unaffectedCPEs , err := reader .GetUnaffectedCPEs (searchCPE , & v6.GetCPEOptions {
355+ PreloadCPE : true ,
356+ PreloadVulnerability : true ,
357+ PreloadBlob : true ,
358+ Vulnerabilities : vulnSpecs ,
359+ AllowBroadCPEMatching : config .AllowBroadCPEMatching ,
360+ Limit : config .RecordLimit ,
361+ })
362+
363+ for i := range unaffectedCPEs {
364+ p := v6 .AffectedCPEHandle (unaffectedCPEs [i ])
365+ if p .BlobValue != nil && len (p .BlobValue .Ranges ) > 0 {
366+ for r := range p .BlobValue .Ranges {
367+ p .BlobValue .Ranges [r ].Fix .Version += " (unaffected)"
368+ }
369+ } else {
370+ if p .BlobValue == nil {
371+ p .BlobValue = & v6.PackageBlob {}
372+ }
373+ p .BlobValue .Ranges = append (p .BlobValue .Ranges , v6.Range {
374+ Fix : & v6.Fix {
375+ Version : "unaffected" ,
376+ },
377+ })
378+ }
379+ allAffectedCPEs = append (allAffectedCPEs , affectedCPEWithDecorations {
380+ AffectedCPEHandle : p ,
381+ })
382+ }
383+
384+ if err != nil {
385+ if errors .Is (err , v6 .ErrLimitReached ) {
386+ return allAffectedPkgs , allAffectedCPEs , err
387+ }
388+ return nil , nil , fmt .Errorf ("unable to get affected cpes for %s: %w" , vulnSpecs , err )
389+ }
322390 }
323391 }
324392
325393 return allAffectedPkgs , allAffectedCPEs , nil
326394}
395+
396+ func markUnaffected (i * * v6.PackageBlob ) {
397+ if * i == nil {
398+ * i = & v6.PackageBlob {}
399+ }
400+ b := * i
401+ if len (b .Ranges ) > 0 {
402+ for r := range b .Ranges {
403+ b .Ranges [r ].Version .Constraint += " (unaffected)"
404+ }
405+ } else {
406+ b .Ranges = append (b .Ranges , v6.Range {
407+ Version : v6.Version {
408+ Constraint : "(unaffected)" ,
409+ },
410+ })
411+ }
412+ }
0 commit comments