diff --git a/syft/formats/common/cyclonedxhelpers/decoder.go b/syft/formats/common/cyclonedxhelpers/decoder.go
index 36d99e26014e..e224ea6043eb 100644
--- a/syft/formats/common/cyclonedxhelpers/decoder.go
+++ b/syft/formats/common/cyclonedxhelpers/decoder.go
@@ -2,6 +2,7 @@ package cyclonedxhelpers
import (
"fmt"
+ "github.com/anchore/packageurl-go"
"io"
"github.com/CycloneDX/cyclonedx-go"
@@ -88,6 +89,10 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
case cyclonedx.ComponentTypeApplication, cyclonedx.ComponentTypeFramework, cyclonedx.ComponentTypeLibrary:
p := decodeComponent(component)
idMap[component.BOMRef] = p
+ syftID := extractSyftPacakgeID(component.BOMRef)
+ if syftID != "" {
+ idMap[syftID] = p
+ }
// TODO there must be a better way than needing to call this manually:
p.SetID()
s.Artifacts.PackageCatalog.Add(*p)
@@ -100,6 +105,19 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
}
}
+func extractSyftPacakgeID(i string) string {
+ instance, err := packageurl.FromString(i)
+ if err != nil {
+ return ""
+ }
+ for _, q := range instance.Qualifiers {
+ if q.Key == "package-id" {
+ return q.Value
+ }
+ }
+ return ""
+}
+
func linuxReleaseFromComponents(components []cyclonedx.Component) *linux.Release {
for i := range components {
component := &components[i]
@@ -188,21 +206,25 @@ func collectRelationships(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]int
return
}
for _, d := range *bom.Dependencies {
- from, fromOk := idMap[d.Ref].(artifact.Identifiable)
- if fromOk {
- if d.Dependencies == nil {
+ from, fromExists := idMap[d.Ref].(artifact.Identifiable)
+ if !fromExists {
+ continue
+ }
+
+ if d.Dependencies == nil {
+ continue
+ }
+
+ for _, t := range *d.Dependencies {
+ to, toExists := idMap[t.Ref].(artifact.Identifiable)
+ if !toExists {
continue
}
- for _, t := range *d.Dependencies {
- to, toOk := idMap[t.Ref].(artifact.Identifiable)
- if toOk {
- s.Relationships = append(s.Relationships, artifact.Relationship{
- From: from,
- To: to,
- Type: artifact.DependencyOfRelationship, // FIXME this information is lost
- })
- }
- }
+ s.Relationships = append(s.Relationships, artifact.Relationship{
+ From: from,
+ To: to,
+ Type: artifact.DependencyOfRelationship, // FIXME this information is lost
+ })
}
}
}
diff --git a/syft/formats/common/cyclonedxhelpers/format.go b/syft/formats/common/cyclonedxhelpers/format.go
index a22b191b2d11..c5c408b25689 100644
--- a/syft/formats/common/cyclonedxhelpers/format.go
+++ b/syft/formats/common/cyclonedxhelpers/format.go
@@ -1,6 +1,7 @@
package cyclonedxhelpers
import (
+ "github.com/anchore/syft/syft/pkg"
"time"
"github.com/CycloneDX/cyclonedx-go"
@@ -141,10 +142,21 @@ func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependenc
continue
}
+ // we only capture package-to-package relationships for now
+ fromPkg, ok := r.From.(*pkg.Package)
+ if !ok {
+ continue
+ }
+
+ toPkg, ok := r.To.(*pkg.Package)
+ if !ok {
+ continue
+ }
+
innerDeps := []cyclonedx.Dependency{}
- innerDeps = append(innerDeps, cyclonedx.Dependency{Ref: string(r.From.ID())})
+ innerDeps = append(innerDeps, cyclonedx.Dependency{Ref: deriveBomRef(*fromPkg)})
result = append(result, cyclonedx.Dependency{
- Ref: string(r.To.ID()),
+ Ref: deriveBomRef(*toPkg),
Dependencies: &innerDeps,
})
}
diff --git a/test/integration/encode_decode_cycle_test.go b/test/integration/encode_decode_cycle_test.go
index 2681bfe6a561..19a8bd9f0a00 100644
--- a/test/integration/encode_decode_cycle_test.go
+++ b/test/integration/encode_decode_cycle_test.go
@@ -2,7 +2,6 @@ package integration
import (
"bytes"
- "encoding/json"
"fmt"
"regexp"
"testing"
@@ -48,13 +47,13 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
// unstable values
in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref)": "[^"]+",`).ReplaceAll(in, []byte{})
- // dependencies are not supported (edge types cannot be encoded or inferred during decoding)
- var det map[string]interface{}
- require.NoError(t, json.Unmarshal(in, &det))
- delete(det, "dependencies")
- inCopy, err := json.Marshal(det)
- require.NoError(t, err)
- in = inCopy
+ //// dependencies are not supported (edge types cannot be encoded or inferred during decoding)
+ //var det map[string]interface{}
+ //require.NoError(t, json.Unmarshal(in, &det))
+ //delete(det, "dependencies")
+ //inCopy, err := json.Marshal(det)
+ //require.NoError(t, err)
+ //in = inCopy
return in
},
@@ -65,19 +64,9 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
redactor: func(in []byte) []byte {
// unstable values
in = regexp.MustCompile(`(serialNumber|bom-ref)="[^"]+"`).ReplaceAll(in, []byte{})
- in = regexp.MustCompile("[^<]+").ReplaceAll(in, []byte{})
+ in = regexp.MustCompile(`[^<]+`).ReplaceAll(in, []byte{})
+ //in = regexp.MustCompile(`(?m:(\n\s+)*[\s\S]*?)`).ReplaceAll(in, []byte{})
- // dependencies are not supported (edge types cannot be encoded or inferred during decoding)
- start := bytes.Index(in, []byte(" ")) // important: mind the prefix whitespace
- endVal := "\n" // important: mind the postfix whitespace
- stop := bytes.Index(in, []byte(endVal))
- if start != -1 && stop != -1 {
- stopAfterVal := stop + len(endVal)
- inCopy := make([]byte, 0)
- inCopy = append(inCopy, in[:start]...)
- inCopy = append(inCopy, in[stopAfterVal:]...)
- in = inCopy
- }
return in
},
},