Safeguard
Security Guides•

Should I remove unused Maven dependencies to cut security risk?

Maven's dependency:analyze finds declared but unused and used but undeclared libraries. Use it to shrink attack surface, but check false positives first.

Safeguard Security Team
3 min read

Usually yes. Every library you ship is code you must patch, so removing declared but unused dependencies shrinks what you track. Run dependency:analyze to find candidates, but verify each one, because bytecode analysis can mislabel libraries loaded by reflection or at runtime.

Definition

The Maven dependency plugin's analyze goal sorts dependencies into groups:

GroupMeaningAction
Used and declaredCorrectNone
Used but undeclaredClasses are referenced but the artifact is not in your POM, so it arrives transitivelyDeclare it directly
Unused but declaredIn the POM but no referenced classesOften removable

It also flags dependencies that only test code uses but that are not declared with test scope.

Why it matters for security

An unused declared library still gets shipped and still shows up in scans. A used but undeclared library is riskier in a quieter way. You depend on a transitive path you do not control. When the parent library changes its dependencies, your code can break or silently move to a different version.

Declaring what you use makes version decisions explicit, which makes pins and fixes easier.

Run it

mvn dependency:analyze
mvn dependency:analyze -DfailOnWarning=true

The standalone goal runs test-compile first. In a lifecycle build, use analyze-only. FailOnWarning defaults to false, so warnings are reported without failing the build.

False positives to expect

The default analyzer works on bytecode. The plugin offers settings to correct what it gets wrong. Common culprits are libraries loaded through reflection or service lookup, and runtime-only dependencies such as database drivers. Use usedDependencies to mark one as used, and the ignored options to filter by coordinates. IgnoreUnusedRuntime relaxes unused checks for runtime scope.

Never delete a library purely because the report says unused. Remove it on a branch, build, run the full tests, and exercise startup.

Steps

  1. Run analyze and save the report.
  2. Sort entries into obviously unused, suspicious, and runtime-loaded.
  3. Remove the obvious ones first.
  4. For used but undeclared, add the declaration at the version you already resolve.
  5. Add the persistent exceptions to the plugin configuration so the report stays quiet.
  6. Turn on failOnWarning once it is clean.

For finding what is actually reachable at runtime, see Is a vulnerable Java dependency actually reachable?.

Try it yourself

Click through it at your own pace, or open it full screen.

Count how many components are transitive. That is the part dependency:analyze helps you make explicit.

Where Safeguard fits

Safeguard's dependency scanning and SBOMs give you the full component list to compare with the analyze output. Reachability analysis helps you see which findings sit in code your application calls. Try the free scan.

Quick check

Will dependency:analyze fail my build by default?

No. FailOnWarning defaults to false, so it reports but does not fail.

Why might a needed library show as unused?

The analysis is bytecode based, so reflection, service lookup and runtime-only use can be missed.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.