From cc7693683fe79eebb8d014768b94fdb702de1e6e Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 28 Oct 2026 13:26:51 -0400 Subject: [PATCH] fix: archive scan leaking temp directories Signed-off-by: Keith Zantow --- syft/source/filesource/file_source.go | 2 +- syft/source/filesource/file_source_test.go | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/syft/source/filesource/file_source.go b/syft/source/filesource/file_source.go index 4beb0925e..05783ab68 100644 --- a/syft/source/filesource/file_source.go +++ b/syft/source/filesource/file_source.go @@ -157,7 +157,7 @@ func (s fileSource) FileResolver(_ source.Scope) (file.Resolver, error) { if isArchiveAnalysis := fi.IsDir(); isArchiveAnalysis { // this is an analysis of an archive file... we should scan the directory where the archive contents - res, err := fileresolver.NewFromDirectory(s.analysisPath, "", exclusionFunctions...) + res, err := fileresolver.NewFromDirectory(s.analysisPath, s.analysisPath, exclusionFunctions...) if err != nil { return nil, fmt.Errorf("unable to create directory resolver: %w", err) } diff --git a/syft/source/filesource/file_source_test.go b/syft/source/filesource/file_source_test.go index 1866dd668..fdfae2f1d 100644 --- a/syft/source/filesource/file_source_test.go +++ b/syft/source/filesource/file_source_test.go @@ -3,6 +3,7 @@ package filesource import ( "archive/zip" "bytes" + "context" "io" "os" "os/exec" @@ -242,6 +243,28 @@ func TestNewFromFile_RarExtension(t *testing.T) { } } +func TestNewFromFile_ArchivePathsAreRootedAtTheArchive(t *testing.T) { + // an extracted archive is scanned like a directory: its root is the empty path, and the temporary directory it + // was extracted to does not appear + archivePath := filepath.Join(t.TempDir(), "example.zip") + require.NoError(t, os.WriteFile(archivePath, zipBytes(t, [][2]string{{"sub/a.txt", "a"}}), 0o600)) + + src, err := New(Config{Path: archivePath}) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, src.Close()) + }) + + res, err := src.FileResolver(source.SquashedScope) + require.NoError(t, err) + + var paths []string + for l := range res.AllLocations(context.Background()) { + paths = append(paths, l.RealPath) + } + assert.ElementsMatch(t, []string{"", "/sub", "/sub/a.txt"}, paths) +} + // createResourceAdapterArchive writes a minimal Java resource adapter archive (a zip file with a .rar extension that // holds a deployment descriptor and a nested jar) into dir and returns its path. func createResourceAdapterArchive(t testing.TB, dir string) string {