Avoid mavenLocal() and flatDir in shared or release builds. Gradle's docs say it bypasses its dependency cache for local Maven and Ivy repositories, that these repositories make reproducible builds harder, and that they should be limited to prototyping. A file on one laptop is not a dependency your team or your auditors can see.
What they do
mavenLocal() points at the Maven repository on your own machine, and flatDir points at a folder of files. Both are local repositories. They are common because they are the quick way to test a library change before publishing it.
What the docs say
Gradle's repository documentation states two things. First, Gradle bypasses its dependency cache for local Maven and Ivy repositories. Second, these repositories make reproducible builds harder, so the page recommends limiting them to prototyping.
Why this matters for security
| Problem | Effect |
|---|---|
| Not reproducible | Another machine or CI cannot rebuild the same thing |
| No provenance | A file in a folder has no registry record or publisher |
| No checksums from a repository | Verification has nothing authoritative to compare to |
| Invisible to review | The artifact is not in version control |
| Poor for inventory | Scanners may see a coordinate with no source |
A local repository entry can also mask a problem: the build works on your machine because a stale artifact sits in your home directory, and fails on CI. Worse, it can work on CI only if an image carries a leftover file.
Better patterns
- Publish internally. Use an internal repository for work in progress modules, with a SNAPSHOT or a dated pre-release version.
- Use included builds. Gradle composite builds let you develop a library and an app together without publishing.
- Use project dependencies inside one repository.
- For vendor jars, host them in your internal repository with a checksum and an owner, instead of a flatDir.
Steps to find and remove them
- Search every build and settings file for mavenLocal and flatDir.
- Check init scripts too, since they can add a local repository. See Gradle init scripts.
- For each hit, decide: temporary experiment or real dependency.
- Move real dependencies to a proper repository.
- Add a CI check that fails if either appears in a release build.
A note on Android
Android's docs show mavenLocal() among the ways to declare a local repository. That is a statement of what is possible, not a recommendation for release builds.
Try it yourself
Click through it at your own pace, or open it full screen.
Check how a component with no clear origin appears. Those entries are hard to defend in an audit.
Safeguard's SBOM and dependency scanning record every component a repository resolves, and the free scan at gold.safeguard.sh/scan can show you what your build lists.
Quick check
Is mavenLocal fine for quick local testing?
Yes, that is the use the Gradle docs call out: prototyping. Keep it out of shared and release builds.
Does Gradle cache artifacts from local repositories?
No. The docs say Gradle bypasses its dependency cache for local Maven and Ivy repositories.
Sources
Last reviewed: 19 October 2026.