What happened:
A directory excluded with --exclude is still indexed and cataloged when a symlink elsewhere points into it.
Exclusions are matched per-path against the paths being indexed and do not consider symlink resolution.
Ex: Matching /boot hits only the /boot directory entry itself.
Indexing can travel to /boot/grub2/grub.cfg via symlink on an un excluded path without ever visiting /boot.
Steps to reproduce the issue:
mkdir -p /tmp/repro/boot/grub2 /tmp/repro/etc
echo menuentry > /tmp/repro/boot/grub2/grub.cfg
ln -s ../boot/grub2/grub.cfg /tmp/repro/etc/grub2.cfg
syft scan dir:/tmp/repro --exclude ./boot -o json | grep grub
Anything else we need to know?:
Quick test in syft/source/directorysource/ can show the failure:
func Test_excludeVsSymlinkTarget(t *testing.T) {
root, err := filepath.EvalSymlinks(t.TempDir())
require.NoError(t, err)
require.NoError(t, os.MkdirAll(filepath.Join(root, "boot", "grub2"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(root, "boot", "grub2", "grub.cfg"), []byte("menuentry"), 0o644))
require.NoError(t, os.MkdirAll(filepath.Join(root, "etc"), 0o755))
require.NoError(t, os.Symlink(filepath.Join("..", "boot", "grub2", "grub.cfg"), filepath.Join(root, "etc", "grub2.cfg")))
visitors, err := GetDirectoryExclusionFunctions(root, []string{"./boot"})
require.NoError(t, err)
res, err := fileresolver.NewFromDirectory(root, root, visitors...)
require.NoError(t, err)
var indexed []string
for l := range res.AllLocations(context.Background()) {
if strings.Contains(l.RealPath, "/boot/") {
indexed = append(indexed, l.RealPath)
}
}
require.Empty(t, indexed, "excluded paths were indexed anyway")
}
This was split out of #3258, which reported this alongside a fatal crash on the same setup.
The crash was a separate defect and was fixed by #5170. This half was not.
I think this is a design question rather than a one-line fix and should be discussed by the team.
This behavior can be seen in RHEL-family hosts, where /etc/grub2.cfg and /etc/grub2-efi.cfg are symlinks into /boot/grub2.
What happened:
A directory excluded with
--excludeis still indexed and cataloged when a symlink elsewhere points into it.Exclusions are matched per-path against the paths being indexed and do not consider symlink resolution.
Ex: Matching
/boothits only the/bootdirectory entry itself.Indexing can travel to
/boot/grub2/grub.cfgvia symlink on an un excluded path without ever visiting/boot.Steps to reproduce the issue:
Anything else we need to know?:
Quick test in
syft/source/directorysource/can show the failure:This was split out of #3258, which reported this alongside a fatal crash on the same setup.
The crash was a separate defect and was fixed by #5170. This half was not.
I think this is a design question rather than a one-line fix and should be discussed by the team.
This behavior can be seen in RHEL-family hosts, where
/etc/grub2.cfgand/etc/grub2-efi.cfgare symlinks into /boot/grub2.