1
0
mirror of https://github.com/siderolabs/kres.git synced 2026-02-05 09:45:35 +01:00

feat: add govulncheck wrapper

This wrapper enables excluding vulnerabilities to pass scans, if we are unaffected.

Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com>
This commit is contained in:
Mateusz Urbanek
2025-08-14 11:23:43 +02:00
parent 9f63e23bda
commit 696c7c7796
10 changed files with 223 additions and 9 deletions

View File

@@ -400,6 +400,10 @@ func (generate *Generate) CompileTemplates(output *template.Output) error {
WithLicenseText(generate.LicenseText).
NoOverwrite()
output.Define(govulncheckPath, templates.GoVulnCheck).
NoPreamble().
NoOverwrite()
return nil
}

View File

@@ -5,20 +5,26 @@
package golang
import (
"fmt"
"path/filepath"
"strings"
"github.com/siderolabs/kres/internal/dag"
"github.com/siderolabs/kres/internal/output/dockerfile"
"github.com/siderolabs/kres/internal/output/dockerfile/step"
"github.com/siderolabs/kres/internal/output/dockerignore"
"github.com/siderolabs/kres/internal/output/makefile"
"github.com/siderolabs/kres/internal/project/meta"
)
const govulncheckPath = "hack/govulncheck.sh"
// GoVulnCheck provides GoVulnCheck linter.
type GoVulnCheck struct { //nolint:govet
dag.BaseNode
Disabled bool `yaml:"disabled"`
Disabled bool `yaml:"disabled"`
Ignore []string `yaml:"ignore,omitempty"`
meta *meta.Options
projectPath string
@@ -34,6 +40,13 @@ func NewGoVulnCheck(meta *meta.Options, projectPath string) *GoVulnCheck {
}
}
// CompileDockerignore implements dockerignore.Compiler.
func (lint *GoVulnCheck) CompileDockerignore(output *dockerignore.Output) error {
output.AllowLocalPath(govulncheckPath)
return nil
}
// CompileMakefile implements makefile.Compiler.
func (lint *GoVulnCheck) CompileMakefile(output *makefile.Output) error {
if lint.Disabled {
@@ -54,12 +67,18 @@ func (lint *GoVulnCheck) CompileDockerfile(output *dockerfile.Output) error {
return nil
}
script := "./hack/govulncheck.sh ./..."
if len(lint.Ignore) != 0 {
script = fmt.Sprintf("./hack/govulncheck.sh -exclude '%s' ./...", strings.Join(lint.Ignore, ","))
}
output.Stage(lint.Name()).
Description("runs govulncheck").
From("base").
Step(step.Copy(govulncheckPath, "./hack/govulncheck.sh").Chmod(0o755)).
Step(step.WorkDir(filepath.Join("/src", lint.projectPath))).
Step(step.Script(
`govulncheck ./...`,
script,
).
MountCache(filepath.Join(lint.meta.CachePath, "go-build"), lint.meta.GitHubRepository).
MountCache(filepath.Join(lint.meta.GoPath, "pkg"), lint.meta.GitHubRepository),

View File

@@ -0,0 +1,86 @@
#!/bin/bash
# Source: https://github.com/tianon/gosu/blob/e157efb/govulncheck-with-excludes.sh
# Licensed under the Apache License, Version 2.0
# Copyright Tianon Gravi
set -Eeuo pipefail
exclude_arg=""
pass_args=()
while [[ $# -gt 0 ]]; do
case "$1" in
-exclude)
exclude_arg="$2"
shift 2
;;
*)
pass_args+=("$1")
shift
;;
esac
done
if [[ -n "$exclude_arg" ]]; then
excludeVulns="$(jq -nc --arg list "$exclude_arg" '$list | split(",")')"
else
excludeVulns="[]"
fi
export excludeVulns
# Debug print
echo "excludeVulns = $excludeVulns"
echo "Passing args: ${pass_args[*]}"
if ! command -v govulncheck > /dev/null; then
printf "govulncheck not installed"
exit 1
fi
if out="$(govulncheck "${pass_args[@]}")"; then
printf '%s\n' "$out"
exit 0
fi
json="$(govulncheck -json "${pass_args[@]}")"
vulns="$(jq <<<"$json" -cs '
(
map(
.osv // empty
| { key: .id, value: . }
)
| from_entries
) as $meta
# https://github.com/tianon/gosu/issues/144
| map(
.finding // empty
# https://github.com/golang/vuln/blob/3740f5cb12a3f93b18dbe200c4bcb6256f8586e2/internal/scan/template.go#L97-L104
| select((.trace[0].function // "") != "")
| .osv
)
| unique
| map($meta[.])
')"
if [ "$(jq <<<"$vulns" -r 'length')" -le 0 ]; then
printf '%s\n' "$out"
exit 1
fi
filtered="$(jq <<<"$vulns" -c '
(env.excludeVulns | fromjson) as $exclude
| map(select(
.id as $id
| $exclude | index($id) | not
))
')"
text="$(jq <<<"$filtered" -r 'map("- \(.id) (aka \(.aliases | join(", ")))\n\n\t\(.details | gsub("\n"; "\n\t"))") | join("\n\n")')"
if [ -z "$text" ]; then
printf 'No vulnerabilities found.\n'
exit 0
else
printf '%s\n' "$text"
exit 1
fi

View File

@@ -11,3 +11,8 @@ import _ "embed"
//
//go:embed version_go
var VersionGo string
// GoVulnCheck govulncheck.sh
//
//go:embed govulncheck.sh
var GoVulnCheck string

View File

@@ -202,7 +202,7 @@ func (toolchain *Toolchain) CompileDockerfile(output *dockerfile.Output) error {
From("--platform=${BUILDPLATFORM} ${TOOLCHAIN}")
if toolchain.Kind == ToolchainOfficial {
packages := []string{"add", "bash", "curl", "build-base", "protoc", "protobuf-dev"}
packages := []string{"add", "bash", "build-base", "curl", "jq", "protoc", "protobuf-dev"}
packages = append(packages, toolchain.ExtraPackages...)
// automatically add git if we know we're going to have to deal with private repos