Because the package really is installed more than once. When two dependencies need different versions, or npm cannot hoist a copy, the same name appears at several places in the tree. The CycloneDX npm tool does not merge them, so each installed copy becomes its own component.
What the tool says
The README states that the tool does not do artificial deduplication, so if a component is installed multiple times, it appears multiple times in the SBOM result. A linked document explains the reasoning: npm already performs the needed graph deduplication internally when it builds the on disk layout, and extra logic would either be invalid or unnecessary.
In other words, the repeats are not noise added by the generator. They reflect npm's actual layout.
Two kinds of repeat
Look at the entries before deciding anything.
| Pattern | What it means | Action |
|---|---|---|
| Same name, different versions | Two dependents need different ranges | Real. Check whether both are patched |
| Same name and version, different paths | One version installed in two places | Usually harmless, but both copies ship |
| Same name and version, same path | Likely a generator or merge artifact | Investigate |
The first row deserves the most attention. A vulnerability fix applied to one copy does nothing for the other, and a scan that only looks at the highest version will miss it.
How to read the list
- Sort components by name.
- For each name with several entries, compare versions and paths. Component properties in the file, where present, can show where each copy lives, for example the package path that npm's own sbom output records.
- For differing versions, trace which dependent pulls each one in, using the dependency graph in the file.
- For identical entries in different paths, confirm both are needed at runtime.
The dependency graph is the useful part. It tells you which parent asked for which copy, so you know what to upgrade to remove the old one.
Can you remove the repeats?
The tool has a flatten components option that removes the nesting representation. The README describes it as meaning the actual nesting of node packages is not represented in the result. Flattening changes how components are arranged, not which packages exist, and you lose the structure that tells you where each copy lives. Use it only if a consumer cannot handle nested components, and keep an unflattened copy for your own analysis.
On the npm side, the dedupe command can reduce duplicate installs by reshaping the tree where version ranges allow. That changes your install, so it is a dependency management decision to test, not an SBOM setting.
What not to do
Do not delete duplicates by hand from a published SBOM. The file is supposed to describe the build, and hand edits break that. If the count looks wrong, fix the cause or regenerate.
Do not count components and call the number a risk figure. A repeated package inflates the count without adding a new library.
Using the result
When matching vulnerabilities, make sure your tool evaluates each installed version separately. Safeguard's SBOM and dependency scanning reads each component with its version and path, and reachability analysis shows which of the vulnerable copies your code calls. A free scan will show it for your project.
Quick check
Is a repeated component a bug in the SBOM?
Usually not. It reflects how npm installed the packages. Check versions and paths to see whether it matters.
Does flattening reduce my risk?
No. It changes how the file is arranged, and it loses the structure showing where each copy sits.
Sources
Last reviewed: 19 October 2026.