syft/internal/relationship/exclude_binaries_by_file_ownership_overlap.go
Alex Goodman 573440b7cf
Infer the package type from ELF package notes (#3008)
* fix ELF package types to be honored

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* prefer OS packages over binary packages when there are duplicates

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-07-02 16:07:08 -04:00

79 lines
2 KiB
Go

package relationship
import (
"reflect"
"slices"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
)
var (
osCatalogerTypes = []pkg.Type{
pkg.AlpmPkg,
pkg.ApkPkg,
pkg.DebPkg,
pkg.NixPkg,
pkg.PortagePkg,
pkg.RpmPkg,
}
binaryCatalogerTypes = []pkg.Type{
pkg.BinaryPkg,
}
binaryMetadataTypes = []string{
reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(),
reflect.TypeOf(pkg.BinarySignature{}).Name(),
}
)
func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) {
accessor.WriteToSBOM(func(s *sbom.SBOM) {
for _, r := range s.Relationships {
if excludeBinaryByFileOwnershipOverlap(r, s.Artifacts.Packages) {
s.Artifacts.Packages.Delete(r.To.ID())
s.Relationships = RemoveRelationshipsByID(s.Relationships, r.To.ID())
}
}
})
}
// excludeBinaryByFileOwnershipOverlap will remove packages from a collection given the following properties are true
// 1) the relationship between packages is OwnershipByFileOverlap
// 2) the parent is an "os" package
// 3) the child is a synthetic package generated by the binary cataloger
// 4) the package names are identical
// This was implemented as a way to help resolve: https://github.com/anchore/syft/issues/931
func excludeBinaryByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collection) bool {
if artifact.OwnershipByFileOverlapRelationship != r.Type {
return false
}
parent := c.Package(r.From.ID())
if parent == nil {
return false
}
parentInExclusion := slices.Contains(osCatalogerTypes, parent.Type)
if !parentInExclusion {
return false
}
child := c.Package(r.To.ID())
if child == nil {
return false
}
if slices.Contains(binaryCatalogerTypes, child.Type) {
return true
}
if child.Metadata == nil {
return false
}
childMetadataType := reflect.TypeOf(child.Metadata)
return slices.Contains(binaryMetadataTypes, childMetadataType.Name())
}