diff --git a/internal/engine/eval/vulncheck/report.go b/internal/engine/eval/vulncheck/report.go
index 442a97f88c..c8f3e13784 100644
--- a/internal/engine/eval/vulncheck/report.go
+++ b/internal/engine/eval/vulncheck/report.go
@@ -80,6 +80,21 @@ const (
`
)
+const (
+ maliciousVulnFoundTemplate = `Malicious vulnerability found for dependency {{.Name}}:
+
+| ID | Summary | Details |
+|----|---------|---------|
+{{- range .Vulns}}
+| [{{.ID}}](https://osv.dev/vulnerability/{{.ID}}) | {{.Summary}} | {{.Details}} |
+{{- end}}
+
+Please review and remove this dependency immediately.`
+
+ maliciousVulnFoundFallbackFmt = `Malicious vulnerability found for dependency %s.
+Please review and remove this dependency immediately.", dep.Dep.Name)`
+)
+
const (
tableVulnerabilitiesHeaderName = "vulnerabilitiesTableHeader"
tableVulnerabilitiesHeader = `
Summary of vulnerabilities found
diff --git a/internal/engine/eval/vulncheck/review.go b/internal/engine/eval/vulncheck/review.go
index d101a9806d..e73f53bd45 100644
--- a/internal/engine/eval/vulncheck/review.go
+++ b/internal/engine/eval/vulncheck/review.go
@@ -16,11 +16,13 @@
package vulncheck
import (
+ "bytes"
"context"
"errors"
"fmt"
"io"
"strings"
+ "text/template"
"github.com/google/go-github/v63/github"
"github.com/rs/zerolog"
@@ -186,6 +188,41 @@ func newReviewPrHandler(
return handler, nil
}
+func getMaliciousVulns(vulns []Vulnerability) []Vulnerability {
+ var malicious []Vulnerability
+ for _, vuln := range vulns {
+ if strings.HasPrefix(vuln.ID, "MAL-") {
+ malicious = append(malicious, vuln)
+ }
+ }
+ return malicious
+}
+
+func handleMaliciousVulns(dep *pbinternal.PrDependencies_ContextualDependency, vulns []Vulnerability) string {
+ maliciousVulns := getMaliciousVulns(vulns)
+ if len(maliciousVulns) == 0 {
+ return ""
+ }
+
+ tmpl, err := template.New("maliciousVuln").Parse(maliciousVulnFoundTemplate)
+ if err != nil {
+ return fmt.Sprintf(maliciousVulnFoundFallbackFmt, dep.Dep.Name)
+ }
+ var buf bytes.Buffer
+ err = tmpl.Execute(&buf, struct {
+ Name string
+ Vulns []Vulnerability
+ }{
+ Name: dep.Dep.Name,
+ Vulns: maliciousVulns,
+ })
+ if err != nil {
+ return fmt.Sprintf(maliciousVulnFoundFallbackFmt, dep.Dep.Name)
+ }
+
+ return buf.String()
+}
+
func (ra *reviewPrHandler) trackVulnerableDep(
ctx context.Context,
dep *pbinternal.PrDependencies_ContextualDependency,
@@ -204,7 +241,10 @@ func (ra *reviewPrHandler) trackVulnerableDep(
case errors.Is(patch.GetFormatterMeta().pkgRegistryLookupError, ErrPkgNotFound):
body = pkgRepoInfoNotFound
case patch.GetFormatterMeta().pkgRegistryLookupError == nil:
- if !patch.HasPatchedVersion() {
+ maliciousBody := handleMaliciousVulns(dep, vulnResp.Vulns)
+ if maliciousBody != "" {
+ body = maliciousBody
+ } else if !patch.HasPatchedVersion() {
body = fmt.Sprintf(vulnFoundWithNoPatchFmt, dep.Dep.Name)
} else {
comment := patch.IndentedString(location.leadingWhitespace, location.line, dep.Dep)