From 6a18784fd02e57ba6e45b4e03eab3f86e68d3769 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 16 Sep 2024 10:29:17 +1200 Subject: [PATCH] feat: error if config file have unrecognized properties --- cmd/osv-scanner/__snapshots__/main_test.snap | 10 ++++ .../fixtures/osv-scanner-unknown-config.toml | 24 +++++++++ cmd/osv-scanner/main_test.go | 6 +++ fixtures/testdatainner/unknown-key-1.toml | 6 +++ fixtures/testdatainner/unknown-key-2.toml | 6 +++ fixtures/testdatainner/unknown-key-3.toml | 5 ++ fixtures/testdatainner/unknown-key-4.toml | 4 ++ fixtures/testdatainner/unknown-key-5.toml | 3 ++ fixtures/testdatainner/unknown-key-6.toml | 1 + fixtures/testdatainner/unknown-key-7.toml | 5 ++ pkg/config/config.go | 15 +++++- pkg/config/config_internal_test.go | 52 +++++++++++++++++++ 12 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 cmd/osv-scanner/fixtures/osv-scanner-unknown-config.toml create mode 100644 fixtures/testdatainner/unknown-key-1.toml create mode 100644 fixtures/testdatainner/unknown-key-2.toml create mode 100644 fixtures/testdatainner/unknown-key-3.toml create mode 100644 fixtures/testdatainner/unknown-key-4.toml create mode 100644 fixtures/testdatainner/unknown-key-5.toml create mode 100644 fixtures/testdatainner/unknown-key-6.toml create mode 100644 fixtures/testdatainner/unknown-key-7.toml diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap index 3b98ecc95a2..a063d47638a 100755 --- a/cmd/osv-scanner/__snapshots__/main_test.snap +++ b/cmd/osv-scanner/__snapshots__/main_test.snap @@ -396,6 +396,16 @@ Ignored invalid config file at: /fixtures/config-invalid/osv-scanner.to --- +[TestRun/config_files_cannot_have_unknown_keys - 1] + +--- + +[TestRun/config_files_cannot_have_unknown_keys - 2] +Failed to read config file: unknown keys in config file: RustVersionOverride, PackageOverrides.skip, PackageOverrides.license.skip +unknown keys in config file: RustVersionOverride, PackageOverrides.skip, PackageOverrides.license.skip + +--- + [TestRun/cyclonedx_1.4_output - 1] { "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/cmd/osv-scanner/fixtures/osv-scanner-unknown-config.toml b/cmd/osv-scanner/fixtures/osv-scanner-unknown-config.toml new file mode 100644 index 00000000000..9fa347cbf41 --- /dev/null +++ b/cmd/osv-scanner/fixtures/osv-scanner-unknown-config.toml @@ -0,0 +1,24 @@ +RustVersionOverride = "1.2.3" + +[[PackageOverrides]] +ecosystem = "npm" +skip = true +license.override = ["0BSD"] + +[[PackageOverrides]] +ecosystem = "Packagist" +license.override = ["0BSD"] + +[[PackageOverrides]] +ecosystem = "Alpine" +Name = "musl" +license.override = ["UNKNOWN"] + +[[PackageOverrides]] +ecosystem = "Alpine" +name = "musl-utils" +license.skip = true + +[[IgnoredVulns]] +id = "GO-2022-0274" +ignoreuntil = 2020-01-01 diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go index 899150473cc..c455914c288 100644 --- a/cmd/osv-scanner/main_test.go +++ b/cmd/osv-scanner/main_test.go @@ -329,6 +329,12 @@ func TestRun(t *testing.T) { args: []string{"", "--verbosity", "verbose", "./fixtures/config-invalid"}, exit: 127, }, + // config file with unknown keys + { + name: "config files cannot have unknown keys", + args: []string{"", "--config=./fixtures/osv-scanner-unknown-config.toml", "./fixtures/locks-many"}, + exit: 127, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/fixtures/testdatainner/unknown-key-1.toml b/fixtures/testdatainner/unknown-key-1.toml new file mode 100644 index 00000000000..9a95cfba3c0 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-1.toml @@ -0,0 +1,6 @@ +[[IgnoredVulns]] +id = "GHSA-jgvc-jfgh-rjvv" + +# whoops, should be ignoreUntil +ignoreUntilTime = 2024-08-02 +reason = "..." diff --git a/fixtures/testdatainner/unknown-key-2.toml b/fixtures/testdatainner/unknown-key-2.toml new file mode 100644 index 00000000000..7f3d82dfaef --- /dev/null +++ b/fixtures/testdatainner/unknown-key-2.toml @@ -0,0 +1,6 @@ +[[IgnoredVulns]] +id = "GHSA-jgvc-jfgh-rjvv" + +# whoops, should be ignoreUntil +ignoreUntiI = 2024-08-02 +reason = "..." diff --git a/fixtures/testdatainner/unknown-key-3.toml b/fixtures/testdatainner/unknown-key-3.toml new file mode 100644 index 00000000000..6d26931f834 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-3.toml @@ -0,0 +1,5 @@ +[[IgnoredVulns]] +id = "GHSA-jgvc-jfgh-rjvv" +ignoreUntil = 2024-08-02 +# whoops, should be reason +reasoning = "..." diff --git a/fixtures/testdatainner/unknown-key-4.toml b/fixtures/testdatainner/unknown-key-4.toml new file mode 100644 index 00000000000..9e362166c14 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-4.toml @@ -0,0 +1,4 @@ +[[PackageOverrides]] +ecosystem = "npm" +skip = true +license.override = ["0BSD"] diff --git a/fixtures/testdatainner/unknown-key-5.toml b/fixtures/testdatainner/unknown-key-5.toml new file mode 100644 index 00000000000..810839d3f45 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-5.toml @@ -0,0 +1,3 @@ +[[PackageOverrides]] +ecosystem = "npm" +license.skip = false diff --git a/fixtures/testdatainner/unknown-key-6.toml b/fixtures/testdatainner/unknown-key-6.toml new file mode 100644 index 00000000000..0e5d3d5da88 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-6.toml @@ -0,0 +1 @@ +RustVersionOverride = "1.2.3" diff --git a/fixtures/testdatainner/unknown-key-7.toml b/fixtures/testdatainner/unknown-key-7.toml new file mode 100644 index 00000000000..c4bc7c10984 --- /dev/null +++ b/fixtures/testdatainner/unknown-key-7.toml @@ -0,0 +1,5 @@ +RustVersionOverride = "1.2.3" + +[[PackageOverrides]] +ecosystem = "npm" +skip = true diff --git a/pkg/config/config.go b/pkg/config/config.go index f27b30ac62d..badee854d63 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "slices" + "strings" "time" "github.com/BurntSushi/toml" @@ -209,7 +210,19 @@ func normalizeConfigLoadPath(target string) (string, error) { // returning the Config object if successful or otherwise the error func tryLoadConfig(configPath string) (Config, error) { config := Config{LoadPath: configPath} - _, err := toml.DecodeFile(configPath, &config) + m, err := toml.DecodeFile(configPath, &config) + + unknownKeys := m.Undecoded() + + if len(unknownKeys) > 0 { + keys := make([]string, 0, len(unknownKeys)) + + for _, key := range unknownKeys { + keys = append(keys, key.String()) + } + + return config, fmt.Errorf("unknown keys in config file: %s", strings.Join(keys, ", ")) + } return config, err } diff --git a/pkg/config/config_internal_test.go b/pkg/config/config_internal_test.go index 84cc8862df6..6a59e5a58d0 100644 --- a/pkg/config/config_internal_test.go +++ b/pkg/config/config_internal_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "path/filepath" "reflect" "testing" @@ -100,6 +101,57 @@ func TestTryLoadConfig(t *testing.T) { } } +func TestTryLoadConfig_UnknownKeys(t *testing.T) { + t.Parallel() + + tests := []struct { + configPath string + unknownMsg string + }{ + { + configPath: "../../fixtures/testdatainner/unknown-key-1.toml", + unknownMsg: "IgnoredVulns.ignoreUntilTime", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-2.toml", + unknownMsg: "IgnoredVulns.ignoreUntiI", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-3.toml", + unknownMsg: "IgnoredVulns.reasoning", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-4.toml", + unknownMsg: "PackageOverrides.skip", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-5.toml", + unknownMsg: "PackageOverrides.license.skip", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-6.toml", + unknownMsg: "RustVersionOverride", + }, + { + configPath: "../../fixtures/testdatainner/unknown-key-7.toml", + unknownMsg: "RustVersionOverride, PackageOverrides.skip", + }, + } + + for _, testData := range tests { + _, err := tryLoadConfig(testData.configPath) + if err == nil { + t.Error("Config error not returned") + } + + wantMsg := fmt.Sprintf("unknown keys in config file: %v", testData.unknownMsg) + + if err.Error() != wantMsg { + t.Errorf("tryLoadConfig() error = '%v', want '%s'", err, wantMsg) + } + } +} + func TestConfig_ShouldIgnore(t *testing.T) { t.Parallel()