From 1caf243d29ca14a808e0f50792f46be7bc823290 Mon Sep 17 00:00:00 2001 From: ChrisJr404 Date: Wed, 6 May 2026 10:51:41 -0400 Subject: [PATCH] fix(source): treat exclude paths with trailing slash as directories (#4892) A trailing slash on --exclude (e.g. './lib/') is dropped during pattern normalization but doublestar.Match still requires an exact string match, so the resulting pattern silently matches nothing and the directory is not excluded. Strip a trailing slash so './lib/' and './lib' behave the same. Fixes #4839 Signed-off-by: ChrisJr404 --- .../directorysource/directory_source.go | 3 +++ .../directorysource/directory_source_test.go | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) 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: "/",