All four build systems let you share a cache, but they give you different controls. Bazel and Turborepo offer a read only switch for clients, Gradle defaults remote push to off, Turborepo can sign artifacts, and Nx defines token based access in its server specification. Combine the tool's switches with your own access control.
Comparison table
| Control | Bazel | Gradle | Nx | Turborepo |
|---|---|---|---|---|
| Read only client | Yes, by disabling upload of local results | Yes, push is a setting | Read only tokens in the server spec | Yes, cache option with remote read only |
| Default for remote writes | Read and write when a cache is configured | Remote push off by default | Depends on authentication settings | Read and write by default |
| Integrity check | Action hashes and content addressed storage | Trust in the cache server, TLS required by default | Hash keyed entries, tokens | Optional HMAC signing of artifacts |
| Secrets risk | stdout and stderr stored | Outputs shared through the cache | Terminal output stored | Logs treated as artifacts |
| Known foot gun | Untracked host tools, leaking environment | Allowing untrusted servers | Missing inputs in the hash | Loose environment mode |
Cells describe what the documentation we reviewed says about each tool. Check current docs before relying on a detail, because defaults change between versions.
What the table does not show
None of these tools can tell whether the person writing an entry is trustworthy. They give you switches. The decision about who may write is yours, and it should be made the same way for all four.
A rollout order that works for any tool
- Inventory the caches. Local, remote, and any CI cache that holds build outputs.
- Make clients read only by default. Developers and pull requests read, trusted CI writes.
- Use TLS and authentication everywhere. Do not disable certificate checks to get past a trust error.
- Complete the hash. Declare environment variables, tool versions and generated inputs.
- Keep secrets out of outputs and logs. Both are cached and may be restored elsewhere.
- Add integrity. Use signing where the tool supports it, or restrict the server's write path where it does not.
- Rehearse the wipe. Know how to clear every cache and rebuild releases from source.
Why the foot guns differ
Bazel's risk centers on actions reading things outside the declared inputs. Gradle's centers on trust in the cache server. Nx and Turborepo, being script oriented, most often go wrong on environment variables and printed secrets. Learn the one for your stack first.
What to do if you run more than one
Some monorepos use a language specific build for services and a JavaScript task runner for web packages. Treat each cache as a separate system with its own writer list. A shared credential across them turns a small compromise into a large one.
Where Safeguard fits
Safeguard can inventory the dependencies your repository declares through SBOM and dependency scanning, and reachability analysis helps you decide which findings matter first. You can try a free scan on a repository to see what it finds. Check coverage for your specific build files before relying on it.
Try it yourself
Open the pull request gate demo and see how a policy can require checks before a change is accepted. Apply the same thinking to who may write to your caches.
Click through it at your own pace, or open it full screen.
Quick check
Which tool has the safest defaults?
That depends on version and setup, so avoid relying on defaults. Gradle documents remote push as off by default, while others write by default once a remote cache is configured. Set the behavior explicitly.
Is a local disk cache a risk?
It is lower risk than a shared cache, but it can still hold stale or wrong outputs. Clear it after a compromise.
Sources
- Bazel documentation: Remote caching
- Gradle documentation: Build cache
- Nx documentation: Self-hosted remote cache
- Turborepo documentation: Remote Caching
Last reviewed: 19 October 2026.