Safeguard
Developer Tools•

How do you upgrade a vulnerable transitive dependency in Gradle?

Add a Gradle dependency constraint with a because note to raise a transitive library without declaring it directly. Steps, example and how to verify.

Safeguard Security Team
3 min read

Add a dependency constraint. In Gradle, a constraint raises the version of a library that something else pulls in, without adding it as a direct dependency. Include a because note that records the reason, then run dependencyInsight to confirm the new version was selected.

The Gradle mechanism

Gradle's documentation says constraints let you upgrade a transitive dependency without declaring it directly. A constraint does not add a module to the graph. It only takes part in version selection when something else brings the module in. By default it expresses at least this version. If the module is not pulled in transitively, the constraint has no effect.

Gradle's own example upgrades commons-codec, which httpclient brings in:

dependencies {
    implementation("org.apache.httpcomponents:httpclient:4.5.13")

    constraints {
        implementation("commons-codec:commons-codec:1.15") {
            because("httpclient pulls in 1.11 which has known vulnerabilities")
        }
    }
}

Steps

  1. Find the path. Run ./gradlew :app:dependencyInsight --dependency <name> to see which library brings it in and why this version was chosen.
  2. Find a fixed version. Use the advisory's fixed version, and check it is compatible with the library that needs it.
  3. Add the constraint. Put it in the dependencies block with a because note naming the advisory.
  4. Verify. Run dependencyInsight again. The selection reason should now say by constraint.
  5. Test. Run your tests and a manual pass. The library that pulled in the old version was built against it.
  6. Revisit. When the parent library ships its own fix, remove the constraint.

Which approach to use

ApproachUse when
Upgrade the direct dependencyA newer release of it already pulls in the fixed version
Constraint on the transitive libraryThe parent has not updated and the fix is compatible
Excluding the transitive libraryYou do not use the feature that needs it, and have tested removal
Replacing the parent libraryIt is abandoned and no fix is coming

Start with the first row. A constraint is a patch you own until the parent catches up.

Pitfalls

  • A constraint that forces a major version jump can break the parent library at runtime.
  • Constraints do not help for libraries bundled inside another library's binary.
  • If you use dependency locking, update the lock file after the change.
  • Do not leave constraints without a note. A year later nobody will know why they exist.

For pinning in general, see Gradle dependency locking.

Try it yourself

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

Look for which package carries the fix and which one needs to change. That is the same pair you find with dependencyInsight.

Quick check

Does a constraint add the library to my app?

No. It only affects selection when another dependency brings the library in.

How do I confirm the fix took effect?

Run dependencyInsight and read the selection reasons, then rescan the built dependencies.

Safeguard identifies vulnerable components through dependency and SBOM scanning and can open fix PRs through autonomous remediation, which is off by default with every category on Manual. Run a free scan.

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.