From 2dcac8d4db801b919d244e526421842360266ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Sardin?= Date: Fri, 10 Jul 2026 11:06:25 +0200 Subject: [PATCH 1/2] fix(parser): kics-scan ignore-line/ignore-block misapplied in YAML files with resolved references --- pkg/kics/sink.go | 11 ++++ pkg/kics/sink_test.go | 63 +++++++++++++++++++ .../resolve_ignore_lines/docker-compose.yaml | 12 ++++ .../resolve_ignore_lines/included.yaml | 7 +++ .../resolve_ignore_lines/no-include.yaml | 10 +++ 5 files changed, 103 insertions(+) create mode 100644 test/fixtures/resolve_ignore_lines/docker-compose.yaml create mode 100644 test/fixtures/resolve_ignore_lines/included.yaml create mode 100644 test/fixtures/resolve_ignore_lines/no-include.yaml diff --git a/pkg/kics/sink.go b/pkg/kics/sink.go index ce7e054f26c..27dd684b65c 100644 --- a/pkg/kics/sink.go +++ b/pkg/kics/sink.go @@ -63,6 +63,17 @@ func (s *Service) sink(ctx context.Context, filename, scanID string, } s.Tracker.TrackFileFoundCountLines(linesResolved) + if len(documents.ResolvedFiles) > 0 { + // ignore lines were collected while parsing the resolved content, so they can have + // the lines from the resolved files; since results are reported on the original + // file lines, the lines ignore should be replaced with ones based on the original data + documents.IgnoreLines = model.GetIgnoreLines(&model.FileMetadata{ + FilePath: filename, + OriginalData: documents.Content, + LinesIgnore: documents.IgnoreLines, + }) + } + fileCommands := s.Parser.CommentsCommands(filename, *content) for idx, document := range documents.Docs { diff --git a/pkg/kics/sink_test.go b/pkg/kics/sink_test.go index d8119de692b..d8ae57293dd 100644 --- a/pkg/kics/sink_test.go +++ b/pkg/kics/sink_test.go @@ -1,10 +1,18 @@ package kics import ( + "bytes" + "context" "encoding/json" + "os" + "path/filepath" "testing" + "github.com/Checkmarx/kics/v2/internal/storage" + "github.com/Checkmarx/kics/v2/internal/tracker" "github.com/Checkmarx/kics/v2/pkg/model" + "github.com/Checkmarx/kics/v2/pkg/parser" + yamlParser "github.com/Checkmarx/kics/v2/pkg/parser/yaml" "github.com/stretchr/testify/require" ) @@ -149,3 +157,58 @@ func compareJSONLine(t *testing.T, test1 interface{}, test2 string) { require.NoError(t, err) require.JSONEq(t, test2, string(stringefiedJSON)) } + +// TestKics_sinkIgnoreLinesWithResolvedFiles ensures that the ignore lines stored in the +// file metadata keep the original file coordinates, even when the file references other +// files (e.g. a docker-compose "include") and its parsed content has shifted lines +func TestKics_sinkIgnoreLinesWithResolvedFiles(t *testing.T) { + tests := []struct { + name string + filePath string + wantIgnoreLines []int + wantResolvedFiles bool + }{ + { + name: "yaml with include should keep ignore lines on the original file coordinates", + filePath: filepath.Join("..", "..", "test", "fixtures", "resolve_ignore_lines", "docker-compose.yaml"), + wantIgnoreLines: []int{6, 7}, + wantResolvedFiles: true, + }, + { + name: "yaml without include should keep the parser ignore lines", + filePath: filepath.Join("..", "..", "test", "fixtures", "resolve_ignore_lines", "no-include.yaml"), + wantIgnoreLines: []int{4, 5}, + wantResolvedFiles: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + content, err := os.ReadFile(tt.filePath) + require.NoError(t, err) + + file := sinkFile(t, tt.filePath, content) + require.Equal(t, tt.wantResolvedFiles, len(file.ResolvedFiles) > 0) + require.Equal(t, tt.wantIgnoreLines, file.LinesIgnore) + }) + } +} + +func sinkFile(t *testing.T, filename string, content []byte) model.FileMetadata { + yamlOnlyParser, err := parser.NewBuilder().Add(&yamlParser.Parser{}).Build([]string{""}, []string{""}) + require.NoError(t, err) + + ciTracker, err := tracker.NewTracker(3) + require.NoError(t, err) + + s := &Service{ + Parser: yamlOnlyParser[0], + Storage: storage.NewMemoryStorage(), + Tracker: ciTracker, + MaxFileSize: 5, + } + err = s.sink(context.Background(), filename, "scanID", bytes.NewReader(content), make([]byte, mbConst), false, 15) + require.NoError(t, err) + require.Len(t, s.files, 1) + return s.files[0] +} diff --git a/test/fixtures/resolve_ignore_lines/docker-compose.yaml b/test/fixtures/resolve_ignore_lines/docker-compose.yaml new file mode 100644 index 00000000000..1693ab10ca3 --- /dev/null +++ b/test/fixtures/resolve_ignore_lines/docker-compose.yaml @@ -0,0 +1,12 @@ +include: + - included.yaml +services: + alpha: + image: alpine + # kics-scan ignore-line + ports: + - "1111:1111" + beta: + image: alpine + ports: + - "2222:2222" diff --git a/test/fixtures/resolve_ignore_lines/included.yaml b/test/fixtures/resolve_ignore_lines/included.yaml new file mode 100644 index 00000000000..4d05c815cde --- /dev/null +++ b/test/fixtures/resolve_ignore_lines/included.yaml @@ -0,0 +1,7 @@ +services: + rabbit: + image: rabbitmq:3 + environment: + K0: "0" + K1: "1" + K2: "2" diff --git a/test/fixtures/resolve_ignore_lines/no-include.yaml b/test/fixtures/resolve_ignore_lines/no-include.yaml new file mode 100644 index 00000000000..b354d4cf3d8 --- /dev/null +++ b/test/fixtures/resolve_ignore_lines/no-include.yaml @@ -0,0 +1,10 @@ +services: + alpha: + image: alpine + # kics-scan ignore-line + ports: + - "1111:1111" + beta: + image: alpine + ports: + - "2222:2222" From a33bef71105dc67f53f54013604fc1d08cbd6301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Sardin?= Date: Fri, 10 Jul 2026 11:09:14 +0200 Subject: [PATCH 2/2] refactor(secrets): remove redundant GetIgnoreLines call, now handled in the sink --- pkg/engine/secrets/inspector.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/engine/secrets/inspector.go b/pkg/engine/secrets/inspector.go index 36dfa4aab00..0db0d2118b0 100644 --- a/pkg/engine/secrets/inspector.go +++ b/pkg/engine/secrets/inspector.go @@ -631,10 +631,6 @@ func validateCustomSecretsQueriesID(allRegexQueries []RegexQuery) error { } func (c *Inspector) checkContent(i, idx int, basePaths []string, files model.FileMetadatas) { - // lines ignore can have the lines from the resolved files - // since inspector secrets only looks to original data, the lines ignore should be replaced - files[idx].LinesIgnore = model.GetIgnoreLines(&files[idx]) - wg := &sync.WaitGroup{} // check file content line by line if c.regexQueries[i].Multiline == (MultilineResult{}) {