tools/govulncheck-filter/main.go (70 lines of code) (raw):
package main
import (
"bufio"
"fmt"
"io"
"os"
"regexp"
"strings"
)
var (
vulnIDRegex = regexp.MustCompile("^Vulnerability #[0-9]{0,3}: (GO-[0-9]{4}-[0-9]{4})")
// If the `vulnerability` CI job fails due to an issue that the Gitaly team cannot directly patch, and the
// vulnerability is deemed non-critical, an exception can be added to the ignore list below. Please create a
// **confidential** issue using the "Ignored Vulnerability" template on gitlab-org/gitaly before adding a new
// entry here.
defaultIgnoreList = ignoreList{
"GO-2025-3563": {
GitLabIssueURL: "https://gitlab.com/gitlab-org/gitaly/-/issues/6703",
},
}
outputPrologue = `
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️
This check may have undergone filtering. The pipeline may be passing despite known vulnerabilities. See
./tools/govulnchecker-filter/main.go for the filtering rules.
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️
⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️
The following vulnerabilities were ignored if present:
`
)
type ignoreList map[string]struct {
GitLabIssueURL string
}
// FilteredVulncheck parses the human-readable output of the `govulncheck` tool and compares its list of affected
// vulnerabilities with an ignore list. An affected vulnerability is code which is imported/used by Gitaly, not code
// which is imported but never used, or code imported transitively by package dependencies which are never used.
// We parse the human-readable output instead of calling `govulncheck -json` because the latter does not provide a
// filtered view of vulnerabilities.
//
// IFF the set of ignored vulnerabilities is equal to the set of affected vulnerabilities, the tool returns an exit
// code of 0. Regardless of error, the original output from `govulncheck` is streamed to w.
func FilteredVulncheck(r io.Reader, w io.Writer, ignoreList ignoreList) (exitCode int, err error) {
looking := true
actualVulns := make(map[string]struct{})
scanner := bufio.NewScanner(r)
for scanner.Scan() {
text := scanner.Text()
_, _ = io.WriteString(w, text)
_, _ = io.WriteString(w, "\n")
// Keep capturing the original output, but skip further regex checking.
if !looking {
continue
}
if strings.HasPrefix(text, "=== Informational ===") {
// The rest of the output contains informational vulnerabilities and can be ignored.
looking = false
continue
}
matches := vulnIDRegex.FindStringSubmatch(text)
if len(matches) == 2 {
// matches contains the entire match and the group
actualVulns[matches[1]] = struct{}{}
}
}
if scanner.Err() != nil {
return exitCode, fmt.Errorf("read line: %w", scanner.Err())
}
for actualID := range actualVulns {
if _, ok := ignoreList[actualID]; !ok {
exitCode = 1
}
}
_, _ = io.WriteString(w, outputPrologue)
for id := range ignoreList {
_, _ = fmt.Fprintf(w, "- %s\n", id)
}
return exitCode, nil
}
func main() {
exitCode, err := FilteredVulncheck(os.Stdin, os.Stdout, defaultIgnoreList)
if err != nil {
panic(fmt.Errorf("filter govulncheck: %w", err))
}
os.Exit(exitCode)
}