mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
fix: migrate from *.list to *.md5sums files for dpkg (#9131)
This commit is contained in:
@@ -70,7 +70,7 @@
|
||||
"PkgName": "libidn2-0",
|
||||
"PkgIdentifier": {
|
||||
"PURL": "pkg:deb/debian/libidn2-0@2.0.5-1?arch=amd64\u0026distro=debian-10.1",
|
||||
"UID": "473f5eb9e3d4a2f2"
|
||||
"UID": "24f9b08969c58720"
|
||||
},
|
||||
"InstalledVersion": "2.0.5-1",
|
||||
"FixedVersion": "2.0.5-1+deb10u1",
|
||||
|
||||
@@ -47,6 +47,8 @@ const (
|
||||
statusDir = "var/lib/dpkg/status.d/"
|
||||
infoDir = "var/lib/dpkg/info/"
|
||||
availableFile = "var/lib/dpkg/available"
|
||||
|
||||
md5sumsExtension = ".md5sums"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -72,14 +74,14 @@ func (a dpkgAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysis
|
||||
|
||||
// parse other files
|
||||
err = fsutils.WalkDir(input.FS, ".", required, func(path string, _ fs.DirEntry, r io.Reader) error {
|
||||
// parse list files
|
||||
if a.isListFile(filepath.Split(path)) {
|
||||
// parse *md5sums files
|
||||
if a.isMd5SumsFile(filepath.Split(path)) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
systemFiles, err := a.parseDpkgInfoList(scanner)
|
||||
systemFiles, err := a.parseDpkgMd5sums(scanner)
|
||||
if err != nil {
|
||||
return err
|
||||
return xerrors.Errorf("failed to parse %s file: %w", path, err)
|
||||
}
|
||||
packageFiles[strings.TrimSuffix(filepath.Base(path), ".list")] = systemFiles
|
||||
packageFiles[strings.TrimSuffix(filepath.Base(path), md5sumsExtension)] = systemFiles
|
||||
systemInstalledFiles = append(systemInstalledFiles, systemFiles...)
|
||||
return nil
|
||||
}
|
||||
@@ -113,46 +115,31 @@ func (a dpkgAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysis
|
||||
|
||||
}
|
||||
|
||||
// parseDpkgInfoList parses /var/lib/dpkg/info/*.list
|
||||
func (a dpkgAnalyzer) parseDpkgInfoList(scanner *bufio.Scanner) ([]string, error) {
|
||||
var (
|
||||
allLines []string
|
||||
installedFiles []string
|
||||
previous string
|
||||
)
|
||||
|
||||
// parseDpkgMd5sums parses `/var/lib/dpkg/*/*.md5sums` file.
|
||||
//
|
||||
// `*.md5sums` files don't contain links (see https://github.com/aquasecurity/trivy/pull/9131#discussion_r2182557288).
|
||||
// But Trivy doesn't support links, so this will not cause problems.
|
||||
// TODO use `*.list` files instead of `*.md5sums` files when Trivy will support links.
|
||||
func (a dpkgAnalyzer) parseDpkgMd5sums(scanner *bufio.Scanner) ([]string, error) {
|
||||
var installedFiles []string
|
||||
for scanner.Scan() {
|
||||
current := scanner.Text()
|
||||
if current == "/." {
|
||||
continue
|
||||
|
||||
// md5sums file use the following format:
|
||||
// <digest> <filepath> (2 spaces)
|
||||
// cf. https://man7.org/linux/man-pages/man5/deb-md5sums.5.html
|
||||
_, file, ok := strings.Cut(current, " ")
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("invalid md5sums line format: %s", current)
|
||||
}
|
||||
allLines = append(allLines, current)
|
||||
installedFiles = append(installedFiles, "/"+file) // md5sums files don't contain leading slash
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, xerrors.Errorf("scan error: %w", err)
|
||||
}
|
||||
|
||||
// Add the file if it is not directory.
|
||||
// e.g.
|
||||
// /usr/sbin
|
||||
// /usr/sbin/tarcat
|
||||
//
|
||||
// In the above case, we should take only /usr/sbin/tarcat since /usr/sbin is a directory
|
||||
// sort first,see here:https://github.com/aquasecurity/trivy/discussions/6543
|
||||
sort.Strings(allLines)
|
||||
for _, current := range allLines {
|
||||
if !strings.HasPrefix(current, previous+"/") {
|
||||
installedFiles = append(installedFiles, previous)
|
||||
}
|
||||
previous = current
|
||||
}
|
||||
|
||||
// // Add the last file
|
||||
if previous != "" && !strings.HasSuffix(previous, "/") {
|
||||
installedFiles = append(installedFiles, previous)
|
||||
}
|
||||
|
||||
sort.Strings(installedFiles)
|
||||
return installedFiles, nil
|
||||
}
|
||||
|
||||
@@ -290,14 +277,10 @@ func (a dpkgAnalyzer) parseDpkgPkg(header textproto.MIMEHeader) *types.Package {
|
||||
|
||||
func (a dpkgAnalyzer) Required(filePath string, _ os.FileInfo) bool {
|
||||
dir, fileName := filepath.Split(filePath)
|
||||
if a.isListFile(dir, fileName) || filePath == statusFile || filePath == availableFile {
|
||||
if a.isMd5SumsFile(dir, fileName) || filePath == statusFile || filePath == availableFile || dir == statusDir {
|
||||
return true
|
||||
}
|
||||
|
||||
// skip `*.md5sums` files from `status.d` directory
|
||||
if dir == statusDir && filepath.Ext(fileName) != ".md5sums" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -356,12 +339,14 @@ func (a dpkgAnalyzer) consolidateDependencies(pkgs map[string]*types.Package, pk
|
||||
}
|
||||
}
|
||||
|
||||
func (a dpkgAnalyzer) isListFile(dir, fileName string) bool {
|
||||
if dir != infoDir {
|
||||
func (a dpkgAnalyzer) isMd5SumsFile(dir, fileName string) bool {
|
||||
// - var/lib/dpkg/info/*.md5sums is default path
|
||||
// - var/lib/dpkg/status.d/*.md5sums path in distroless images (see https://github.com/GoogleContainerTools/distroless/blob/5c119701429fb742ab45682cfc3073f911bad4bf/PACKAGE_METADATA.md#omitted-files)
|
||||
if dir != infoDir && dir != statusDir {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.HasSuffix(fileName, ".list")
|
||||
return strings.HasSuffix(fileName, md5sumsExtension)
|
||||
}
|
||||
|
||||
func (a dpkgAnalyzer) Type() analyzer.Type {
|
||||
|
||||
@@ -18,7 +18,7 @@ func Test_dpkgAnalyzer_Analyze(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
// testFiles contains path in testdata and path in OS
|
||||
// e.g. tar.list => var/lib/dpkg/info/tar.list
|
||||
// e.g. tar.md5sums => var/lib/dpkg/info/tar.md5sums
|
||||
testFiles map[string]string
|
||||
want *analyzer.AnalysisResult
|
||||
wantErr bool
|
||||
@@ -1372,7 +1372,9 @@ func Test_dpkgAnalyzer_Analyze(t *testing.T) {
|
||||
Packages: []types.Package{
|
||||
{
|
||||
ID: "apt@1.6.3ubuntu0.1", Name: "apt", Version: "1.6.3ubuntu0.1",
|
||||
SrcName: "apt", SrcVersion: "1.6.3ubuntu0.1", Maintainer: "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>", Arch: "amd64"},
|
||||
SrcName: "apt", SrcVersion: "1.6.3ubuntu0.1",
|
||||
Maintainer: "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>", Arch: "amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1418,12 +1420,11 @@ func Test_dpkgAnalyzer_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "info list",
|
||||
testFiles: map[string]string{"./testdata/tar.list": "var/lib/dpkg/info/tar.list"},
|
||||
name: "md5sums",
|
||||
testFiles: map[string]string{"./testdata/tar.md5sums": "var/lib/dpkg/info/tar.md5sums"},
|
||||
want: &analyzer.AnalysisResult{
|
||||
SystemInstalledFiles: []string{
|
||||
"/bin/tar",
|
||||
"/etc/rmt",
|
||||
"/usr/bin/tar",
|
||||
"/usr/lib/mime/packages/tar",
|
||||
"/usr/sbin/rmt-tar",
|
||||
"/usr/sbin/tarcat",
|
||||
@@ -1488,12 +1489,17 @@ func Test_dpkgAnalyzer_Required(t *testing.T) {
|
||||
{
|
||||
name: "*.md5sums file in status dir",
|
||||
filePath: "var/lib/dpkg/status.d/base-files.md5sums",
|
||||
want: false,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "*.md5sums file in info dir",
|
||||
filePath: "var/lib/dpkg/info/bash.md5sums",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "list file",
|
||||
filePath: "var/lib/dpkg/info/bash.list",
|
||||
want: true,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "available file",
|
||||
@@ -1502,7 +1508,7 @@ func Test_dpkgAnalyzer_Required(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
filePath: "var/lib/dpkg/status/bash.list",
|
||||
filePath: "var/lib/dpkg/status/bash.md5sums",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
28
pkg/fanal/analyzer/pkg/dpkg/testdata/tar.list
vendored
28
pkg/fanal/analyzer/pkg/dpkg/testdata/tar.list
vendored
@@ -1,28 +0,0 @@
|
||||
/.
|
||||
/bin
|
||||
/bin/tar
|
||||
/etc
|
||||
/usr
|
||||
/usr/lib
|
||||
/usr/lib/mime
|
||||
/usr/lib/mime/packages
|
||||
/usr/lib/mime/packages/tar
|
||||
/usr/sbin
|
||||
/usr/sbin/rmt-tar
|
||||
/usr/sbin/tarcat
|
||||
/usr/share
|
||||
/usr/share/doc
|
||||
/usr/share/doc/tar
|
||||
/usr/share/doc/tar/AUTHORS
|
||||
/usr/share/doc/tar/NEWS.gz
|
||||
/usr/share/doc/tar/README.Debian
|
||||
/usr/share/doc/tar/THANKS.gz
|
||||
/usr/share/doc/tar/changelog.Debian.gz
|
||||
/usr/share/doc/tar/copyright
|
||||
/usr/share/man
|
||||
/usr/share/man/man1
|
||||
/usr/share/man/man1/tar.1.gz
|
||||
/usr/share/man/man1/tarcat.1.gz
|
||||
/usr/share/man/man8
|
||||
/usr/share/man/man8/rmt-tar.8.gz
|
||||
/etc/rmt
|
||||
13
pkg/fanal/analyzer/pkg/dpkg/testdata/tar.md5sums
vendored
Normal file
13
pkg/fanal/analyzer/pkg/dpkg/testdata/tar.md5sums
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
25de5fcdc3c8ebd9c9f599fb7a899b40 usr/bin/tar
|
||||
5bf0e62990e0b668830ceb2c8615b497 usr/lib/mime/packages/tar
|
||||
de1096fbccdc14324196fc6829324ebc usr/sbin/rmt-tar
|
||||
fd2fab77cf4da2288c11a4de2c0c7fe0 usr/sbin/tarcat
|
||||
020511595e8fb6a77b29032b3ec4ab10 usr/share/doc/tar/AUTHORS
|
||||
5386c77b19064999a340c62ec50b9307 usr/share/doc/tar/NEWS.gz
|
||||
882d20d9ef9c5baf1557a921bb9c6251 usr/share/doc/tar/README.Debian
|
||||
63b372367a085f8d07c4127828c56999 usr/share/doc/tar/THANKS.gz
|
||||
e9c4ef9b5dffd7b5b94f019d28bf86d6 usr/share/doc/tar/changelog.Debian.gz
|
||||
4546fba65a596c8793dca393b32ad9ee usr/share/doc/tar/copyright
|
||||
0502616f764289571b974ecc5adc1209 usr/share/man/man1/tar.1.gz
|
||||
9376d82eb54e507863d32114dddd3de6 usr/share/man/man1/tarcat.1.gz
|
||||
4892b2039586e61ef7b290591e9743e5 usr/share/man/man8/rmt-tar.8.gz
|
||||
Reference in New Issue
Block a user