static/frontend/vuln,internal/osv: display info about unreviewed meaning on vuln page

For UNREVIEWED reports, display the word "Unreviewed" under the title,
and add a blurb to the feedback section explaining its meaning.

Currently, don't display anything special for a REVIEWED report. This is the
default.

Change-Id: I43ad7c324f6712a22a035c4aac725808cd50e7c3
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/586101
Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
kokoro-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/osv/affected.go b/internal/osv/affected.go
index 4976bd2..d691ba3 100644
--- a/internal/osv/affected.go
+++ b/internal/osv/affected.go
@@ -33,3 +33,7 @@
 	}
 	return false
 }
+
+func (e *Entry) IsUnreviewed() bool {
+	return e.DatabaseSpecific.ReviewStatus == ReviewStatusUnreviewed
+}
diff --git a/internal/osv/osv.go b/internal/osv/osv.go
index a7bb639..1ffa352 100644
--- a/internal/osv/osv.go
+++ b/internal/osv/osv.go
@@ -233,4 +233,6 @@
 	// The URL of the Go advisory for this vulnerability, of the form
 	// "https://pkg.go.dev/GO-YYYY-XXXX".
 	URL string `json:"url,omitempty"`
+	// The review status of this report (UNREVIEWED or REVIEWED).
+	ReviewStatus ReviewStatus `json:"review_status,omitempty"`
 }
diff --git a/internal/osv/review_status.go b/internal/osv/review_status.go
new file mode 100644
index 0000000..7185e18
--- /dev/null
+++ b/internal/osv/review_status.go
@@ -0,0 +1,67 @@
+// 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.
+
+package osv
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type ReviewStatus int
+
+const (
+	ReviewStatusUnknown ReviewStatus = iota
+	ReviewStatusUnreviewed
+	ReviewStatusReviewed
+)
+
+var statusStrs = []string{
+	ReviewStatusUnknown:    "",
+	ReviewStatusUnreviewed: "UNREVIEWED",
+	ReviewStatusReviewed:   "REVIEWED",
+}
+
+func (r ReviewStatus) String() string {
+	if !r.IsValid() {
+		return fmt.Sprintf("INVALID(%d)", r)
+	}
+	return statusStrs[r]
+}
+
+func ReviewStatusValues() []string {
+	return statusStrs[1:]
+}
+
+func (r ReviewStatus) IsValid() bool {
+	return int(r) >= 0 && int(r) < len(statusStrs)
+}
+
+func ToReviewStatus(s string) (ReviewStatus, bool) {
+	for stat, str := range statusStrs {
+		if s == str {
+			return ReviewStatus(stat), true
+		}
+	}
+	return 0, false
+}
+
+func (r ReviewStatus) MarshalJSON() ([]byte, error) {
+	if !r.IsValid() {
+		return nil, fmt.Errorf("MarshalJSON: unrecognized review status: %d", r)
+	}
+	return json.Marshal(r.String())
+}
+
+func (r *ReviewStatus) UnmarshalJSON(b []byte) error {
+	var s string
+	if err := json.Unmarshal(b, &s); err != nil {
+		return err
+	}
+	if rs, ok := ToReviewStatus(s); ok {
+		*r = rs
+		return nil
+	}
+	return fmt.Errorf("UnmarshalJSON: unrecognized review status: %s", s)
+}
diff --git a/static/frontend/vuln/entry/entry.tmpl b/static/frontend/vuln/entry/entry.tmpl
index 0bbe0e7..c749395 100644
--- a/static/frontend/vuln/entry/entry.tmpl
+++ b/static/frontend/vuln/entry/entry.tmpl
@@ -138,6 +138,11 @@
     </ul>
   {{end}}
   <h2>Feedback</h2>
+  {{if $e.IsUnreviewed}}
+    <div>
+    This report is <a href="https://go.dev/doc/security/vuln/database#database-specificreview-status">unreviewed</a>. It was automatically generated from a third-party source and its details have not been verified by the Go team. 
+    </div>
+  {{end}}
   <div>
     See anything missing or incorrect?
     <a target="_blank" rel="noopener" href="https://github.com/golang/vulndb/issues/new?assignees=&labels=Needs+Triage%2CSuggested+Edit&template=suggest_edit.yaml&title=x%2Fvulndb%3A+suggestion+regarding+{{$e.ID}}&report={{$e.ID}}">
diff --git a/static/frontend/vuln/vuln.tmpl b/static/frontend/vuln/vuln.tmpl
index 65b4c39..3315b7e 100644
--- a/static/frontend/vuln/vuln.tmpl
+++ b/static/frontend/vuln/vuln.tmpl
@@ -54,6 +54,9 @@
       {{with .Withdrawn}}
         <li class="go-textSubtle">Withdrawn: {{.Format "Jan 02, 2006"}}</li>
       {{end}}
+      {{if .IsUnreviewed}}
+        <li class="go-textSubtle">Unreviewed</li>
+      {{end}}
     </ul>
 {{end}}
 
diff --git a/tests/screentest/testdata/ci/vuln-540x1080.a.png b/tests/screentest/testdata/ci/vuln-540x1080.a.png
index 299f02b..64e166f 100644
--- a/tests/screentest/testdata/ci/vuln-540x1080.a.png
+++ b/tests/screentest/testdata/ci/vuln-540x1080.a.png
Binary files differ
diff --git a/tests/screentest/testdata/ci/vuln-entry-unreviewed-540x1080.a.png b/tests/screentest/testdata/ci/vuln-entry-unreviewed-540x1080.a.png
index cb793e0..e8dc240 100644
--- a/tests/screentest/testdata/ci/vuln-entry-unreviewed-540x1080.a.png
+++ b/tests/screentest/testdata/ci/vuln-entry-unreviewed-540x1080.a.png
Binary files differ
diff --git a/tests/screentest/testdata/ci/vuln-entry-unreviewed.a.png b/tests/screentest/testdata/ci/vuln-entry-unreviewed.a.png
index 368df04..e54beb7 100644
--- a/tests/screentest/testdata/ci/vuln-entry-unreviewed.a.png
+++ b/tests/screentest/testdata/ci/vuln-entry-unreviewed.a.png
Binary files differ
diff --git a/tests/screentest/testdata/ci/vuln-list-540x1080.a.png b/tests/screentest/testdata/ci/vuln-list-540x1080.a.png
index 29f4413..195972f 100644
--- a/tests/screentest/testdata/ci/vuln-list-540x1080.a.png
+++ b/tests/screentest/testdata/ci/vuln-list-540x1080.a.png
Binary files differ
diff --git a/tests/screentest/testdata/ci/vuln-list.a.png b/tests/screentest/testdata/ci/vuln-list.a.png
index f769307..9215518 100644
--- a/tests/screentest/testdata/ci/vuln-list.a.png
+++ b/tests/screentest/testdata/ci/vuln-list.a.png
Binary files differ
diff --git a/tests/screentest/testdata/ci/vuln.a.png b/tests/screentest/testdata/ci/vuln.a.png
index d1a8403..7409625 100644
--- a/tests/screentest/testdata/ci/vuln.a.png
+++ b/tests/screentest/testdata/ci/vuln.a.png
Binary files differ