GitHub announced a change to Actions cache behavior for workflow events that can be triggered without write permission to a repository. The June 26 changelog says those untrusted-trigger paths receive read-only cache tokens, while trusted default-branch workflows retain the ability to create or overwrite caches. That is a useful platform boundary, but it does not remove the need to review cache keys, restored files, permissions, and commands.
This article separates what GitHub documents from operational guidance inferred from the documented model. CodeRiskTools did not test GitHub’s hosted implementation or inspect a private repository. A read-only token can reduce one write path; it cannot prove that a workflow is safe, that a restored dependency is authentic, or that no sensitive data is exposed.
What the read-only change addresses
GitHub’s announcement concerns the token used by Actions cache operations for selected untrusted events. The practical question is whether a workflow triggered from an untrusted context can overwrite a cache that a more trusted workflow later restores. Restricting writes narrows that specific cache-poisoning route.
It does not make every cache read harmless. GitHub’s dependency-caching documentation warns that untrusted workflows may read sensitive cache contents and that poisoned caches can lead to code execution in trusted workflows. Review both directions: who can write, and what a job is allowed to restore and execute.
Map the trust boundary before changing YAML
| Question | Evidence to capture | Review interpretation |
|---|---|---|
| Which event starts the job? | Trigger, fork policy, branch filters | Classify whether the source can be changed by an untrusted contributor. |
| Which cache scope is visible? | Key, restore keys, branch and repository context | Do not assume a narrow-looking key prevents collisions. |
| What is restored? | Paths, package-manager directories, generated files | Restore only data that the job can safely treat as untrusted. |
| What runs afterward? | Install scripts, tests, build commands, action inputs | Any restored executable content needs a separate trust decision. |
| What can the token do? | Workflow and job-level permissions, secrets, environments | Use the minimum permissions, independently of cache behavior. |
Inventory the cache implementation
- List every cache action. Search workflow files and reusable workflows for
actions/cacheand setup actions that create caches implicitly. - Record the exact key. Include operating system, architecture, lockfile hash, toolchain version, and any trust-context component that prevents an unsafe collision.
- Inspect restore keys. Broad prefixes can select an older or less specific cache. Document why each fallback is acceptable.
- Separate dependency data from build output. A package-manager cache and a compiled workspace have different integrity and execution properties.
- Trace use after restore. Follow the restored path into package installation, test discovery, generated configuration, and shell commands.
- Capture failure behavior. A cache miss, partial restore, corrupt archive, or unavailable key should fail safely or rebuild from a trusted lockfile.
Red flags that remain after the platform change
- A privileged workflow restores a cache whose key can be influenced by pull-request content.
- Restore-key prefixes are shared across branches, repositories, operating systems, or toolchain versions without a documented reason.
- A job executes scripts or package lifecycle hooks from a restored directory before integrity checks.
- Secrets, credentials, private build output, or signed material are placed in a cache path.
- The workflow grants broad write permissions because a later step might need them.
- A cache hit is treated as proof that dependencies came from the intended lockfile or registry.
A bounded validation workflow
Use a disposable repository or synthetic fixture, not production credentials. First, record the workflow graph, event, permissions, cache key, restore keys, paths, and action revisions. Next, run an untrusted-trigger case with a harmless marker file and confirm which cache operations are attempted. Then run a trusted default-branch case and verify that the intended cache population path still works.
Finally, inspect the consumer job. Confirm that a cache hit does not bypass lockfile validation, that the job does not execute attacker-controlled files merely because they were restored, and that secrets are absent from the cache path. Label each observation as tested, documented, or inferred. Do not convert one successful rehearsal into a security guarantee.
How to make the review repeatable
Keep a small evidence record with the workflow commit, event payload class, action revisions, permissions, cache key template, restore paths, expected hit or miss result, and cleanup step. Bind the record to the exact change under review. If the key or trigger changes later, rerun the review rather than carrying forward an old green result.
For teams using reusable workflows, review the caller and called workflow together. A caller may pass a ref, path, or input that changes the effective trust boundary. The cache policy should be understandable from the combined execution graph, not only from the line containing actions/cache.
FAQ
Does read-only cache access stop cache poisoning?
It can reduce the ability of selected untrusted triggers to overwrite caches, according to GitHub’s changelog. It does not eliminate every cache-poisoning scenario, cache disclosure risk, or command-execution risk. Verify the current event, scope, and consumer workflow.
Should caches be disabled for all pull requests?
Not automatically. Caching can improve feedback time, but the acceptable design depends on what is cached, who can influence the key and contents, and whether trusted jobs execute restored data. Use a bounded policy instead of a blanket assumption.
Is a lockfile hash enough?
No. A lockfile hash helps distinguish dependency versions, but it does not by itself prove that the cache path is free of scripts, that restore-key fallbacks are safe, or that the workflow has least-privilege permissions.
What should be kept out of caches?
Keep credentials, tokens, private signing material, sensitive logs, and any artifact whose disclosure would exceed the job’s intended access. Treat cache contents as durable shared workflow data, not as a secret store.
Official sources and next step
- GitHub Changelog: Read-only Actions cache for untrusted triggers — documented token behavior.
- GitHub Docs: Dependency caching — cache security concepts and limitations.
- GitHub Docs: Dependency caching reference — cache action usage and key matching.
- GitHub Docs: Security hardening for GitHub Actions — broader workflow security guidance.
- actions/cache repository — official action source and inputs.
Use the single CodeRiskTools comparison hub to separate workflow scopes. The secret-scanning workflow guide covers a related evidence path. Start with the free 5-point AI code review checklist. For a local intent-bound change-review workflow paired with secret scanning, inspect the documented scope of the AI Change Firewall; it does not replace GitHub controls or human review.
Review the exact workflow change
Before merging a cache or trigger change, compare the final diff, event boundary, permissions, key construction, restored paths, and execution steps. The goal is a reversible, evidence-backed review—not a security guarantee.


