mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
fix: de-duplicate same dpkg packages with different filePaths from different layers (#8298)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package applier
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -13,7 +14,9 @@ import (
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
xslices "github.com/aquasecurity/trivy/pkg/x/slices"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -232,6 +235,12 @@ func ApplyLayers(layers []ftypes.BlobInfo) ftypes.ArtifactDetail {
|
||||
}
|
||||
}
|
||||
|
||||
// De-duplicate same debian packages from different dirs
|
||||
// cf. https://github.com/aquasecurity/trivy/issues/8297
|
||||
mergedLayer.Packages = xslices.ZeroToNil(lo.UniqBy(mergedLayer.Packages, func(pkg ftypes.Package) string {
|
||||
return cmp.Or(pkg.ID, fmt.Sprintf("%s@%s", pkg.Name, utils.FormatVersion(pkg)))
|
||||
}))
|
||||
|
||||
for _, app := range mergedLayer.Applications {
|
||||
for i, pkg := range app.Packages {
|
||||
// Skip lookup for SBOM
|
||||
|
||||
@@ -254,6 +254,61 @@ func TestApplyLayers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path with duplicate of debian packages",
|
||||
inputLayers: []types.BlobInfo{
|
||||
{
|
||||
SchemaVersion: 2,
|
||||
DiffID: "sha256:96e320b34b5478d8b369ca43ffaa88ff6dd9499ec72b792ca21b1e8b0c55670f",
|
||||
PackageInfos: []types.PackageInfo{
|
||||
{
|
||||
FilePath: "var/lib/dpkg/status.d/libssl1",
|
||||
Packages: types.Packages{
|
||||
{
|
||||
ID: "libssl1.1@1.1.1n-0+deb11u3",
|
||||
Name: "libssl1.1",
|
||||
Version: "1.1.1n",
|
||||
Release: "0+deb11u3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
SchemaVersion: 2,
|
||||
DiffID: "sha256:5e087d956f3e62bd034dd0712bc4cbef8fda55fba0b11a7d0564f294887c7079",
|
||||
PackageInfos: []types.PackageInfo{
|
||||
{
|
||||
FilePath: "var/lib/dpkg/status.d/libssl1.1",
|
||||
Packages: types.Packages{
|
||||
{
|
||||
ID: "libssl1.1@1.1.1n-0+deb11u3",
|
||||
Name: "libssl1.1",
|
||||
Version: "1.1.1n",
|
||||
Release: "0+deb11u3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactDetail{
|
||||
Packages: types.Packages{
|
||||
{
|
||||
ID: "libssl1.1@1.1.1n-0+deb11u3",
|
||||
Name: "libssl1.1",
|
||||
Version: "1.1.1n",
|
||||
Release: "0+deb11u3",
|
||||
Identifier: types.PkgIdentifier{
|
||||
UID: "522a5c3b263d1357",
|
||||
},
|
||||
Layer: types.Layer{
|
||||
DiffID: "sha256:96e320b34b5478d8b369ca43ffaa88ff6dd9499ec72b792ca21b1e8b0c55670f",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path with digests in libs/packages (as for SBOM)",
|
||||
inputLayers: []types.BlobInfo{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package slices
|
||||
|
||||
// ZeroToNil returns nil, if slice is empty
|
||||
func ZeroToNil[T any](t []T) []T {
|
||||
if len(t) == 0 {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user