feat: Add TrivyConfig.VulnSeveritySources (Trivy's --vuln-severity-source) (#3943)

And default it to ["auto"] when unset, with an info log from applyDefaultValues.

Refactor CVE NewScanner to take *CVEConfig instead of separate DB repository
strings so the full Trivy block is available to the scanner.

Extend CLI and search tests for the new field and logged config; document
CVE/Trivy in examples/README and add examples/config-cve-trivy.json.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
This commit is contained in:
Andrei Aaron
2026-04-08 09:39:26 +03:00
committed by GitHub
parent c6289ec5ba
commit 451e7b8e47
15 changed files with 285 additions and 37 deletions
+72 -1
View File
@@ -967,7 +967,8 @@ func TestServeSearchEnabledDefaultCVEDB(t *testing.T) {
// The default config handling logic will convert the 1h interval to a 2h interval
substring := "\"Search\":{\"Enable\":true,\"CVE\":{\"UpdateInterval\":7200000000000,\"Trivy\":" +
"{\"DBRepository\":\"ghcr.io/aquasecurity/trivy-db\",\"JavaDBRepository\":\"ghcr.io/aquasecurity/trivy-java-db\"}}}"
"{\"DBRepository\":\"ghcr.io/aquasecurity/trivy-db\",\"JavaDBRepository\":\"ghcr.io/aquasecurity/trivy-java-db\"," +
"\"VulnSeveritySources\":[\"auto\"]}}}"
found, err := ReadLogFileAndSearchString(logPath, substring, readLogFileTimeout)
@@ -986,6 +987,76 @@ func TestServeSearchEnabledDefaultCVEDB(t *testing.T) {
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
})
Convey("VulnSeveritySources defaults to [auto] when trivy block is empty", t, func(c C) {
cfg := config.New()
// mapstructure omits an all-empty CVE; at least updateInterval (or any non-zero cve/trivy
// field) must be present for CVE to unmarshal non-nil before defaults run.
content := `{
"storage": { "rootDirectory": "/tmp/zot" },
"http": { "address": "127.0.0.1", "port": "8080" },
"extensions": {
"search": {
"enable": true,
"cve": { "updateInterval": "24h", "trivy": { } }
}
}
}`
configPath := MakeTempFileWithContent(t, "zot-test.json", content)
err := cli.LoadConfiguration(cfg, configPath)
So(err, ShouldBeNil)
So(cfg.Extensions, ShouldNotBeNil)
So(cfg.Extensions.Search, ShouldNotBeNil)
So(cfg.Extensions.Search.CVE, ShouldNotBeNil)
So(cfg.Extensions.Search.CVE.Trivy, ShouldNotBeNil)
So(cfg.Extensions.Search.CVE.Trivy.VulnSeveritySources, ShouldResemble, []string{"auto"})
})
Convey("VulnSeveritySources respects explicit list", t, func(c C) {
cfg := config.New()
content := `{
"storage": { "rootDirectory": "/tmp/zot" },
"http": { "address": "127.0.0.1", "port": "8080" },
"extensions": {
"search": {
"enable": true,
"cve": { "trivy": { "vulnSeveritySources": ["nvd", "ghsa"] } }
}
}
}`
configPath := MakeTempFileWithContent(t, "zot-test.json", content)
err := cli.LoadConfiguration(cfg, configPath)
So(err, ShouldBeNil)
So(cfg.Extensions.Search.CVE.Trivy.VulnSeveritySources, ShouldResemble, []string{"nvd", "ghsa"})
})
Convey("CVE with only updateInterval (no trivy key) gets VulnSeveritySources [auto]", t, func(c C) {
cfg := config.New()
content := `{
"storage": { "rootDirectory": "/tmp/zot" },
"http": { "address": "127.0.0.1", "port": "8080" },
"extensions": {
"search": {
"enable": true,
"cve": { "updateInterval": "24h" }
}
}
}`
configPath := MakeTempFileWithContent(t, "zot-test.json", content)
err := cli.LoadConfiguration(cfg, configPath)
So(err, ShouldBeNil)
So(cfg.Extensions.Search.CVE.Trivy, ShouldNotBeNil)
So(cfg.Extensions.Search.CVE.Trivy.VulnSeveritySources, ShouldResemble, []string{"auto"})
})
}
func TestServeSearchEnabledNoCVE(t *testing.T) {
+8
View File
@@ -891,6 +891,14 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, logge
config.Extensions.Search.CVE.Trivy.JavaDBRepository = defaultJavaDBDownloadURL
}
if len(config.Extensions.Search.CVE.Trivy.VulnSeveritySources) == 0 {
defaultVulnSeveritySources := []string{"auto"}
logger.Info().Strs("vulnSeveritySources", defaultVulnSeveritySources).Str("component", "config").
Msg("using default trivy vulnerability severity sources.")
config.Extensions.Search.CVE.Trivy.VulnSeveritySources = defaultVulnSeveritySources
}
}
}