Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dpkg/distroless_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ func (ps *DistrolessScanner) Scan(ctx context.Context, layer *claircore.Layer) (
log.DebugContext(ctx, "examining package database")
db, err := sys.Open(fn)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
log.WarnContext(ctx, "skipping missing database file", "reason", err)
continue
}
return fmt.Errorf("reading database files from layer failed: %w", err)
}

Expand Down
83 changes: 83 additions & 0 deletions dpkg/distroless_scanner_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package dpkg

import (
"archive/tar"
"bytes"
"context"
"crypto/sha256"
"fmt"
"io"
"testing"
"time"

"github.com/google/go-cmp/cmp"

Expand Down Expand Up @@ -61,3 +68,79 @@ func TestDistrolessLayer(t *testing.T) {
t.Fatal(cmp.Diff(ps, want))
}
}

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.

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.


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....

MediaType: "application/vnd.oci.image.layer.v1.tar",
}
var l claircore.Layer
if err := l.Init(ctx, &desc, bytes.NewReader(buf.Bytes())); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { l.Close() })

var s DistrolessScanner
ps, err := s.Scan(ctx, &l)
if err != nil {
t.Fatalf("scan should not fail with missing .list file: %v", err)
}

// Should still find the valid package.
if got := len(ps); got != 1 {
t.Fatalf("got %d packages, want 1", got)
}
if ps[0].Name != "gcc-14-base" {
t.Errorf("got package name %q, want %q", ps[0].Name, "gcc-14-base")
}
}
Loading