internal/vulns: disable display of vulns for stdlib pages at master

The resolved version for stdlib pages at master is a
v0-prefixed psuedoversion. The result is that all vulns
for stdlib pages that begin at v0 are listed as affecting
even though they may have been fixed in later versions of Go.

This change removes vuln data for stdlib pages when requested
version is master.

Fixes golang/go#57327.

Change-Id: Ie9df8cb25bc3126397a49af349d401d3a1e2e994
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/460817
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/internal/vulns/vulns.go b/internal/vulns/vulns.go
index 9265609..15ffb54 100644
--- a/internal/vulns/vulns.go
+++ b/internal/vulns/vulns.go
@@ -14,6 +14,7 @@
 	"golang.org/x/mod/semver"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/stdlib"
+	"golang.org/x/pkgsite/internal/version"
 	"golang.org/x/vuln/osv"
 )
 
@@ -48,12 +49,19 @@
 	return vs
 }
 
-func vulnsForPackage(ctx context.Context, modulePath, version, packagePath string, getVulnEntries VulnEntriesFunc) (_ []Vuln, err error) {
-	defer derrors.Wrap(&err, "vulns(%q, %q, %q)", modulePath, version, packagePath)
+func vulnsForPackage(ctx context.Context, modulePath, vers, packagePath string, getVulnEntries VulnEntriesFunc) (_ []Vuln, err error) {
+	defer derrors.Wrap(&err, "vulns(%q, %q, %q)", modulePath, vers, packagePath)
 
 	if getVulnEntries == nil {
 		return nil, nil
 	}
+	// Stdlib pages requested at master will map to a pseudo version that puts
+	// all vulns in range. We can't really tell you're at master so version.IsPseudo
+	// is the best we can do. The result is vulns won't be reported for a pseudoversion
+	// that refers to a commit that is in a vulnerable range.
+	if modulePath == stdlib.ModulePath && version.IsPseudo(vers) {
+		return nil, nil
+	}
 	if modulePath == stdlib.ModulePath && strings.HasPrefix(packagePath, "cmd/go") {
 		modulePath = vulnCmdGoModulePath
 	} else if modulePath == stdlib.ModulePath {
@@ -68,7 +76,7 @@
 	// package at this version.
 	var vulns []Vuln
 	for _, e := range entries {
-		if vuln, ok := entryVuln(e, modulePath, packagePath, version); ok {
+		if vuln, ok := entryVuln(e, modulePath, packagePath, vers); ok {
 			vulns = append(vulns, vuln)
 		}
 	}
@@ -107,10 +115,10 @@
 	return affected
 }
 
-func entryVuln(e *osv.Entry, modulePath, packagePath, version string) (Vuln, bool) {
+func entryVuln(e *osv.Entry, modulePath, packagePath, ver string) (Vuln, bool) {
 	for _, a := range e.Affected {
 		// a.Package.Name is Go "module" name. Go package path is a.EcosystemSpecific.Imports.Path.
-		if a.Package.Name != modulePath || !a.Ranges.AffectsSemver(version) {
+		if a.Package.Name != modulePath || !a.Ranges.AffectsSemver(ver) {
 			continue
 		}
 		if packageMatches := func() bool {
diff --git a/internal/vulns/vulns_test.go b/internal/vulns/vulns_test.go
index dd27adc..831e493 100644
--- a/internal/vulns/vulns_test.go
+++ b/internal/vulns/vulns_test.go
@@ -44,6 +44,21 @@
 			},
 		}},
 	}
+	stdlib := osv.Entry{
+		ID: "GO-2",
+		Affected: []osv.Affected{{
+			Package: osv.Package{Name: "stdlib"},
+			Ranges: []osv.AffectsRange{{
+				Type:   osv.TypeSemver,
+				Events: []osv.RangeEvent{{Introduced: "0"}, {Fixed: "1.19.4"}},
+			}},
+			EcosystemSpecific: osv.EcosystemSpecific{
+				Imports: []osv.EcosystemSpecificImport{{
+					Path: "net/http",
+				}},
+			},
+		}},
+	}
 
 	get := func(_ context.Context, modulePath string) ([]*osv.Entry, error) {
 		switch modulePath {
@@ -51,6 +66,8 @@
 			return nil, nil
 		case "bad.com", "unfixable.com":
 			return []*osv.Entry{&e}, nil
+		case "stdlib":
+			return []*osv.Entry{&stdlib}, nil
 		default:
 			return nil, fmt.Errorf("unknown module %q", modulePath)
 		}
@@ -89,6 +106,16 @@
 		{
 			"unfixable.com", "", "v1.999.999", []Vuln{{ID: "GO-1"}},
 		},
+		// Vulns for stdlib
+		{
+			"std", "net/http", "go1.19.3", []Vuln{{ID: "GO-2"}},
+		},
+		{
+			"std", "net/http", "v0.0.0-20230104211531-bae7d772e800", nil,
+		},
+		{
+			"std", "net/http", "go1.20", nil,
+		},
 	}
 	for _, tc := range testCases {
 		got := VulnsForPackage(ctx, tc.mod, tc.version, tc.pkg, get)