internal/report: add skip_lint option for modules

Add the option to skip all lints for a certain module
by setting "skip_lint: true". This should only be used
in exceptional circumstances, such as when a module
is no longer served by the proxy but it possibly
still exists in the ecosystem.

Change-Id: I1f7f7f557bc6f6f3393b5e43b100ba7331d007c6
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/601915
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Tatiana Bradley <tatianabradley@google.com>
diff --git a/internal/report/lint.go b/internal/report/lint.go
index 7ea9534..2895c26 100644
--- a/internal/report/lint.go
+++ b/internal/report/lint.go
@@ -541,6 +541,10 @@
 }
 
 func (m *Module) lint(l *linter, r *Report, pc *proxy.Client) {
+	if m.SkipLint {
+		return
+	}
+
 	if m.Module == "" {
 		l.Error("no module name")
 	}
diff --git a/internal/report/lint_test.go b/internal/report/lint_test.go
index 605cf39..7f361cc 100644
--- a/internal/report/lint_test.go
+++ b/internal/report/lint_test.go
@@ -158,6 +158,18 @@
 			pc:           nil,
 			wantNumLints: 1,
 		},
+		{
+			name: "bad_module_skip_lint",
+			desc: "Module does not exist but skip lint is set.",
+			report: validReport(func(r *Report) {
+				r.Modules = append(r.Modules, &Module{
+					Module:   "golang.org/x/doesnotexist",
+					SkipLint: true,
+				})
+			}),
+			pc: pc,
+			// No lints.
+		},
 	} {
 		test := test
 		t.Run(test.name, func(t *testing.T) {
diff --git a/internal/report/report.go b/internal/report/report.go
index 68b495e..8de36b4 100644
--- a/internal/report/report.go
+++ b/internal/report/report.go
@@ -51,6 +51,10 @@
 	// the fix links found in the report's References field will be used.
 	// Only auto-added if the -update flag is passed to vulnreport.
 	FixLinks []string `yaml:"fix_links,omitempty"`
+	// Do not lint this module.
+	// Only for use in exceptional circumstances, such as when a malicious
+	// module has been deleted from the proxy entirely.
+	SkipLint bool `yaml:"skip_lint,omitempty"`
 }
 
 type Version struct {
diff --git a/internal/report/testdata/lint/TestLint/bad_module_skip_lint.txtar b/internal/report/testdata/lint/TestLint/bad_module_skip_lint.txtar
new file mode 100644
index 0000000..14c801c
--- /dev/null
+++ b/internal/report/testdata/lint/TestLint/bad_module_skip_lint.txtar
@@ -0,0 +1,24 @@
+Copyright 2024 The Go Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
+
+Test: TestLint/bad_module_skip_lint
+Description: Module does not exist but skip lint is set.
+
+-- data/reports/GO-0000-0000.yaml --
+id: GO-0000-0000
+modules:
+    - module: golang.org/x/net
+      vulnerable_at: 1.2.3
+      packages:
+        - package: golang.org/x/net/http2
+    - module: golang.org/x/doesnotexist
+      skip_lint: true
+summary: A summary of the issue in golang.org/x/net
+description: description
+cves:
+    - CVE-1234-0000
+review_status: REVIEWED
+
+-- golden --
+