vulndb/internal/audit: filter affected fields in vulnerabilities

Filtering of vulnerabilities did not filter affected fields. This can
lead to false positives. For instance, filtering would deem a
vulnerability applicable to the current user code if a single affected
field applies to it. Other affected fields would be kept too even though
they might not apply to the code. If the code uses packages and symbols
related to these non-applicable affected fields, audit will report them.
The most prominent example of this is YAML vulnerability. This CL
filters affected fields as well.

Change-Id: I92a521a7eeadf12376a3c42f4fe69769ee1c3637
Reviewed-on: https://go-review.googlesource.com/c/exp/+/351454
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Julie Qiu <julie@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Trust: Julie Qiu <julie@golang.org>
diff --git a/vulndb/internal/audit/detect.go b/vulndb/internal/audit/detect.go
index fd88a6f..34735c9 100644
--- a/vulndb/internal/audit/detect.go
+++ b/vulndb/internal/audit/detect.go
@@ -190,6 +190,7 @@
 		// TODO: if modVersion == "", try vcs to get the version?
 		var filteredVulns []*osv.Entry
 		for _, v := range mod.vulns {
+			var filteredAffected []osv.Affected
 			for _, a := range v.Affected {
 				// A module version is affected if
 				//  - it is included in one of the affected version ranges
@@ -199,10 +200,15 @@
 				//  TODO: issue warning for "" cases above?
 				affected := modVersion != "" && a.Ranges.AffectsSemver(modVersion) && matchesPlatform(os, arch, a.EcosystemSpecific)
 				if affected {
-					filteredVulns = append(filteredVulns, v)
-					break
+					filteredAffected = append(filteredAffected, a)
 				}
 			}
+			if len(filteredAffected) == 0 {
+				continue
+			}
+			newV := *v
+			newV.Affected = filteredAffected
+			filteredVulns = append(filteredVulns, &newV)
 		}
 		filteredMod = append(filteredMod, modVulns{
 			mod:   module,
diff --git a/vulndb/internal/audit/detect_test.go b/vulndb/internal/audit/detect_test.go
index c3a18ef..5294b19 100644
--- a/vulndb/internal/audit/detect_test.go
+++ b/vulndb/internal/audit/detect_test.go
@@ -32,7 +32,10 @@
 				Version: "v1.0.0",
 			},
 			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
+				{ID: "a", Affected: []osv.Affected{
+					{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}},
+					{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.0.0"}}}}}, // should be filtered out
+				}},
 				{ID: "b", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows", "linux"}}}}},
 				{ID: "c", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64", "amd64"}}}}},
 				{ID: "d", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}}},
@@ -66,7 +69,10 @@
 				Version: "v1.2.0",
 			},
 			vulns: []*osv.Entry{
-				{ID: "l", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}, {EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
+				{ID: "l", Affected: []osv.Affected{
+					{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}, // should be filtered out
+					{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}},
+				}},
 			},
 		},
 	}
@@ -103,7 +109,7 @@
 				Version: "v1.2.0",
 			},
 			vulns: []*osv.Entry{
-				{ID: "l", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}, {EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
+				{ID: "l", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
 			},
 		},
 	}