internal/scan: text output allows module level vulns

This change updates the text handler for govulncheck to allow for (and
make explicit when) one has vulnerabilities that are only required at a
module level but aren't called or imported.

Change-Id: Iadaf8cbffae3d0b66d8dc8497304f7a5b6aaebe5
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/528095
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/cmd/govulncheck/testdata/convert_text.ct b/cmd/govulncheck/testdata/convert_text.ct
index 5e4d460..8275005 100644
--- a/cmd/govulncheck/testdata/convert_text.ct
+++ b/cmd/govulncheck/testdata/convert_text.ct
@@ -27,10 +27,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-2021-0054
     Due to improper bounds checking, maliciously crafted JSON objects can cause
diff --git a/cmd/govulncheck/testdata/source_informational_text.ct b/cmd/govulncheck/testdata/source_informational_text.ct
index 1e6e36c..cf9f0fd 100644
--- a/cmd/govulncheck/testdata/source_informational_text.ct
+++ b/cmd/govulncheck/testdata/source_informational_text.ct
@@ -5,10 +5,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-2021-0265
     A maliciously crafted path can cause Get and other query functions to
diff --git a/cmd/govulncheck/testdata/source_vuln_text.ct b/cmd/govulncheck/testdata/source_vuln_text.ct
index 9016385..c296cdb 100644
--- a/cmd/govulncheck/testdata/source_vuln_text.ct
+++ b/cmd/govulncheck/testdata/source_vuln_text.ct
@@ -27,10 +27,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-2021-0054
     Due to improper bounds checking, maliciously crafted JSON objects can cause
@@ -78,10 +79,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-2021-0054
     Due to improper bounds checking, maliciously crafted JSON objects can cause
diff --git a/cmd/govulncheck/testdata/usage.ct b/cmd/govulncheck/testdata/usage.ct
index 778aec8..8a8dbe8 100644
--- a/cmd/govulncheck/testdata/usage.ct
+++ b/cmd/govulncheck/testdata/usage.ct
@@ -47,4 +47,4 @@
 
 No vulnerabilities found.
 
-Share feedback at https://go.dev/s/govulncheck-feedback.
\ No newline at end of file
+Share feedback at https://go.dev/s/govulncheck-feedback.
diff --git a/internal/scan/testdata/no-vulns.txt b/internal/scan/testdata/no-vulns.txt
index 45389ff..083c126 100644
--- a/internal/scan/testdata/no-vulns.txt
+++ b/internal/scan/testdata/no-vulns.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 0 vulnerabilities in packages that you import, but there are no
+call stacks leading to the use of these vulnerabilities. You may not
+need to take any action. There is also 1 vulnerability in modules
+that you require that is neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-0000-0001
     Third-party vulnerability
diff --git a/internal/scan/testdata/platform-all.json b/internal/scan/testdata/platform-all.json
index 4022863..afc6e37 100644
--- a/internal/scan/testdata/platform-all.json
+++ b/internal/scan/testdata/platform-all.json
@@ -23,7 +23,8 @@
     "trace": [
       {
         "module": "golang.org/vmod",
-        "version": "v0.0.1"
+        "version": "v0.0.1",
+        "package": "golang.org/vmod"
       }
     ]
   }
diff --git a/internal/scan/testdata/platform-all.txt b/internal/scan/testdata/platform-all.txt
index d3ae80b..4a2a06d 100644
--- a/internal/scan/testdata/platform-all.txt
+++ b/internal/scan/testdata/platform-all.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: All
 
diff --git a/internal/scan/testdata/platform-one-arch-only.json b/internal/scan/testdata/platform-one-arch-only.json
index a64db90..ec1c0c3 100644
--- a/internal/scan/testdata/platform-one-arch-only.json
+++ b/internal/scan/testdata/platform-one-arch-only.json
@@ -49,7 +49,8 @@
     "trace": [
       {
         "module": "golang.org/vmod",
-        "version": "v0.0.1"
+        "version": "v0.0.1",
+        "package": "golang.org/vmod"
       }
     ]
   }
diff --git a/internal/scan/testdata/platform-one-arch-only.txt b/internal/scan/testdata/platform-one-arch-only.txt
index 81283df..ad5cadf 100644
--- a/internal/scan/testdata/platform-one-arch-only.txt
+++ b/internal/scan/testdata/platform-one-arch-only.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: one-arch-only
 
diff --git a/internal/scan/testdata/platform-one-import.json b/internal/scan/testdata/platform-one-import.json
index a3f0979..aba7459 100644
--- a/internal/scan/testdata/platform-one-import.json
+++ b/internal/scan/testdata/platform-one-import.json
@@ -54,7 +54,8 @@
     "trace": [
       {
         "module": "golang.org/vmod",
-        "version": "v0.0.1"
+        "version": "v0.0.1",
+        "package": "golang.org/vmod"
       }
     ]
   }
diff --git a/internal/scan/testdata/platform-one-import.txt b/internal/scan/testdata/platform-one-import.txt
index 9f372a7..23cf2a1 100644
--- a/internal/scan/testdata/platform-one-import.txt
+++ b/internal/scan/testdata/platform-one-import.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: one-import
 
diff --git a/internal/scan/testdata/platform-two-imports.json b/internal/scan/testdata/platform-two-imports.json
index d65b6cb..b40758b 100644
--- a/internal/scan/testdata/platform-two-imports.json
+++ b/internal/scan/testdata/platform-two-imports.json
@@ -60,7 +60,8 @@
     "trace": [
       {
         "module": "golang.org/vmod",
-        "version": "v0.0.1"
+        "version": "v0.0.1",
+        "package": "golang.org/vmod"
       }
     ]
   }
diff --git a/internal/scan/testdata/platform-two-imports.txt b/internal/scan/testdata/platform-two-imports.txt
index 554e5f8..9336b93 100644
--- a/internal/scan/testdata/platform-two-imports.txt
+++ b/internal/scan/testdata/platform-two-imports.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: two-imports
 
diff --git a/internal/scan/testdata/platform-two-os-only.json b/internal/scan/testdata/platform-two-os-only.json
index f78f3d8..103edac 100644
--- a/internal/scan/testdata/platform-two-os-only.json
+++ b/internal/scan/testdata/platform-two-os-only.json
@@ -49,7 +49,8 @@
     "trace": [
       {
         "module": "golang.org/vmod",
-        "version": "v0.0.1"
+        "version": "v0.0.1",
+        "package": "golang.org/vmod"
       }
     ]
   }
diff --git a/internal/scan/testdata/platform-two-os-only.txt b/internal/scan/testdata/platform-two-os-only.txt
index d3d6b18..e9ff27a 100644
--- a/internal/scan/testdata/platform-two-os-only.txt
+++ b/internal/scan/testdata/platform-two-os-only.txt
@@ -1,9 +1,10 @@
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: two-os-only
 
diff --git a/internal/scan/testdata/source.txt b/internal/scan/testdata/source.txt
index 5278bc8..d649eaf 100644
--- a/internal/scan/testdata/source.txt
+++ b/internal/scan/testdata/source.txt
@@ -10,10 +10,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-0000-0002
     Stdlib vulnerability
diff --git a/internal/scan/testdata/source_traces.txt b/internal/scan/testdata/source_traces.txt
index 7155ef3..c7bc846 100644
--- a/internal/scan/testdata/source_traces.txt
+++ b/internal/scan/testdata/source_traces.txt
@@ -12,10 +12,11 @@
 
 === Informational ===
 
-Found 1 vulnerability in packages that you import, but there are no call
-stacks leading to the use of this vulnerability. You may not need to
-take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
-for details.
+Found 1 vulnerability in packages that you import, but there are no
+call stacks leading to the use of this vulnerability. You may not
+need to take any action. There are also 0 vulnerabilities in modules
+that you require that are neither imported nor called.
+See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
 
 Vulnerability #1: GO-0000-0002
     Stdlib vulnerability
diff --git a/internal/scan/text.go b/internal/scan/text.go
index 4afcf3f..0586336 100644
--- a/internal/scan/text.go
+++ b/internal/scan/text.go
@@ -136,22 +136,30 @@
 func (h *TextHandler) byVulnerability(findings []*findingSummary) {
 	byVuln := groupByVuln(findings)
 	called := 0
+	onlyImported := 0
 	for _, findings := range byVuln {
 		if isCalled(findings) {
 			h.vulnerability(called, findings)
 			called++
+		} else if isImported(findings) {
+			onlyImported++
 		}
 	}
-	unCalled := len(byVuln) - called
-	if unCalled == 0 {
+	onlyRequired := len(byVuln) - (called + onlyImported)
+	if onlyImported+onlyRequired == 0 {
 		return
 	}
 	h.style(sectionStyle, "=== Informational ===\n")
-	h.print("\nFound ", unCalled)
-	h.print(choose(unCalled == 1, ` vulnerability`, ` vulnerabilities`))
-	h.print(" in packages that you import, but there are no call\nstacks leading to the use of ")
-	h.print(choose(unCalled == 1, `this vulnerability`, `these vulnerabilities`))
-	h.print(". You may not need to\ntake any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck\nfor details.\n\n")
+	h.print("\nFound ", onlyImported)
+	h.print(choose(onlyImported == 1, ` vulnerability`, ` vulnerabilities`))
+	h.print(" in packages that you import, but there are no\ncall stacks leading to the use of ")
+	h.print(choose(onlyImported == 1, `this vulnerability`, `these vulnerabilities`))
+	h.print(". You may not\nneed to take any action. ")
+	h.print("There ", choose(onlyRequired == 1, `is`, `are`), " also ", onlyRequired)
+	h.print(choose(onlyRequired == 1, ` vulnerability`, ` vulnerabilities`))
+	h.print(" in modules\nthat you require that")
+	h.print(choose(onlyRequired == 1, ` is `, ` are `), "neither imported nor called.\n")
+	h.print("See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.\n\n")
 	index := 0
 	for _, findings := range byVuln {
 		if !isCalled(findings) {