diff --git a/pkg/fanal/applier/docker.go b/pkg/fanal/applier/docker.go index b0f42d957eec..36592a4e5ba6 100644 --- a/pkg/fanal/applier/docker.go +++ b/pkg/fanal/applier/docker.go @@ -91,7 +91,6 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail { nestedMap := nested.Nested{} secretsMap := make(map[string]types.Secret) var mergedLayer types.ArtifactDetail - for _, layer := range layers { for _, opqDir := range layer.OpaqueDirs { opqDir = strings.TrimSuffix(opqDir, sep) // this is necessary so that an empty element is not contribute into the array of the DeleteByString function @@ -110,9 +109,31 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail { // Apply OS packages for _, pkgInfo := range layer.PackageInfos { key := fmt.Sprintf("%s/type:ospkg", pkgInfo.FilePath) - nestedMap.SetByString(key, sep, pkgInfo) - } + value, err := nestedMap.GetByString(key, sep) + if err != nil && err == nested.ErrNoSuchKey { + nestedMap.SetByString(key, sep, pkgInfo) + continue + } + if existPpkgInfo, ok := value.(types.PackageInfo); ok { + mapPkgs := lo.KeyBy(existPpkgInfo.Packages, func(pkg types.Package) string { + return pkg.ID + }) + + updatedPackages := make(types.Packages, 0) + lo.ForEach(pkgInfo.Packages, func(pkg types.Package, _ int) { + if mPkg, ok := mapPkgs[pkg.ID]; ok { + pkg.InstalledFiles = lo.Uniq(append(pkg.InstalledFiles, mPkg.InstalledFiles...)) + } + updatedPackages = append(updatedPackages, pkg) + }) + + nestedMap.SetByString(key, sep, types.PackageInfo{ + FilePath: pkgInfo.FilePath, + Packages: updatedPackages, + }) + } + } // Apply language-specific packages for _, app := range layer.Applications { key := fmt.Sprintf("%s/type:%s", app.FilePath, app.Type)