Safeguard
Developer Tools•

How do you make Turborepo cache read only for pull requests?

Use the cache flag to give pull request builds read access to the remote cache and no write access. Examples, a CI split and common mistakes.

Safeguard Security Team
3 min read

Run pull request builds with the cache option set to local read write and remote read only. Turborepo will download shared artifacts but never upload new ones from untrusted code. Let only protected branch builds use remote read write, so a pull request cannot seed the cache others reuse.

What the flag does

The cache option takes a comma separated list of sources, local and remote, each with a mode: read write, read only, or write only. The default is read and write for both. If a source is omitted, reading and writing are both disabled for it. The reference gives these examples:

# read and write local, only read remote
turbo run build --cache=local:rw,remote:r

# only read local, read and write remote
turbo run build --cache=local:r,remote:rw

# no remote activity
turbo run build --cache=local:rw

# no local cache, only read remote
turbo run build --cache=local:,remote:r

A CI split worth copying

JobSettingReason
Pull request from a forkRemote none, or read onlyUntrusted code should not write
Pull request from your own branchRemote read onlyFaster, cannot poison
Protected branch buildRemote read writeReviewed code seeds the cache
Release buildClean build, consider forceYou want to verify, not trust

The force flag overwrites existing task caches for a run, which is useful for a release build that should not trust earlier entries.

Why this is a security control

A shared cache works because everyone trusts what is in it. The Turborepo remote caching page warns that remote caching comes with responsibility: cache correctly first, check environment variable handling, and remember that logs are treated as artifacts. A write path from every pull request makes all of those risks larger.

Pair the flag with signing, which makes tampering visible, and with a credential that is scoped so only the protected branch job can write.

Steps

  1. Decide which jobs may write. Write the list down.
  2. Set the cache option explicitly in every job script, not once in a shared default.
  3. Store the cache token as a secret available only to protected branches.
  4. Enable artifact signing and restrict the signing key to the same jobs.
  5. Add a periodic clean rebuild of a release candidate and compare.

Mistakes to avoid

  • Relying on a default. The default is read and write for both sources.
  • Giving every job the same token.
  • Printing secrets in task output. Logs are replayed from the cache.
  • Assuming a self hosted cache is private by default. Follow the authentication model of whatever server you run.

Quick check

What does omitting the remote source do?

It disables both reading and writing for that source in that run.

Should fork pull requests read the remote cache at all?

That is a risk decision. Reading is lower risk than writing, but if you do not want untrusted code to receive shared artifacts, disable remote for those jobs.

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.