SHA pinning is now the default advice for securing GitHub Actions workflows, and many platform teams enforce it across their organizations. But a recent platform engineering community webinar showed that pinning solves a narrower problem than most teams assume. Here is what pinning actually verifies, what it leaves open, and how you can close the gap.
TL;DR: Main insights
- Commit SHA pinning guarantees the exact bytes you run, but it does not verify who wrote them or whether they belong to the project you think you are using.
- Because GitHub forks share an object store with the upstream repository, an impostor commit from a fork can pass every pinning check.
- GitHub's roadmap features - immutable releases and workflow lock files - represent real progress, but they do not close the provenance gap on their own.
- A curated, rebuilt catalog of actions can address provenance without requiring your team to maintain every mirror.
This webinar was hosted by Mariya, who moderated the session and Q&A. The speaker was Erika Heidi, a Staff Developer Relations Engineer at Chainguard. Erika joined Chainguard in 2022, has been part of the GitHub Stars program since 2021, and brings a background in Linux containers and PHP development. They create content and documentation that help teams secure their software supply chains.
You can watch the full discussion here if you missed it.
A year of CI/CD supply chain incidents
Erika opened with a timeline of CI/CD supply chain incidents spanning March 2024 to March 2025. What made this period notable was how attacks built on each other - attackers reused techniques and stolen credentials from earlier compromises, compressing the time between incidents.
- Reviewdog action-setup compromise (March 2025): A tag poisoning attack that became the upstream origin of the next incident.
- tj-actions/changed-files: Tag poisoning combined with memory dumping of runner secrets. More than 23,000 repositories were affected.
- Ingress-nginx and build system attacks: These abused
pullrequesttarget, which runs code in the context of the target repository with full access to its secrets. The goal was to steal npm tokens. - Shai-Hulud npm worms: A self-replicating worm that compromised post-install hooks, followed by a second variant using pre-install hooks to target cloud credentials.
- The Trivy breach: An initial compromise through
pullrequesttargetled to a personal access token with broad organization access. Because credential rotation was not atomic, attackers retained access and force-pushed malicious tags and binaries.
Why CI/CD is a high-value target
Open source CI/CD pipelines offer attackers an exceptional return on effort. Exploiting one widely used action reaches far more projects than targeting a single repository. Attackers can also read your workflows directly and see exactly what is installed, which secrets are in scope, and which tokens are available.
Several trends are making this worse:
- The exploitation window is collapsing. Erika noted that the time-to-exploit is now described as negative seven days - meaning exploitation can begin roughly a week before a vulnerability is publicly disclosed.
- More code flows through CI than humans can review. Automated agents open pull requests around the clock, workflows run dozens of actions, and each action pulls in a deep dependency tree.
- Review fatigue is real. As Erika put it: "I have approved several of these in the past and I didn't ever look at what those were pointing actually." Digest update PRs look routine, and that is exactly what attackers count on.
What SHA pinning actually does - and does not do
There are three ways to reference an action in a workflow, and two of them are mutable:
- Branch: Mutable. Pinning to
mainmeans anything merged into that branch runs in your workflow. - Tag: Also mutable. A tag points to a commit, and that pointer can be changed - exactly what happened in the tj-actions and Trivy incidents.
- Commit SHA: The only immutable reference. A 40-character SHA identifies a specific, fixed point in time.
Teams that had pinned to a SHA during the tj-actions and Trivy incidents were not affected by the repointed tags, because their workflows still referenced the older, known-good commits. That is a real and meaningful protection.
But here is what SHA pinning does not verify:
- Authorship: Who actually wrote the commit.
- Project membership: Whether the commit genuinely belongs to the project you think you are running.
- Runtime behavior: Container actions build their image at runtime, so their dependencies are not deterministic. Pinning freezes the repository at a commit, not whatever a Dockerfile downloads when it executes.
The impostor commit problem
This is the central insight of the talk, and it is worth understanding precisely. Org-level pin enforcement checks only that a reference is a 40-character SHA. It does not check who wrote the commit or whether it belongs to the upstream project.
This is possible because of how Git and GitHub work. Forks share the object store of the upstream repository, so a commit made in a fork is reachable through the upstream repository URL. As Erika emphasized, this is a feature of Git, not a bug - but it creates a meaningful attack surface.
Erika demonstrated this live: a pull request appeared to update the digest for actions/checkout. The diff looked completely ordinary - one 40-character SHA replaced by another under the legitimate actions/checkout path. But the new commit lived only in a fork Erika had created. After merging, the workflow log confirmed the action was running code from the fork. An attacker would place credential exfiltration logic there instead.
Chainguard documented this technique in 2023. The attack needs to succeed only once to cause damage, even if the reference is updated afterward.
What GitHub's roadmap addresses - and what it does not
Erika gave GitHub credit for meaningful progress on two fronts.
Immutable releases have been generally available since October 2024. They lock a tag once a release is published, preventing it from being repointed. They also add a signed attestation using Sigstore that records the tag, commit SHA, and release assets. You can verify that attestation with the GitHub CLI or any Sigstore-compatible tool.
Workflow lock files bring the lock file concept from language package ecosystems into CI. Currently in public preview, they record exact commit references for the actions in your workflow and for the dependencies those actions use. Critically, the recorded commit must exist on a branch of the source repository - a check that helps defend against impostor commits.
Erika's assessment was candid. These features move the ecosystem forward, but they do not close the provenance gap alone:
- Immutable releases are opt-in per repository. The maintainers of the actions you use must adopt them. As a consumer, you cannot enable them on someone else's repository.
- Lock files improve publisher identity checks but do not prove full provenance, and the runtime concern for container actions remains unaddressed.
- Authorship, project membership, and runtime behavior remain open questions.
Closing the gap: Options and trade-offs
Erika outlined three practical approaches, each with real costs:
- Vendoring and mirrors: Copy the action source into a repository you control, review it, and run only your copy. Authorship and membership become your decision. The cost is that every action becomes yours to maintain - security fixes will not arrive automatically, and the burden scales with every action you adopt.
- Provenance verification: Automate checks that tie an artifact to its source and build origin. The cost is that someone on your team must define what "trusted" means and enforce it consistently for each action.
- A curated catalog: Use actions that are already vetted for authorship, rebuilt under controlled conditions, and maintained for you rather than by you.
Erika presented Chainguard Actions as an example of the third approach. It is a catalog of more than a thousand hardened actions with the following properties: each action is verified to originate from its genuine upstream project; you consume from the catalog rather than from an arbitrary commit SHA, so impostor commits are not reachable; rebuilds are deterministic and container actions are built under controlled conditions; and each action ships with a hardening report explaining what was changed and why.
Erika was explicit that this does not replace pinning: "Pinning guarantees the bytes but does not guarantee provenance." You keep your SHA pinning and your org-level enforcement, and you add verified provenance on top.
Practical guidance from the Q&A
During the Q&A, a participant asked whether a workflow lock file can replace pinning when using a curated catalog. Erika clarified that the lock file itself records SHA references - the difference is where the SHA is stored. You still define the version, and the lock file resolves the exact commit for you.
Maria asked for top advice for platform engineers. Erika offered two recommendations:
- Pin everything to a commit SHA rather than a tag, because tags can be hijacked and you do not control the maintainer's repository. Use tools like Dependabot or digest bots to keep those pins current.
- Minimize your attack surface. Use minimal, hardened container images, and remember that the entire ecosystem that builds, runs, and distributes your code is a potential target.
If you enjoyed this, find more great insights and events from our Platform Engineering Community.
If you want to dive deeper, explore our instructor-led Platform Engineering Certified Professional course and connect with peers from large-scale enterprises who are driving platform engineering initiatives.
Key takeaways
- Pinning guarantees bytes, not provenance. Keep enforcing SHA pinning at the organization level, but do not treat it as proof that code originates from the project you trust. It is a necessary control, not a sufficient one.
- Fork commits can pass every pinning check. Because forks share an object store with upstream, impostor commits are reachable through the upstream URL. When you review digest update pull requests, verify that the new commit actually belongs to the upstream project - not just that it is a valid SHA.
- Adopt GitHub's new controls, and know their limits. Immutable releases and workflow lock files are meaningful improvements, but they depend on maintainer adoption and leave authorship, project membership, and runtime behavior gaps open.
- Weigh the maintenance cost of closing the gap. Vendoring gives you control but scales poorly. A curated, rebuilt catalog can reduce your maintenance burden while adding verified provenance on top of the pinning you already enforce.

