Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3ded95a
add SearchComponentByRefGitDiff for frogbot usage
kerenr-jfrog Dec 8, 2025
bd0d9b3
Update froggit to v1.20.6
attiasas Dec 9, 2025
339bbc5
fix static test unused vars
attiasas Dec 9, 2025
3b15179
Merge remote-tracking branch 'upstream/dev' into update_ftoggit_1_20_6
attiasas Dec 9, 2025
257d63a
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 9, 2025
0d920de
minor fix
kerenr-jfrog Dec 9, 2025
5e93904
fix excludeFromDependencies logic
kerenr-jfrog Dec 9, 2025
1c11af9
Fix breaking changes in remediation API
attiasas Dec 10, 2025
2a815cb
update dependencies versions to fix static
attiasas Dec 10, 2025
5c02222
Merge remote-tracking branch 'assafa/update_ftoggit_1_20_6' into fix-…
kerenr-jfrog Dec 10, 2025
35e0123
update dependencies
kerenr-jfrog Dec 11, 2025
0f00a97
fix cr comments
kerenr-jfrog Dec 11, 2025
7e4a1ab
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 11, 2025
4687742
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 11, 2025
1bc0077
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 11, 2025
9456278
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 11, 2025
72e2aea
implement diff with bomref
kerenr-jfrog Dec 16, 2025
54609e9
progress
kerenr-jfrog Dec 16, 2025
d4ca7e4
add GetTrimmedPurl()
kerenr-jfrog Dec 16, 2025
cbb72e3
fix cyclonedxutils_test.go
kerenr-jfrog Dec 16, 2025
ff1cb5b
fix bomgenerator_test.go
kerenr-jfrog Dec 16, 2025
ec31edd
added hash exclude test
kerenr-jfrog Dec 17, 2025
0452c0e
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 18, 2025
8645015
Merge branch 'dev' into fix-sbom-component-ref-compare
kerenr-jfrog Dec 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions sca/bom/bomgenerator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestGetDiff(t *testing.T) {
Sbom: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "root", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component1", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component1", PackageURL: "pkg:component1", Version: "1.0"},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"component1"}},
Expand All @@ -96,8 +96,8 @@ func TestGetDiff(t *testing.T) {
sbom: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "root", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component1", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component2", Version: "2.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component1", PackageURL: "pkg:component1", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component2", PackageURL: "pkg:component2", Version: "2.0"},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"component1", "component2"}},
Expand All @@ -107,7 +107,7 @@ func TestGetDiff(t *testing.T) {
expectedSbom: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "root", Version: "1.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component2", Version: "2.0"},
{Type: cyclonedx.ComponentTypeLibrary, BOMRef: "component2", PackageURL: "pkg:component2", Version: "2.0"},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"component2"}},
Expand Down
37 changes: 29 additions & 8 deletions utils/formats/cdxutils/cyclonedxutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,18 @@ func SearchComponentByRef(components *[]cyclonedx.Component, ref string) (compon
return
}

func SearchComponentByCleanPurl(components *[]cyclonedx.Component, purl string) (component *cyclonedx.Component) {
if components == nil || len(*components) == 0 {
return
}
for i, comp := range *components {
if techutils.PurlToXrayComponentId(comp.PackageURL) == techutils.PurlToXrayComponentId(purl) {
return &(*components)[i]
}
}
return
}

func CreateFileOrDirComponent(filePathOrUri string) (component cyclonedx.Component) {
component = cyclonedx.Component{
BOMRef: GetFileRef(filePathOrUri),
Expand Down Expand Up @@ -309,12 +321,12 @@ func Exclude(bom cyclonedx.BOM, componentsToExclude ...cyclonedx.Component) (fil
}
filteredSbom = &bom
for _, compToExclude := range componentsToExclude {
if matchedBomComp := SearchComponentByRef(bom.Components, compToExclude.BOMRef); matchedBomComp == nil || GetComponentRelation(&bom, matchedBomComp.BOMRef, false) == RootRelation {
if matchedBomComp := SearchComponentByCleanPurl(bom.Components, compToExclude.PackageURL); matchedBomComp == nil || GetComponentRelation(&bom, matchedBomComp.BOMRef, false) == RootRelation {
// If not a match or Root component, skip it
continue
}
// Exclude the component from the dependencies
filteredSbom.Dependencies = excludeFromDependencies(bom.Dependencies, compToExclude.BOMRef)
filteredSbom.Dependencies = excludeFromDependencies(bom.Dependencies, bom.Components, compToExclude)
}
toExclude := datastructures.MakeSet[string]()
for _, comp := range *filteredSbom.Components {
Expand Down Expand Up @@ -366,25 +378,25 @@ func excludeFromComponents(components *[]cyclonedx.Component, excludeComponents
return &filteredComponents
}

func excludeFromDependencies(dependencies *[]cyclonedx.Dependency, excludeComponents ...string) *[]cyclonedx.Dependency {
func excludeFromDependencies(dependencies *[]cyclonedx.Dependency, components *[]cyclonedx.Component, excludeComponents ...cyclonedx.Component) *[]cyclonedx.Dependency {
if dependencies == nil || len(*dependencies) == 0 || len(excludeComponents) == 0 {
return dependencies
}
excludeRefs := datastructures.MakeSet[string]()
for _, compRef := range excludeComponents {
excludeRefs.Add(compRef)
excludePurls := datastructures.MakeSet[string]()
for _, component := range excludeComponents {
excludePurls.Add(techutils.PurlToXrayComponentId(component.PackageURL))
}
filteredDependencies := []cyclonedx.Dependency{}
for _, dep := range *dependencies {
if excludeRefs.Exists(dep.Ref) {
if excludePurls.Exists(GetTrimmedPurlByRef(dep.Ref, components)) {
// This dependency is excluded, skip it
continue
}
filteredDep := cyclonedx.Dependency{Ref: dep.Ref}
if dep.Dependencies != nil {
// Also filter the components from the dependencies of this dependency
for _, depRef := range *dep.Dependencies {
if !excludeRefs.Exists(depRef) {
if !excludePurls.Exists(GetTrimmedPurlByRef(depRef, components)) {
if filteredDep.Dependencies == nil {
filteredDep.Dependencies = &[]string{}
}
Expand All @@ -399,6 +411,15 @@ func excludeFromDependencies(dependencies *[]cyclonedx.Dependency, excludeCompon
return &filteredDependencies
}

func GetTrimmedPurlByRef(dep string, components *[]cyclonedx.Component) string {
component := SearchComponentByRef(components, dep)
if component == nil {
// couldn't find component
return ""
}
return techutils.PurlToXrayComponentId(component.PackageURL)
}

func AttachLicenseToComponent(component *cyclonedx.Component, license cyclonedx.LicenseChoice) {
if component.Licenses == nil {
component.Licenses = &cyclonedx.Licenses{}
Expand Down
52 changes: 39 additions & 13 deletions utils/formats/cdxutils/cyclonedxutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1121,9 +1121,9 @@ func TestExclude(t *testing.T) {
bom := cyclonedx.NewBOM()
bom.Components = &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", PackageURL: "pkg:comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", PackageURL: "pkg:comp2", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", PackageURL: "pkg:comp3", Type: cyclonedx.ComponentTypeLibrary},
}
bom.Dependencies = &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp1", "comp3"}},
Expand Down Expand Up @@ -1152,9 +1152,9 @@ func TestExclude(t *testing.T) {
expected: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", PackageURL: "pkg:comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", PackageURL: "pkg:comp2", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", PackageURL: "pkg:comp3", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp1", "comp3"}},
Expand All @@ -1164,25 +1164,25 @@ func TestExclude(t *testing.T) {
},
{
name: "Exclude single component with transitive dependencies",
exclude: []cyclonedx.Component{{BOMRef: "comp1"}},
exclude: []cyclonedx.Component{{BOMRef: "comp1", PackageURL: "pkg:comp1"}},
bom: *bom,
expected: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", PackageURL: "pkg:comp3", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{{Ref: "root", Dependencies: &[]string{"comp3"}}},
},
},
{
name: "Exclude single component existing both directly and transitively",
exclude: []cyclonedx.Component{{BOMRef: "comp3"}},
exclude: []cyclonedx.Component{{BOMRef: "comp3", PackageURL: "pkg:comp3"}},
bom: *bom,
expected: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", PackageURL: "pkg:comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", PackageURL: "pkg:comp2", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp1"}},
Expand All @@ -1192,18 +1192,44 @@ func TestExclude(t *testing.T) {
},
{
name: "Exclude multiple components",
exclude: []cyclonedx.Component{{BOMRef: "comp2"}, {BOMRef: "comp3"}, {BOMRef: "exclude-me"}},
exclude: []cyclonedx.Component{{BOMRef: "comp2", PackageURL: "pkg:comp2"}, {BOMRef: "comp3", PackageURL: "pkg:comp3"}, {BOMRef: "exclude-me", PackageURL: "pkg:exclude-me"}},
bom: *bom,
expected: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", PackageURL: "pkg:comp1", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp1"}},
},
},
},
{
name: "Exclude by same name+version while ignoring hash",
bom: cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp1", PackageURL: "pkg:npm/[email protected]?hash=4321", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp2", PackageURL: "pkg:npm/[email protected]", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", PackageURL: "pkg:npm/[email protected]", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp1", "comp3"}},
{Ref: "comp1", Dependencies: &[]string{"comp2", "comp3"}},
},
},
// Exclude the same name+version, with a hash that should be ignored
exclude: []cyclonedx.Component{{BOMRef: "comp1", PackageURL: "pkg:npm/[email protected]?hash=1234"}},
expected: &cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{BOMRef: "root", Type: cyclonedx.ComponentTypeLibrary},
{BOMRef: "comp3", PackageURL: "pkg:npm/[email protected]", Type: cyclonedx.ComponentTypeLibrary},
},
Dependencies: &[]cyclonedx.Dependency{
{Ref: "root", Dependencies: &[]string{"comp3"}},
},
},
},
}

for _, tt := range tests {
Expand Down
Loading