Run the Gradle dependencyInsight task with the library name and the configuration you ship. It shows why that version was selected and which dependency path brought it in. Run the dependencies task first for the full tree. Both work for Java and Kotlin projects built with Gradle.
Step 1: view the tree
Gradle's built-in dependencies task renders the dependency tree. By default it covers all configurations in a single project, so limit it to the one that matters:
./gradlew -q dependencies --configuration runtimeClasspath
The docs say the tree shows the selected version of each dependency and information on conflict resolution. In the output, an asterisk marks a repeated subtree, a letter c marks a constraint, and a letter n marks a configuration that cannot be resolved.
Step 2: ask why a version was chosen
./gradlew -q dependencyInsight --dependency jackson-databind --configuration runtimeClasspath
The dependency option takes a full group and name or part of one, and if several match it reports on all of them. The report identifies the reason and origin of the version selection. The documentation's sample shows a reason like selected by conflict resolution between two versions.
Two more options help: one that renders only a single path to the dependency, and one that renders all variants.
Step 3: pick the fix
| Finding | Action |
|---|---|
| A direct dependency brings the old version | Upgrade it |
| A transitive path brings it in | Upgrade the nearest parent, or add a constraint |
| Conflict resolution picked the old version | Check for another requirement holding it back |
| It only appears in a test configuration | Lower priority, but still track it |
For the constraint route, see our post on forcing a fixed transitive version in Gradle.
Pick the right configuration
Gradle's dependency scope is represented by configurations. Test classpaths and runtime classpaths hold different sets, and the docs show examples of passing a configuration name. Check the one your release artifact uses, usually the runtime classpath for the module you ship. For Java plugin projects the insight task defaults to the compile classpath, so name the runtime one explicitly.
Try it yourself
Click through it at your own pace, or open it full screen.
Pick a component and look for whether it is direct or pulled in by another package, which is the same question the Gradle task answers.
Quick check
What if the vulnerable library shows up under several configurations?
Check which one ships. The runtime classpath of the deployed module matters most. Others, such as tests, are lower risk.
Does Kotlin change any of this?
Not for Gradle projects. Kotlin builds use the same dependency tasks, and the Kotlin DSL is only the way you write the build file.
Safeguard's SBOM and dependency scanning shows components in a project with their direct or transitive status, and reachability analysis helps decide which to fix first. Try the free scan.
Sources
Last reviewed: 19 October 2026.