diff --git a/syft/internal/fileresolver/directory_indexer.go b/syft/internal/fileresolver/directory_indexer.go index 088aa8b7d..d5f5956f5 100644 --- a/syft/internal/fileresolver/directory_indexer.go +++ b/syft/internal/fileresolver/directory_indexer.go @@ -176,6 +176,13 @@ func isRealPath(root string) (bool, error) { func (r *directoryIndexer) indexBranch(root string, stager *progress.Stage) ([]string, error) { rootRealPath, err := filepath.EvalSymlinks(root) if err != nil { + var pathErr *os.PathError + if errors.As(err, &pathErr) { + // we can't index the path, but we shouldn't consider this to be fatal + // TODO: known-unknowns + log.WithFields("root", root, "error", err).Trace("unable to evaluate symlink while indexing branch") + return nil, nil + } return nil, err } diff --git a/syft/internal/fileresolver/directory_indexer_test.go b/syft/internal/fileresolver/directory_indexer_test.go index 3b9378c72..9e6774235 100644 --- a/syft/internal/fileresolver/directory_indexer_test.go +++ b/syft/internal/fileresolver/directory_indexer_test.go @@ -222,6 +222,18 @@ func TestDirectoryIndexer_index(t *testing.T) { } } +func TestDirectoryIndexer_index_survive_badSymlink(t *testing.T) { + // test-fixtures/bad-symlinks + // ├── root + // │ ├── place + // │ │ └── fd -> ../somewhere/self/fd + // │ └── somewhere + // ... + indexer := newDirectoryIndexer("test-fixtures/bad-symlinks/root/place/fd", "test-fixtures/bad-symlinks/root/place/fd") + _, _, err := indexer.build() + require.NoError(t, err) +} + func TestDirectoryIndexer_SkipsAlreadyVisitedLinkDestinations(t *testing.T) { var observedPaths []string pathObserver := func(_, p string, _ os.FileInfo, _ error) error { diff --git a/syft/internal/fileresolver/test-fixtures/bad-symlinks/root/place/fd b/syft/internal/fileresolver/test-fixtures/bad-symlinks/root/place/fd new file mode 120000 index 000000000..24486cb37 --- /dev/null +++ b/syft/internal/fileresolver/test-fixtures/bad-symlinks/root/place/fd @@ -0,0 +1 @@ +../somewhere/self/fd \ No newline at end of file