# GitHub Actions makes cache access a least-privilege workflow permission

GitHub Actions now gives workflows and jobs explicit read, write, write-only or no-cache permissions, with service-enforced limits that propagate into reusable workflows and safer defaults for low-trust events.

The change turns cache poisoning from mostly a workflow-design warning into an enforceable permission boundary. Teams can let untrusted jobs restore caches without writing them, prevent reusable workflows from escalating cache access and isolate jobs that only need to publish cache entries.

- Status: Active
- Published: 2026-09-11T22:02:12+12:00
- Updated: 2026-09-11T22:02:12+12:00
- Categories: Web Development, Cloud & Infrastructure, Deployment & DevOps, Developer Tools
- Tags: CI/CD, GitHub, GitHub Actions, supply chain security
- Canonical HTML: https://beyondthe.news/dossiers/github-actions-cache-mode-cache-poisoning-least-privilege

## What changed

GitHub made `cache-mode` generally available on September 10, 2026. Workflows and jobs can declare `read`, `write`, `write-only` or `none`, and GitHub's cache service enforces the resulting scoped cache token. Low-trust triggers such as `pull_request_target` default to read-only cache access, while trusted triggers such as `push` default to write. Explicit caller limits propagate into reusable workflows; a called workflow cannot request more cache capability than an explicit caller limit permits. GitHub also warns when a low-trust workflow explicitly restores write capability, because doing so reintroduces cache-poisoning risk.

## Why it matters

CI caches can contain executable build artifacts or dependencies that later privileged jobs trust. That makes a writable shared cache a supply-chain boundary, not merely a performance feature. `cache-mode` lets teams express that boundary in the workflow permission model: untrusted jobs can be prevented from poisoning caches, cache-producing jobs can be prevented from restoring potentially hostile entries, and reusable workflows can be capped by their callers. This is especially useful in repositories that run automation on external pull requests or share workflow components across teams.

## Cache access has four explicit capabilities

`read` permits restores but not saves, `write` permits both, `write-only` permits saves without restores, and `none` disables both. Job-level settings can narrow or override workflow-level settings.

## Low-trust events get safer defaults

GitHub applies read-only access to low-trust triggers that resolve against the default branch, including `pull_request_target`, `issue_comment` and `workflow_run`. Those jobs can consume existing cache entries but cannot replace them unless a workflow explicitly opts back into write access.

## Reusable workflows cannot silently escalate an explicit limit

An explicit cache-mode on a calling workflow or job constrains the called reusable workflow. If the callee asks for a capability outside that limit, GitHub rejects the run rather than quietly granting broader access.

## Write-only is useful for one-way cache production

A job can now publish a cache without first restoring anything from the shared cache. That gives security-sensitive pipelines a way to separate cache creation from cache consumption instead of treating both as one permission.

## Overrides remain deliberately dangerous

A workflow can explicitly grant write capability to a low-trust trigger, but GitHub warns that this defeats the secure default and can reopen cache-poisoning attacks. The control is therefore an enforcement primitive, not a guarantee that every declared policy is safe.

## Key details

- `cache-mode` is generally available on github.com for all GitHub plans.
- Supported modes are `read`, `write`, `write-only` and `none`.
- Low-trust events default to read-only cache access; trusted events default to write.
- The cache service enforces the selected mode through scoped cache tokens.
- Explicit caller limits propagate into reusable workflows and cannot be exceeded by the callee.
- A write-capable override on a low-trust event can reintroduce cache-poisoning risk and triggers a warning annotation.
- Existing workflows that do not set `cache-mode` continue to receive trigger-based defaults.

## Builder takeaways

- Set `cache-mode: read` explicitly on workflows that process untrusted input and only need dependency restores, rather than relying on team members to remember the trigger-specific default.
- Use `write-only` for trusted cache-population jobs that should never execute artifacts restored from a shared cache.
- Put cache limits on reusable-workflow callers so downstream workflow changes cannot silently acquire broader cache access.
- Audit `pull_request_target`, `issue_comment` and `workflow_run` jobs before granting any write-capable cache mode; those triggers commonly run with elevated context.
- Do not store secrets or credentials inside caches even when permissions are restricted; cache contents are not a secret store or integrity-verification mechanism.

## What to watch

- Support for cache-mode in GitHub Enterprise Server and third-party Actions runners/tooling.
- Whether organization-level policy can eventually require or cap cache permissions across repositories.
- Additional audit-log visibility for cache writes and permission overrides.
- Adoption by popular reusable workflows and setup actions that currently assume read/write cache behavior.

## Uncertainties

- The control reduces cache-poisoning opportunity but cannot prevent a trusted workflow itself from writing malicious or corrupted cache contents.
- Third-party actions may have their own assumptions about cache availability and need testing under read-only or write-only modes.
- An explicit write override on a low-trust event remains possible, so workflow review still matters.

## Sources

- [Control GitHub Actions cache access with cache-mode](https://github.blog/changelog/2026-09-10-control-github-actions-cache-access-with-cache-mode/) — GitHub · primary changelog · 2026-09-10T00:00:00+12:00. Primary launch details and default/override behavior.
- [Dependency caching reference](https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching) — GitHub Docs · primary documentation. Detailed mode semantics, low-trust trigger behavior, reusable-workflow inheritance and cache-poisoning guidance.

