One vulnerable library creates many findings in a monorepo because each lockfile, workspace and build target lists it separately, and scanners report each listing. The fair way to count is to group findings by component, version and advisory, and show the number of locations as a separate column.
The mechanism
A monorepo may hold many packages, each with its own manifest or a shared lockfile with several resolved entries. A common utility library at one version can be listed in each. A container image built from the same base can add another. If the scanner emits one finding per listing, a single upgrade decision turns into dozens of rows.
What to group by
Use a key made of the component identity, the version, and the advisory identifier. Component identity should use a stable name such as a package URL, not a display name. Then keep a list of locations under the group.
| Field | Role |
|---|---|
| Component identity | What is vulnerable |
| Version | Which release |
| Advisory ID (normalised for aliases) | Which issue |
| Locations | Where it appears, with owners |
Count two ways
- Groups. The number of distinct component, version and advisory combinations. This approximates the number of upgrade decisions.
- Locations. The number of places affected. This approximates rollout effort and exposure.
Report both, labelled. A trend in groups tells you whether decisions are being made. A trend in locations tells you whether updates are spreading.
Pitfalls
- Version drift. The same library at three versions makes three groups. That is correct, and it also tells you consolidating versions would shrink the work.
- Dev only dependencies. Group them separately or tag them, since their exposure differs from production dependencies.
- Vendored copies. A library copied into a source tree may not appear in any manifest. Make sure your scanner can detect it, or the count will be too low.
- Ownership. If locations belong to different teams, a group needs a primary owner for the fix and a list of affected consumers.
An example of the effect
Suppose a library with one advisory is listed in thirty workspaces at the same version. Ungrouped, that is thirty findings and a worrying chart. Grouped, it is one decision with thirty locations. If the fix is one version bump in a shared lockfile, the work is far smaller than the first view suggests.
Check your own tool
Export the findings for one monorepo and group them with a spreadsheet pivot. Compare the group count with what the dashboard shows. If the dashboard already groups, find out on which key. If it does not, ask whether the export lets you do it.
Safeguard does this kind of counting in one place: SBOM and dependency scanning, asset discovery and reachability analysis feed the same inventory, so each number can be traced back to its source. Dependency scanning records components with their locations so grouped views are possible. You can try a free scan at gold.safeguard.sh/scan.
Try it yourself
Open the demo and follow one finding from detection to resolution, noting which number on screen changes and which stays put.
Click through it at your own pace, or open it full screen.
Quick check
Is grouping hiding real work?
No, as long as locations stay visible. Grouping separates the number of decisions from the number of places to update.
What identifier groups components reliably?
A package URL or similar stable identifier is better than a display name, which can differ between tools.
Last reviewed: 19 October 2026.