Only your trusted CI system should write to a shared Bazel remote cache. Developers and pull request builds should read from it. Bazel's own documentation says to take care over who can write, and suggests allowing only CI. Read only access is set with one flag.
What the cache holds
A remote cache stores two things: an action cache, which maps action hashes to result metadata, and a content addressable store of output files. It also keeps stdout and stderr for every action. Anyone who can write to it can influence what other people's builds receive, because a cache hit means Bazel uses the stored output instead of building.
Bazel's docs also point out that the cache holds your binaries, so it needs to be secure.
The risk in one sentence
A bad entry in a shared cache affects everyone who hits it. The sandboxing documentation says this directly: incorrect cache reuse creates problems in remote caching, and wiping the whole cache is not a practical fix.
Who gets which permission
| Actor | Read | Write | Why |
|---|---|---|---|
| Protected branch CI | Yes | Yes | Controlled environment, reviewed code |
| Pull request CI from forks | Yes or no | No | Untrusted code should never seed the cache |
| Developer laptops | Yes | No | Speed without the ability to poison |
| Release builds | Optional | No | Prefer a clean, fully verified build |
This table is a recommendation, not a Bazel rule. The product only provides the switches.
The settings
To read and write, point at the cache. To make a client read only, add one more flag.
build --remote_cache=https://cache.example.internal
build --remote_upload_local_results=false
You can also exclude specific targets by tagging them with no-remote-cache, which is useful for anything that embeds secrets or machine specific data.
Rollout plan
- Put the cache behind HTTPS and authentication. Basic auth sends credentials in plaintext, so only use it over HTTPS.
- Give CI a write credential stored as a protected secret, available only to protected branches.
- Ship a shared .bazelrc that sets read only for everyone else.
- Log who wrote what where your cache server allows it.
- Rehearse deletion. Bazel's docs list creating a clean cache after poisoning as a reason to delete content, and note you cannot tell which build produced an entry, so the realistic response is to clear it all.
Cloud storage keys
If you use an object store, the docs warn that anyone holding the service account key can read and write arbitrary data in the bucket. Treat that key like a deploy credential.
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
Click through the pull request gate and note where a policy can stop an untrusted change before it reaches shared state.
Click through it at your own pace, or open it full screen.
Quick check
Does read only mode stop a developer from being served a bad entry?
No. It stops them from writing one. Reads still return whatever is in the cache, so protect the write path.
Can I tell which build created a cache entry?
Bazel's documentation says there is no way to distinguish which output belongs to a specific build when deleting. Add logging on your server if you need provenance.
Sources
Last reviewed: 19 October 2026.