This probably isn't production-ready code.
Unless otherwise specified below, this is just a snippet of some lightweight code. The following code is probably too small for a full repo.
This is a small snippet showcasing a possibility of getting data out of govulncheck for usage in Go apps. It was inspired by this Bluesky thread.
For demo purposes, run with GOTOOLCHAIN=go1.24.1 go run main.go to get the http request smuggling vuln.
Take the "not production quality" warning to heart. This is not production quality code, but it's a good starting point for exploring the capabilities of govulncheck.
main.go #
1package main
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "log"
9 "net/http"
10 "os"
11 "runtime"
12
13 "github.com/golang-jwt/jwt/v5"
14 "golang.org/x/vuln/scan"
15)
16
17type trace struct {
18 Module string `json:"module"`
19 Package string `json:"package,omitempty"`
20 Version string `json:"version"`
21}
22
23type Finding struct {
24 OSV string `json:"osv"`
25 FixedVersion string `json:"fixed_version"`
26 Trace []trace `json:"trace"`
27}
28
29type OSVEntry struct {
30 SchemaVersion string `json:"schema_version"`
31 ID string `json:"id"`
32 Modified string `json:"modified"`
33 Published string `json:"published"`
34 Aliases []string `json:"aliases"`
35 Summary string `json:"summary"`
36 Details string `json:"details"`
37 Affected []struct {
38 Package struct {
39 Name string `json:"name"`
40 Ecosystem string `json:"ecosystem"`
41 } `json:"package"`
42 Ranges []struct {
43 Type string `json:"type"`
44 Events []struct {
45 Introduced string `json:"introduced,omitempty"`
46 Fixed string `json:"fixed,omitempty"`
47 } `json:"events"`
48 } `json:"ranges"`
49 EcosystemSpecific struct {
50 Imports []struct {
51 Path string `json:"path"`
52 Symbols []string `json:"symbols"`
53 } `json:"imports"`
54 } `json:"ecosystem_specific"`
55 } `json:"affected"`
56 References []struct {
57 Type string `json:"type"`
58 URL string `json:"url"`
59 } `json:"references"`
60 Credits []struct {
61 Name string `json:"name"`
62 } `json:"credits"`
63 DatabaseSpecific struct {
64 URL string `json:"url"`
65 ReviewStatus string `json:"review_status"`
66 } `json:"database_specific"`
67}
68
69type wrapper struct {
70 Finding *Finding `json:"finding"`
71 OSV *OSVEntry `json:"osv"`
72}
73
74func main() {
75 fmt.Println(runtime.Version())
76 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
77 fmt.Fprintln(w, "OK")
78 })
79
80 go func() {
81 // This uses net/http’s internal chunked encoding parser
82 // vulnerable to GO-2025-3563 in versions < 1.23.8 and < 1.24.2
83 err := http.ListenAndServe(":8080", nil)
84 if err != nil {
85 panic(err)
86 }
87 }()
88
89 // demo vuln
90 _ = jwt.ClaimStrings{}
91
92 osvMap := make(map[string]OSVEntry)
93
94 var out bytes.Buffer
95
96 cmd := scan.Command(context.Background(), "-json", "./...")
97 cmd.Stdout = &out
98
99 err := cmd.Start()
100 if err == nil {
101 err = cmd.Wait()
102 }
103
104 dec := json.NewDecoder(&out)
105 dec.UseNumber()
106
107 for dec.More() {
108 var obj wrapper
109 if err := dec.Decode(&obj); err != nil {
110 fmt.Fprintln(os.Stderr, "failed to decode:", err)
111 continue
112 }
113
114 if obj.OSV != nil {
115 osvMap[obj.OSV.ID] = *obj.OSV
116 continue
117 }
118
119 if obj.Finding == nil {
120 continue
121 }
122
123 mappedVuln, ok := osvMap[obj.Finding.OSV]
124
125 if !ok {
126 log.Println("Couldn't find OSV", obj.Finding.OSV)
127 continue
128 }
129
130 fmt.Println("--- VULN ---")
131 fmt.Printf("Name: %s\n", mappedVuln.Summary)
132 fmt.Printf("Fixed in: %s\n", obj.Finding.FixedVersion)
133 printTrace(obj.Finding.Trace)
134 fmt.Println("--- END VULN ---")
135 }
136
137 switch err := err.(type) {
138 case nil:
139 case interface{ ExitCode() int }:
140 os.Exit(err.ExitCode())
141 default:
142 fmt.Fprintln(os.Stderr, err)
143 os.Exit(1)
144 }
145}
146
147func printTrace(trace []trace) {
148 for i, t := range trace {
149 if t.Package != "" {
150 fmt.Printf(" [%d] %s@%s (%s)\n", i+1, t.Package, t.Version, t.Module)
151 } else {
152 fmt.Printf(" [%d] %s@%s\n", i+1, t.Module, t.Version)
153 }
154 }
155}
go.mod #
1module github.com/kvizdos/vulncheck-test
2go 1.24.1
3toolchain go1.23.0
4require golang.org/x/vuln v1.1.4
5require (
6 github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
7 golang.org/x/mod v0.22.0 // indirect
8 golang.org/x/sync v0.10.0 // indirect
9 golang.org/x/sys v0.29.0 // indirect
10 golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect
11 golang.org/x/tools v0.29.0 // indirect
12)
give me some feedback on bluesky: @kv.codes