A dynamic version such as 5.+ or [5.0,6.0) lets Gradle pick a newer release at build time. For a mobile app that means a release build can contain library code nobody reviewed, with no change in your repository. Pin versions or turn on dependency locking, and update on purpose.
What the docs say
Gradle's locking documentation states that dynamic selectors can pick up new releases over time and break builds without any change to your code. Locking records the resolved version of each dependency and transitive dependency in a lock file. Later builds check against it, and if resolution would change, the build fails.
Gradle also warns against using locking with changing versions such as snapshots.
Why mobile is worse than most
A server fix is deployed in minutes. A mobile build is submitted to a store, reviewed, and rolled out in stages. Whatever was in the binary at build time is what users hold for months. If a dynamic selector pulled in a bad version on the day of your release build, you ship it, and you may not be able to rebuild the same binary later to investigate.
Two failure cases:
- Silent breakage. A new minor version of a library changes behavior, and the release build passes only because tests missed it.
- Silent compromise. A malicious or mistaken release lands in the version range you allowed, and your next build ingests it.
Three options compared
| Approach | Reproducible? | Picks up fixes automatically? | Effort |
|---|---|---|---|
| Exact version in the build file | Yes | No | Manual bumps |
| Dynamic selector, no lock | No | Yes, unreviewed | None, until it breaks |
| Dynamic selector plus lock file | Yes | Only when you refresh | Run an update step |
Most teams are better served by exact versions or a lock file, plus a scheduled step that proposes updates for review.
A scenario
Say your app declares a networking library with a selector like 4.+. On Monday the release build resolves to 4.11. On Thursday the maintainers publish 4.12, which changes how redirects are handled. A hotfix build on Friday resolves to 4.12, and nobody touched the build file. The hotfix now carries a behavior change that was never part of the review, and the store rollout begins.
With a lock file, Friday's build would have resolved to 4.11 again, and the move to 4.12 would appear as a diff in the lock file for someone to read.
How to turn locking on
From Gradle's documentation:
dependencyLocking {
lockAllConfigurations()
}
Then write the lock state:
./gradlew dependencies --write-locks
The file is gradle.lockfile in each project directory, and Gradle says to check lock files into source control. To update only some modules, use --update-locks with a comma separated list. Our walkthrough is in Gradle dependency locking: how to turn it on.
Quick check
Do lock files stop me getting security fixes?
They stop unreviewed changes. You still update, but on purpose, by refreshing the locks and reviewing the diff.
Should the lock file be committed?
Yes. Gradle's documentation says to check lock files into source control.
Safeguard's dependency scanning and SBOM generation work from your resolved versions, so a locked build gives it a stable list to match against known vulnerabilities. A free scan is available.
Sources
Last reviewed: 19 October 2026.