Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Bug: Dependency Trees overflows the call stack on cyclic SBOM dependency graphs

Open
#5,746 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@faystmax is already working on this.

Since Oct 3, 2026.

  • #5748 by @faystmax — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Domain
frontend

Research direction

Start with spring-boot-admin-server-ui/src/main/frontend/views/instances/sbomdependencytrees/sbomUtils.ts, especially getChildren() and retrieveChildren(), then inspect tree.spec.ts for the existing normalization and rendering tests. Reproduce the minimal cyclic input and add coverage for cycles, self-references, acyclic chains, and shared dependencies. Done means finite cycle-marked output, preserved repeated shared nodes, and working filtering and rerendering without a stack overflow.

Written by the indexing model from the issue text.

Description

Spring Boot Admin Server information

  • Version: 4.1.3
  • Spring Boot version: 4.1.1

Client information

  • Spring Boot versions: 3.5.10
  • SBOM format: CycloneDX JSON

Description

The SBOM Dependency Trees normalizer recursively expands dependency references without tracking ancestors. When the input graph contains a reachable cycle, expansion never terminates normally and throws RangeError: Maximum call stack size exceeded.

This was reproduced in isolation against the executable normalization logic from 4.1.3 and master inspected on 2026-10-03. A self-reference also reproduces the failure. A full SBA browser integration test was not run for this report.

Regardless of how a producer generated a cyclic graph, the viewer should handle it without exhausting the JavaScript call stack. Removing BOM/POM components from the input should not be necessary to prevent the viewer from failing.

Minimal input

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "version": 1,
  "metadata": {
    "component": { "type": "application", "bom-ref": "app", "name": "demo-app", "version": "1.0.0" }
  },
  "components": [
    { "type": "library", "bom-ref": "a", "name": "library-a", "version": "1.0.0" },
    { "type": "library", "bom-ref": "b", "name": "library-b", "version": "1.0.0" }
  ],
  "dependencies": [
    { "ref": "app", "dependsOn": ["a"] },
    { "ref": "a", "dependsOn": ["b"] },
    { "ref": "b", "dependsOn": ["a"] }
  ]
}

Reproduction and actual behavior

Pass this document's dependencies to normalizeData() in sbomUtils.ts. It throws Maximum call stack size exceeded while expanding app -> a -> b -> a -> ....

For UI reproduction, serve the document through the monitored application's SBOM endpoint, or mock instance.fetchSbom() in tree.spec.ts, and open Dependency Trees. Normalization fails before a finite tree can be passed to the D3 renderer.

Expected behavior

Render a finite representation of the reachable graph. For example, show a terminal node/reference marked as a cycle when a dependency points back to an ancestor:

app
└── a
    └── b
        └── a [cycle; not expanded again]

An explicit controlled diagnostic would also be preferable to a stack overflow, but retaining the rest of the graph would make the view more useful.

Cause and proposed fix

getChildren() and retrieveChildren() in 4.1.3 call each other without an ancestor/recursion-path guard.

  • Index dependency records by their exact ref.
  • Track references on the current traversal path, including the root.
  • If the next reference is already on that path, create a terminal cycle/reference node rather than expanding it again.
  • Use full references for identity; normalized labels can collide.
  • Do not use a global visited set to suppress all repeated nodes. A shared dependency in two independent branches is not a cycle and should remain visible under both parents.
  • Keep the resulting object structure acyclic for D3, and preserve the original SBOM graph.
  • Consider an explicit stack or controlled expansion limits for very deep graphs / large numbers of repeated paths; cycle detection alone does not bound all work.

Regression cases should include a two-node cycle, self-reference, an edge back to the application root, an ordinary acyclic chain, and a diamond (app -> a,b, a -> c, b -> c) where c is shown in both branches. Filtering and rerendering should still work with cycle markers.

Related reports

There is a separate root-selection defect where dependencies[0] is treated as the root. Correcting it can make previously hidden cycles reachable. [#5745]

#5157 fixes an alert displayed during SBOM loading; it does not add cycle detection to dependency traversal.

I would be happy to contribute a PR targeting master, covering both root selection and cycle-safe traversal if preferred.

Dominant language
Java
Stars
12.9k
Forks
3.2k
Avg merge
23h 31m
Merged PRs (30d)
72

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from codecentric/spring-boot-admin

All issues in codecentric/spring-boot-admin

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.