SHA pinning has won the argument. After a year of high-profile CI/CD compromises, pinning every GitHub Action to a full 40-character commit SHA has become the house rule for platform and security teams. GitHub lets you enforce it as an org-level policy, and nearly every hardening guide recommends it.

So it got the room's attention when Erika Heidi, Staff DevRel Engineer at Chainguard, opened her Platform Engineering community webinar by arguing that pinning solves a narrower problem than most teams think. Her one-line summary: immutability is not the same as provenance.

Here's what she covered, and what platform teams should take from it.

A year of CI/CD supply chain incidents

Erika started with a timeline of incidents from March 2025 to March 2026. The groups behind them differed, but each attack borrowed ideas from the ones before it.

  • reviewdog/action-setup (March 2025). Attackers poisoned tags in the reviewdog action, which became the upstream foothold for the next incident.
  • tj-actions/changed-files (March 2025). Every version tag was repointed to a malicious commit that dumped runner memory, leaking secrets into workflow logs. More than 23,000 repositories were affected.
  • s1ngularity / Nx (August 2025). A pull_request_target misconfiguration let attackers steal an npm publishing token. It was also one of the first supply chain attacks to weaponize AI CLI tools to hunt for secrets on victims' machines.
  • npm package hijacking (September 2025). Phishing against maintainers of packages like chalk and debug yielded more stolen npm tokens.
  • Shai-Hulud and its second wave (September and November 2025). A self-replicating npm worm spread first through post-install hooks, then pre-install hooks, harvesting credentials (cloud credentials, in the second wave) and injecting itself into every package a victim maintained.
  • Trivy (February–March 2026). Another pull_request_target misconfiguration exposed a personal access token with org-wide permissions at Aqua Security. Credentials were rotated, but not atomically, and the attackers kept access. Weeks later they force-pushed nearly all of the trivy-action tags to malicious commits and tampered with the distributed binaries.

"The Trivy compromise changed the whole industry and how we think about software supply chain security," Erika said.

Why CI/CD is the target

The answer is economics. Compromising one gated product gets an attacker one target. Compromising a widely used open source dependency or action gets them thousands. CI/CD is where the valuable material converges: secrets, API tokens, cloud and deployment credentials. In open source, workflows are public, so attackers can read exactly what gets installed and which secrets are in play.

Exploitation is also getting faster. Citing Mandiant's M-Trends 2026 data, Erika pointed to a time-to-exploit window that has shrunk from more than 700 days in 2020 to 44 days in 2025, and is now going negative: exploitation increasingly starts before a vulnerability is even disclosed. AI makes it easier than ever to turn a researcher's proof of concept into a working exploit in a day or two.

Meanwhile, the volume of change flowing through CI keeps climbing. Agents open pull requests around the clock, workflows pull in dozens of actions with deep dependency trees, and human review stays flat at best. "We have review fatigue, and we've started passing things without scrutiny," Erika said.

What SHA pinning gets right

There are three ways to reference an action in a workflow:

  • Branch (@main): mutable. Whatever landed last is what runs. Erika called pinning to main "the worst practice."
  • Tag (@v4): looks fixed in time, but it's also mutable. A tag is just a pointer that a maintainer, or an attacker holding the maintainer's credentials, can move.
  • Commit SHA (@a1b2c3…): immutable. The bytes are frozen at a specific point in the repository's history.

Tag repointing is exactly what happened with tj-actions and Trivy. Teams pinned to a SHA kept running the old, clean commit and never noticed the attack. That's the class of problem pinning was built to stop, and it worked.

Where pinning falls short: imposter commits

There was a detail in the Trivy incident that few people noticed. The same attackers planted malicious commits in actions/checkout while spoofing a real maintainer. A workflow pinned to one of those SHAs would have passed every check.

The reason lies in how GitHub works. Org-level SHA enforcement checks one thing: is this reference a 40-character commit SHA? It doesn't check who authored the commit, or whether the commit belongs to the project you think you're running. And on GitHub, forks share the upstream repository's object store, so a commit that exists only in a fork is reachable through the upstream URL. "It's not a bug, it's a feature," Erika said.

She demonstrated it live. She forked actions/checkout, added a commit to her fork that printed "checkout running from fork," and opened a pull request that looked like a routine bot-generated digest bump from 4.3.1 to 4.3.2:

uses: actions/checkout@<40-character-sha>

The line looked canonical. Once merged, the workflow log showed actions/checkout running at that commit, but the commit wasn't part of actions/checkout at all. An attacker would replace the debug line with code that exfiltrates secrets, downloads malware, or publishes using your GitHub token. Chainguard documented imposter commits back in 2023, but the technique is still little known, and it only needs to run once. By the time anyone notices, the tokens may already be gone.

"I've approved several of these in the past without ever looking at what they pointed to," Erika admitted.

That leaves three things SHA pinning doesn't verify:

  1. Authorship: who wrote the commit. Anyone's fork commit can be pinned.
  2. Project membership: being reachable through the upstream URL doesn't mean a commit belongs to the project.
  3. Runtime: container actions often build their image at runtime. If the pinned commit contains a Dockerfile that downloads dependencies, what actually executes isn't frozen.

GitHub's roadmap helps, but doesn't close the gap

Erika gave GitHub credit for two meaningful improvements.

Immutable releases, generally available since October 2025, lock a release's tag and assets so they can't be moved or changed, and attach a Sigstore-signed attestation recording the tag, commit SHA, and assets. Consumers can verify it with the GitHub CLI or any Sigstore-compatible tool. The catch: it's opt-in per repository, so it only protects you if the maintainers of the actions you consume turn it on. As a consumer, you can't do anything about it.

Workflow lock files, in public preview as of October 2026, bring the lockfile model to CI. An actions.lock file pins a workflow's actions and their transitive dependencies to exact commits, and the locked commit must exist on a branch of the source repository, which helps against fork-only imposter commits. Repo- and org-level policies can require a lock file, though teams will need to maintain them with the GitHub CLI.

Her honest scorecard:

Gap Status
Tag repointingSolved, if maintainers opt in
Publisher identityImproved
Commit authorshipOpen
Project membershipOpen
Runtime buildOpen

Three ways to close the rest

Erika walked through three approaches, all judged against the same question: can your team actually maintain it?

Vendoring and internal mirrors. Copy each action 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, upstream security fixes land in your backlog, and the burden grows with every action you adopt.

Provenance verification. Use signed attestations to tie each artifact to its source and builder. It's a real step beyond pinning, but someone still has to define what "trusted" means and enforce that policy for every action.

A curated catalog. Consume actions that have already been vetted for authorship and project membership, rebuilt in a controlled pipeline, and kept up to date by someone else.

That last approach is what Chainguard built with Chainguard Actions, a catalog of more than a thousand hardened GitHub Actions. Each action is confirmed to originate from its genuine upstream project and is built from source, and container actions are rebuilt under control on minimal, hardened images. Every action ships with a hardening report documenting what was fixed, why, and how, covering issues like workflow misconfigurations and runner memory exposure, and actions are re-evaluated as new exploit techniques emerge.

Erika was clear that this adds to pinning rather than replacing it: "Keep your pinning and your org-level pinning policy. Nothing you enforce today goes away." In her demo, the change to an existing Python test workflow was small. She added a permissions block so the job can request an identity token, added chainguard-dev/setup-chainctl to authenticate with Chainguard, then swapped actions/checkout and similar references for their Chainguard Actions equivalents, still pinned to a SHA.

What platform teams should do now?

Asked during the Q&A for her top advice to platform engineers, Erika kept it simple:

  1. Pin everything to a SHA. Don't reference actions by tag; you don't control the maintainers' repositories, and their tags can be redirected to malware. Use Dependabot or a similar bot to keep pins current, and look at what those bumps actually point to.
  2. Shrink the attack surface. Use minimal, hardened container images, and think about the whole path your code takes: not just your code, but everything that builds, executes, and distributes it.

The broader lesson of the talk is to treat provenance as its own requirement. Pinning tells you the bytes won't change. It doesn't tell you whose bytes they are.

To learn more, visit chainguard.dev/actions and Chainguard Academy's guide to getting started with CI/CD pipelines. The full webinar recording and slides are available to everyone who registered, and you can find upcoming Platform Engineering community webinars at platformengineering.org/events.

‍