diff --git a/syft/source/directorysource/directory_source.go b/syft/source/directorysource/directory_source.go index e4f79eee4..dcbbeaa62 100644 --- a/syft/source/directorysource/directory_source.go +++ b/syft/source/directorysource/directory_source.go @@ -145,6 +145,9 @@ func GetDirectoryExclusionFunctions(root string, exclusions []string) ([]fileres // check exclusions for supported paths, these are all relative to the "scan root" if strings.HasPrefix(exclusion, "./") || strings.HasPrefix(exclusion, "*/") || strings.HasPrefix(exclusion, "**/") { exclusion = strings.TrimPrefix(exclusion, "./") + // a trailing slash signals a directory but is otherwise discarded by doublestar.Match, + // causing the pattern to silently match nothing (see issue #4839) + exclusion = strings.TrimSuffix(exclusion, "/") exclusions[idx] = root + exclusion } else { errors = append(errors, exclusion) diff --git a/syft/source/directorysource/directory_source_test.go b/syft/source/directorysource/directory_source_test.go index aac93a88d..fc4160e58 100644 --- a/syft/source/directorysource/directory_source_test.go +++ b/syft/source/directorysource/directory_source_test.go @@ -175,6 +175,18 @@ func Test_DirectorySource_Exclusions(t *testing.T) { }, exclusions: []string{"./target"}, }, + { + input: "testdata/image-simple", + desc: "exclude explicit directory with trailing slash (issue #4839)", + glob: "**", + expected: []string{ + "Dockerfile", + "file-1.txt", + "file-2.txt", + //"target/really/nested/file-3.txt", // explicitly skipped + }, + exclusions: []string{"./target/"}, + }, { input: "testdata/image-simple", desc: "exclude explicit file relative to the root", @@ -329,6 +341,14 @@ func Test_getDirectoryExclusionFunctions_crossPlatform(t *testing.T) { finfo: file.ManualInfo{ModeValue: os.ModeDir}, walkHint: fs.SkipDir, }, + { + desc: "directory exclusion with trailing slash (issue #4839)", + root: "/usr/var", + path: "/usr/var/lib", + exclude: "./lib/", + finfo: file.ManualInfo{ModeValue: os.ModeDir}, + walkHint: fs.SkipDir, + }, { desc: "no file info", root: "/",