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()) }