diff --git a/pkg/action/archive.go b/pkg/action/archive.go index 8c637a9f8..e46f65409 100644 --- a/pkg/action/archive.go +++ b/pkg/action/archive.go @@ -5,6 +5,7 @@ import ( "archive/zip" "compress/bzip2" "compress/gzip" + "compress/zlib" "context" "errors" "fmt" @@ -19,6 +20,7 @@ import ( "github.com/cavaliergopher/cpio" "github.com/cavaliergopher/rpm" "github.com/chainguard-dev/clog" + "github.com/chainguard-dev/malcontent/pkg/programkind" "github.com/egibs/go-debian/deb" @@ -220,7 +222,6 @@ func extractTar(ctx context.Context, d string, f string) error { // extractGzip extracts .gz archives. func extractGzip(ctx context.Context, d string, f string) error { logger := clog.FromContext(ctx).With("dir", d, "file", f) - logger.Debug("extracting gzip") // Check if the file is valid _, err := os.Stat(f) @@ -234,23 +235,50 @@ func extractGzip(ctx context.Context, d string, f string) error { } defer gf.Close() - gr, err := gzip.NewReader(gf) + // Determine if we're extracting a gzip- or zlib-compressed file + ft, err := programkind.File(f) if err != nil { - return fmt.Errorf("failed to create gzip reader: %w", err) + return fmt.Errorf("failed to determine file type: %w", err) } - defer gr.Close() + + logger.Debugf("extracting %s", ft.Ext) base := filepath.Base(f) target := filepath.Join(d, base[:len(base)-len(filepath.Ext(base))]) - ef, err := os.Create(target) - if err != nil { - return fmt.Errorf("failed to create extracted file: %w", err) - } - defer ef.Close() + switch ft.Ext { + case "gzip": + gr, err := gzip.NewReader(gf) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gr.Close() - if _, err := io.Copy(ef, io.LimitReader(gr, maxBytes)); err != nil { - return fmt.Errorf("failed to copy file: %w", err) + ef, err := os.Create(target) + if err != nil { + return fmt.Errorf("failed to create extracted file: %w", err) + } + defer ef.Close() + + if _, err := io.Copy(ef, io.LimitReader(gr, maxBytes)); err != nil { + return fmt.Errorf("failed to copy file: %w", err) + } + case "zlib": + zr, err := zlib.NewReader(gf) + if err != nil { + return fmt.Errorf("failed to create zlib reader: %w", err) + } + defer zr.Close() + + ef, err := os.Create(target) + if err != nil { + return fmt.Errorf("failed to create extracted file: %w", err) + } + defer ef.Close() + + if _, err := io.Copy(ef, io.LimitReader(zr, maxBytes)); err != nil { + return fmt.Errorf("failed to copy file: %w", err) + } } return nil diff --git a/pkg/programkind/programkind.go b/pkg/programkind/programkind.go index 923f9f4fa..a23a4816e 100644 --- a/pkg/programkind/programkind.go +++ b/pkg/programkind/programkind.go @@ -39,6 +39,7 @@ var supportedKind = map[string]string{ "expect": "text/x-expect", "fish": "text/x-fish", "go": "text/x-go", + "gzip": "application/gzip", "h": "text/x-h", "hh": "text/x-h", "html": "", @@ -68,6 +69,7 @@ var supportedKind = map[string]string{ "yaml": "", "yara": "", "yml": "", + "zlib": "application/zlib", "zsh": "application/x-zsh", } @@ -176,6 +178,10 @@ func File(path string) (*FileType, error) { return Path(".c"), nil case strings.Contains(s, "BEAMAtU8"): return Path(".beam"), nil + case hdr[0] == '\x1f' && hdr[1] == '\x8b': + return Path(".gzip"), nil + case hdr[0] == '\x78' && hdr[1] == '\x5E': + return Path(".zlib"), nil } return nil, nil }