Skip to content

fix(dpkg): handle missing files in distroless status.d gracefully#1808

Open
yuvalk wants to merge 2 commits intoquay:mainfrom
yuvalk:fix-distroless-missing-list-file
Open

fix(dpkg): handle missing files in distroless status.d gracefully#1808
yuvalk wants to merge 2 commits intoquay:mainfrom
yuvalk:fix-distroless-missing-list-file

Conversation

@yuvalk
Copy link
Copy Markdown

@yuvalk yuvalk commented Apr 1, 2026

Summary

  • The distroless dpkg scanner fails the entire scan when a file in status.d/ cannot be opened (e.g., a dangling symlink to a .list file in info/ that doesn't exist in the layer)
  • Now gracefully skips missing files with a warning log instead of aborting, matching the error-handling pattern used elsewhere in the dpkg scanners
  • Adds a test that constructs a synthetic layer with a dangling symlink in status.d/ to verify the fix

Test plan

  • New unit test TestDistrolessMissingListFile passes — constructs a layer with a dangling symlink and verifies the scan succeeds
  • Verify against the real container image that originally triggered the bug

🤖 Generated with Claude Code

@yuvalk yuvalk requested a review from a team as a code owner April 1, 2026 17:58
@yuvalk yuvalk requested review from hdonnay and removed request for a team April 1, 2026 17:58
@yuvalk yuvalk force-pushed the fix-distroless-missing-list-file branch from aa2b5c4 to e6fa003 Compare April 20, 2026 19:23
The distroless scanner failed the entire scan when a file in status.d/
could not be opened (e.g., a dangling symlink to a .list file in
info/). Now skips missing files with a warning instead of aborting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Yuval Kashtan <yuvalkashtan@gmail.com>
@yuvalk yuvalk force-pushed the fix-distroless-missing-list-file branch from e6fa003 to 87ea190 Compare April 20, 2026 19:31
Comment thread dpkg/distroless_scanner_test.go Outdated
Comment on lines +74 to +120
now := time.Now()

// Build a tar with:
// - var/lib/dpkg/status.d/gcc-14-base (valid control file)
// - var/lib/dpkg/status.d/gcc-14-base.list (symlink to missing ../info/gcc-14-base.list)
controlData := []byte("Package: gcc-14-base\nVersion: 14.2.0-19\nArchitecture: amd64\nSource: gcc-14\n\n")
buf := &bytes.Buffer{}
h := sha256.New()
tw := tar.NewWriter(io.MultiWriter(buf, h))

for _, dir := range []string{
"var/lib/dpkg/",
"var/lib/dpkg/status.d/",
} {
if err := tw.WriteHeader(&tar.Header{
Typeflag: tar.TypeDir,
Name: dir,
Mode: 0755,
ModTime: now,
}); err != nil {
t.Fatal(err)
}
}
if err := tw.WriteHeader(&tar.Header{
Typeflag: tar.TypeReg,
Name: "var/lib/dpkg/status.d/gcc-14-base",
Size: int64(len(controlData)),
Mode: 0644,
ModTime: now,
}); err != nil {
t.Fatal(err)
}
if _, err := tw.Write(controlData); err != nil {
t.Fatal(err)
}
if err := tw.WriteHeader(&tar.Header{
Typeflag: tar.TypeSymlink,
Name: "var/lib/dpkg/status.d/gcc-14-base.list",
Linkname: "../info/gcc-14-base.list",
Mode: 0644,
ModTime: now,
}); err != nil {
t.Fatal(err)
}
if err := tw.Close(); err != nil {
t.Fatal(err)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use test.GenerateFixture.

Comment thread dpkg/distroless_scanner_test.go Outdated
}

func TestDistrolessMissingListFile(t *testing.T) {
ctx := context.Background()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use test.Logging.

Comment thread dpkg/distroless_scanner_test.go Outdated

desc := claircore.LayerDescription{
URI: "file:///dev/null",
Digest: fmt.Sprintf("sha256:%x", h.Sum(nil)),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need the "correct" sha256, just a valid sha256, so this could be replaced with sha256:aaa....

Use test.Logging, test.GenerateFixture, and test.AnyDescription
instead of hand-rolled context, sha256 computation, and in-memory
tar buffer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants