internal/worker: prevent duplicates for GHSAs

This is a quick fix to prevent the worker from filing issues for
duplicate GHSAs. The check for duplicates should eventually be moved to
the triage stage.

For golang/go#54049

Change-Id: I902c64f032fc66c15b7fe62787ecb0520e446216
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/461237
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Tatiana Bradley <tatiana@golang.org>
diff --git a/internal/worker/worker.go b/internal/worker/worker.go
index e7e3bcd..ec52c30 100644
--- a/internal/worker/worker.go
+++ b/internal/worker/worker.go
@@ -365,6 +365,24 @@
 		if limit > 0 && numCreated >= limit {
 			break
 		}
+		// TODO(https://github.com/golang/go/issues/54049): Move this
+		// check to the triage step of the worker.
+		if isDuplicate(ctx, gr.GHSA, allReports) {
+			// Update the GHSARecord in the DB to reflect that the GHSA
+			// already has an advisory.
+			if err = st.RunTransaction(ctx, func(ctx context.Context, tx store.Transaction) error {
+				r, err := tx.GetGHSARecord(gr.GetID())
+				if err != nil {
+					return err
+				}
+				r.TriageState = store.TriageStateHasVuln
+				return tx.SetGHSARecord(r)
+			}); err != nil {
+				return err
+			}
+			// Do not create an issue.
+			continue
+		}
 		ref, err := createIssue(ctx, gr, client, allReports)
 		if err != nil {
 			return err
@@ -389,6 +407,16 @@
 	return nil
 }
 
+func isDuplicate(ctx context.Context, sa *ghsa.SecurityAdvisory, allReports map[string]*report.Report) bool {
+	r := report.GHSAToReport(sa, "")
+	for _, aliases := range report.XRef(r, allReports) {
+		if slices.Contains(aliases, sa.ID) {
+			return true
+		}
+	}
+	return false
+}
+
 func CreateGHSABody(sa *ghsa.SecurityAdvisory, allReports map[string]*report.Report) (body string, err error) {
 	r := report.GHSAToReport(sa, "")
 	rs, err := r.ToString()
diff --git a/internal/worker/worker_test.go b/internal/worker/worker_test.go
index b928082..9ea1683 100644
--- a/internal/worker/worker_test.go
+++ b/internal/worker/worker_test.go
@@ -175,10 +175,20 @@
 			},
 			TriageState: store.TriageStateAlias,
 		},
+		{
+			GHSA: &ghsa.SecurityAdvisory{
+				ID:          "g5",
+				Vulns:       []*ghsa.Vuln{{Package: "p1"}},
+				Identifiers: []ghsa.Identifier{{Type: "GHSA", Value: "g5"}},
+			},
+			TriageState: store.TriageStateNeedsIssue,
+		},
 	}
 	createGHSARecords(t, mstore, grs)
 
-	if err := CreateIssues(ctx, mstore, ic, map[string]*report.Report{}, 0); err != nil {
+	// Add an existing report with GHSA "g5".
+	allReports := map[string]*report.Report{"data/reports/GO-1999-0001": {GHSAs: []string{"g5"}}}
+	if err := CreateIssues(ctx, mstore, ic, allReports, 0); err != nil {
 		t.Fatal(err)
 	}
 
@@ -209,6 +219,9 @@
 	wantGHSARecs[0].TriageState = store.TriageStateIssueCreated
 	wantGHSARecs[0].IssueReference = "https://github.com/test-owner/test-repo/issues/1"
 
+	// A report already exists for GHSA "g5".
+	wantGHSARecs[4].TriageState = store.TriageStateHasVuln
+
 	gotGHSARecs := getGHSARecordsSorted(t, mstore)
 	fmt.Printf("%+v\n", gotGHSARecs[0])
 	if diff := cmp.Diff(wantGHSARecs, gotGHSARecs,