Skip to content

Commit

Permalink
fix(cli): Handle empty ignore files more gracefully (#7962)
Browse files Browse the repository at this point in the history
Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
  • Loading branch information
simar7 and knqyf263 authored Nov 26, 2024
1 parent fbc42a0 commit 4cfb2a9
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
2 changes: 1 addition & 1 deletion pkg/flag/report_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
t.Run("Error on non existing ignore file", func(t *testing.T) {
t.Cleanup(viper.Reset)

setValue(flag.IgnoreFileFlag.ConfigName, string("doesntexist"))
setValue(flag.IgnoreFileFlag.ConfigName, "doesntexist")
f := &flag.ReportFlagGroup{
IgnoreFile: flag.IgnoreFileFlag.Clone(),
}
Expand Down
8 changes: 5 additions & 3 deletions pkg/result/ignore.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ func ParseIgnoreFile(ctx context.Context, ignoreFile string) (IgnoreConfig, erro
var conf IgnoreConfig
if _, err := os.Stat(ignoreFile); errors.Is(err, fs.ErrNotExist) {
// .trivyignore doesn't necessarily exist
log.Debug("Specified ignore file does not exist", log.String("file", ignoreFile))
return IgnoreConfig{}, nil
} else if filepath.Ext(ignoreFile) == ".yml" || filepath.Ext(ignoreFile) == ".yaml" {
conf, err = parseIgnoreYAML(ignoreFile)
Expand Down Expand Up @@ -218,16 +219,17 @@ func ParseIgnoreFile(ctx context.Context, ignoreFile string) (IgnoreConfig, erro

func parseIgnoreYAML(ignoreFile string) (IgnoreConfig, error) {
// Read .trivyignore.yaml
f, err := os.Open(ignoreFile)
b, err := os.ReadFile(ignoreFile)
if err != nil {
return IgnoreConfig{}, xerrors.Errorf("file open error: %w", err)
}
defer f.Close()
log.Debug("Found an ignore yaml", log.FilePath(ignoreFile))

// Parse the YAML content
// We have to use Unmarshal() due to go-yaml returning an error with Decode()
// ref: https://github.com/go-yaml/yaml/issues/805
var ignoreConfig IgnoreConfig
if err = yaml.NewDecoder(f).Decode(&ignoreConfig); err != nil {
if err = yaml.Unmarshal(b, &ignoreConfig); err != nil {
return IgnoreConfig{}, xerrors.Errorf("yaml decode error: %w", err)
}
return ignoreConfig, nil
Expand Down
72 changes: 72 additions & 0 deletions pkg/result/ignore_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package result

import (
"context"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseIgnoreFile(t *testing.T) {
t.Run("happy path valid config file", func(t *testing.T) {
got, err := ParseIgnoreFile(context.TODO(), "testdata/.trivyignore")
require.NoError(t, err)
assert.Equal(t, "testdata/.trivyignore", got.FilePath)

// IDs in .trivyignore are treated as IDs for all scanners
// as it is unclear which type of security issue they are
assert.Len(t, got.Vulnerabilities, 6)
assert.Len(t, got.Misconfigurations, 6)
assert.Len(t, got.Secrets, 6)
assert.Len(t, got.Licenses, 6)
})

t.Run("happy path valid YAML config file", func(t *testing.T) {
got, err := ParseIgnoreFile(context.TODO(), "testdata/.trivyignore.yaml")
require.NoError(t, err)
assert.Equal(t, "testdata/.trivyignore.yaml", got.FilePath)
assert.Len(t, got.Vulnerabilities, 5)
assert.Len(t, got.Misconfigurations, 3)
assert.Len(t, got.Secrets, 3)
assert.Len(t, got.Licenses, 1)
})

t.Run("empty YAML file passed", func(t *testing.T) {
f, err := os.CreateTemp("", "TestParseIgnoreFile-*.yaml")
require.NoError(t, err)
defer os.Remove(f.Name())

_, err = ParseIgnoreFile(context.TODO(), f.Name())
require.NoError(t, err)
})

t.Run("invalid YAML file passed", func(t *testing.T) {
f, err := os.CreateTemp("", "TestParseIgnoreFile-*.yaml")
require.NoError(t, err)
defer os.Remove(f.Name())
_, _ = f.WriteString("this file is not a yaml file")

got, err := ParseIgnoreFile(context.TODO(), f.Name())
assert.Contains(t, err.Error(), "yaml decode error")
assert.Empty(t, got)
})

t.Run("invalid file passed", func(t *testing.T) {
f, err := os.CreateTemp("", "TestParseIgnoreFile-*")
require.NoError(t, err)
defer os.Remove(f.Name())
_, _ = f.WriteString("this file is not a valid trivyignore file")

_, err = ParseIgnoreFile(context.TODO(), f.Name())
require.NoError(t, err) // TODO(simar7): We don't verify correctness, should we?
})

t.Run("non existing file passed", func(t *testing.T) {
got, err := ParseIgnoreFile(context.TODO(), "does-not-exist.yaml")
require.NoError(t, err)
assert.Empty(t, got)
})

}

0 comments on commit 4cfb2a9

Please sign in to comment.