Start at the root pom.xml that lists the modules, then confirm how each module inherits its dependencies. In Maven, an aggregator POM and a parent POM are different things, and a single project can be one, both or neither. Scanning only the root can miss modules that sit outside it.
Aggregator versus parent
Maven's POM reference explains the split. An aggregator lists modules so one command builds them all. A parent supplies inherited settings, including dependency versions. The reference says plainly that the two are not the same and should not be confused.
In a legacy monorepo you often find the muddle that follows from this:
- A root POM that lists modules but defines no versions.
- Modules whose parent is a different POM, in another directory.
- Modules that inherit from a company POM published to an internal repository, not stored in the repo.
Steps to find the right starting points
- Find every pom.xml and read the packaging line. Values of pom mean aggregator or parent; jar, war and others mean a deliverable.
- For each deliverable, read its parent element. Note whether the parent resolves to a path in the repository or to an artifact.
- List the modules element of each aggregator and compare with the files on disk. Modules that exist on disk but appear in no list are orphans.
- Choose starting points: each aggregator that nothing else lists, plus each orphan.
What goes wrong when you skip these checks
| Symptom | Likely cause |
|---|---|
| Scan finds far fewer packages than expected | Scanner started at a module, not the aggregator |
| Versions reported as unresolved | Parent POM lives in an internal repository the scanner cannot reach |
| Same package, two different versions | Two modules inherit from different parents |
| Whole service missing | Module not listed by any aggregator |
The internal parent case is the most common blocker. If the scanner runs in an environment with no access to your artifact repository, it cannot read the parent and must guess. Give it read access, or provide the parent POM as a file.
Use the resolved tree for confirmation
Maven's dependency plugin can display the tree for a project in formats including text, DOT, GraphML, TGF and JSON. Run it on a handful of modules and compare the output with what your scanner reports. If the two disagree on a version, find out which one is right before you trust either.
Do this for a sample, not all modules. Ten modules chosen across old and new code give you a good read on accuracy.
Dependency management sections
Look at the dependencyManagement block in the parent. It sets versions for children without adding them to the build, so a package can appear there and never be used. A good scanner reports what is used; check that yours does not flag entries that are only managed.
Record the decision
Write down the list of starting points and the reason for each. When someone adds a module next quarter, the note tells them whether it is already covered. Without it, coverage decays quietly.
Where Safeguard fits
Safeguard's dependency scanning and SBOM generation can be run from the CLI against chosen directories, which suits a repository with several Maven roots. Reachability analysis then helps rank what you find. Try a free scan at https://gold.safeguard.sh/scan.
Quick check
Do I need to scan every module separately?
Not if an aggregator lists them all. Scan from the aggregator and verify that the module count matches what is on disk.
What if the parent POM is private?
Give the scanner read access to the internal repository or supply the file. Without it, versions inherited from the parent will be missing or guessed.
Sources
Last reviewed: 19 October 2026.