blob: a4b382dc6d1df0bdf1c1fefe509e5d170326e6b9 [file] [log] [blame]
// Copyright 2022 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.
//go:build go1.18
// +build go1.18
package main
import (
func html(w io.Writer, r *vulncheck.Result, callStacks map[*vulncheck.Vuln][]vulncheck.CallStack, moduleVersions map[string]string, topPackages map[string]bool, vulnGroups [][]*vulncheck.Vuln) error {
tmpl, err := template.New("govulncheck").Funcs(template.FuncMap{
"funcName": funcName,
if err != nil {
return err
type callstack struct {
Summary string
Stack vulncheck.CallStack
type vuln struct {
ID string
PkgPath string
CurrentVersion string
FixedVersion string
Reference string
Details string
Stacks []callstack
var vulns []*vuln
for _, vg := range vulnGroups {
v0 := vg[0]
vn := &vuln{
ID: v0.OSV.ID,
PkgPath: v0.PkgPath,
CurrentVersion: moduleVersions[v0.ModPath],
FixedVersion: "v" + latestFixed(v0.OSV.Affected),
Reference: fmt.Sprintf("", v0.OSV.ID),
Details: v0.OSV.Details,
// Keep first call stack for each vuln.
for _, v := range vg {
if css := callStacks[v]; len(css) > 0 {
vn.Stacks = append(vn.Stacks, callstack{
Summary: summarizeCallStack(css[0], topPackages, v.PkgPath),
Stack: css[0],
vulns = append(vulns, vn)
return tmpl.Execute(w, vulns)
var templateSource = `
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>govulncheck Results</title>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
'Helvetica Neue', Arial, sans-serif;
list-style-type: none;
{{range .}}
<tr><td>Your version</td><td>{{.CurrentVersion}}</td></tr>
<tr><td>Fixed version</td><td>{{.FixedVersion}}</td></tr>
{{range .Stacks}}
{{range .Stack}}
<li>{{.Function | funcName}}</li>
No vulnerabilities found.