diff --git a/xray/services/scan.go b/xray/services/scan.go index 88633e00b..f295f246e 100644 --- a/xray/services/scan.go +++ b/xray/services/scan.go @@ -188,10 +188,17 @@ func FlattenGraph(graph []*xrayUtils.GraphNode) ([]*xrayUtils.GraphNode, error) } func populateUniqueDependencies(node *xrayUtils.GraphNode, allDependencies map[string]*xrayUtils.GraphNode) { - if _, exist := allDependencies[node.Id]; exist { + if value, exist := allDependencies[node.Id]; exist && + (len(node.Nodes) == 0 || value.ChildrenExist) { return } allDependencies[node.Id] = &xrayUtils.GraphNode{Id: node.Id} + if len(node.Nodes) > 0 { + // In some cases node can appear twice, with or without children, this because of the depth limit when creating the graph. + // If the node was covered with its children, we mark that, so we won't cover it again. + // If its without children, we want to cover it again when it comes with its children. + allDependencies[node.Id].ChildrenExist = true + } for _, dependency := range node.Nodes { populateUniqueDependencies(dependency, allDependencies) } diff --git a/xray/services/scan_test.go b/xray/services/scan_test.go index 7ba0d72c5..bc8fb5c47 100644 --- a/xray/services/scan_test.go +++ b/xray/services/scan_test.go @@ -58,13 +58,17 @@ func TestFlattenGraph(t *testing.T) { nodeD := &xrayUtils.GraphNode{Id: "D"} nodeE := &xrayUtils.GraphNode{Id: "E"} nodeF := &xrayUtils.GraphNode{Id: "F"} + nodeG := &xrayUtils.GraphNode{Id: "G"} + nodeGNoChildren := &xrayUtils.GraphNode{Id: "G"} + nodeH := &xrayUtils.GraphNode{Id: "H"} // Set dependencies nodeA.Nodes = []*xrayUtils.GraphNode{nodeB, nodeC} nodeB.Nodes = []*xrayUtils.GraphNode{nodeC, nodeD} nodeC.Nodes = []*xrayUtils.GraphNode{nodeD} nodeD.Nodes = []*xrayUtils.GraphNode{nodeE, nodeF} - nodeF.Nodes = []*xrayUtils.GraphNode{nodeA, nodeB, nodeC} + nodeF.Nodes = []*xrayUtils.GraphNode{nodeGNoChildren, nodeA, nodeB, nodeC, nodeG} + nodeG.Nodes = []*xrayUtils.GraphNode{nodeH} // Create graph graph := []*xrayUtils.GraphNode{nodeA, nodeB, nodeC} @@ -72,7 +76,7 @@ func TestFlattenGraph(t *testing.T) { assert.NoError(t, err) // Check that the graph has been flattened correctly - assert.Equal(t, len(flatGraph[0].Nodes), 6) + assert.Equal(t, len(flatGraph[0].Nodes), 8) set := datastructures.MakeSet[string]() for _, node := range flatGraph[0].Nodes { assert.Len(t, node.Nodes, 0) diff --git a/xray/services/utils/graph.go b/xray/services/utils/graph.go index 5d8a2627c..706fd26da 100644 --- a/xray/services/utils/graph.go +++ b/xray/services/utils/graph.go @@ -24,6 +24,9 @@ type GraphNode struct { OtherComponentIds []OtherComponentIds `json:"other_component_ids,omitempty"` // Node parent (for internal use) Parent *GraphNode `json:"-"` + // Node Can appear in some cases without children. When adding node to flatten graph, + // we want to process node again if it was processed without children. + ChildrenExist bool `json:"-"` } type OtherComponentIds struct {