Security & supply chain

GitHub Actions lockfiles pin the commit and leave your tags alone

GitHub Actions lockfiles pin the commit and leave your tags alone

You reviewed the action. You approved the pull request. Then someone moved the tag, and your next run executed code nobody on your team has ever read. (Tags are sticky notes. Nobody ever promised they were signatures.) GitHub's answer is workflow dependency lockfiles, now in public preview. You keep @v1 in your YAML, and the run uses the commit you actually reviewed.

What shipped

The preview covers GitHub Enterprise Cloud, Enterprise Cloud with data residency, Team and Free. GitHub Enterprise Server is not on that list.

The work happens in a GitHub CLI extension, gh actions-lock. It generates .github/workflows/actions.lock, which records reviewable commits for each action, for that action's transitive dependencies, and for reusable workflow dependencies. You onboard workflows one at a time. Once a workflow is onboarded, every one of its dependencies must have a lockfile entry, and Actions runs the recorded commit even if the tag or branch has since moved. The extension can also check whether the lockfile is stale without modifying anything, and GitHub says that check can run in CI.

Two pieces sit around it. A Require lockfile policy, also in preview, lets enterprise, organization and repository administrators make lockfiles mandatory within their scope. Dependabot, when it opens a version update for an action in an onboarded workflow, regenerates the matching lockfile entry in the same pull request.

Couldn't I just SHA-pin everything?

You could. Plenty of us do. But anyone who has maintained it knows what it costs: 40 characters of hex on every uses: line, a # v1 comment that quietly drifts out of sync with the SHA, and diffs nobody reads. Worse, your pin covers one edge of the graph. A composite action you pinned by SHA can still call another action by a floating tag, and you never see that line because it lives in someone else's repository.

The lockfile closes both gaps. The readable reference stays in the workflow, the commit moves into a file you can diff, and the transitive dependencies get locked too. Same trick package-lock.json and go.sum pulled years ago, finally applied to the layer of the stack that holds your deploy credentials.

Rolling it out

Install the extension from the public github/gh-actions-lock repository:

gh extension install github/gh-actions-lock

Then generate the lockfile, review it, and commit it together with the workflow changes the tool produces. Start with the workflows that hold secrets or deploy permissions. Add the stale-lockfile check to CI so a drifted lockfile fails a pull request. Turn on Require lockfile only after the important workflows are onboarded, unless you enjoy a red Monday. The exact subcommands are in GitHub's workflow dependency lockfiles documentation, and I am not going to guess them for you.

What a lockfile will not do

GitHub says this plainly in the changelog: locking "does not determine whether the dependency itself is safe, so review dependencies before locking them." Lock a backdoored commit and you get a backdoored workflow that runs exactly the same way every time. Reproducible. Still compromised.

The Dependabot integration deserves the same suspicion. When a bot PR updates both the reference and the locked commit, that PR becomes your trust boundary. Rubber-stamp it and you have automated the tag move with extra steps.

Then there is scope. The changelog describes locking commits for actions, their transitive dependencies and reusable workflows. It says nothing about container images or binaries an action downloads at runtime, so assume those are still yours to pin by digest ($REGISTRY/image@sha256:<digest>). And until the policy is on, any workflow you have not onboarded still floats.

How other CI systems handle the same problem

Every CI system has this problem. Here is how pinning looks in three of them.

  • GitLab CI/CD lets you pin include: references and CI/CD components to a commit SHA. That is pinning per reference: you write each SHA yourself, one line at a time.
  • CircleCI orbs are referenced by version. A full semantic version points at a published release, while a major-only reference such as @1 picks up newer releases automatically.
  • Jenkins shared libraries load via @Library('name@ref'), where the ref can be a branch, a tag or a commit. Same model: safe if you choose a commit, floating if you choose a branch.

What GitHub adds is transitive coverage and an admin policy to enforce it, at least on paper. It is still a preview, built with community contributors that GitHub credits by name, including Andrew Nesbitt and William Woodruff, so expect rough edges.

Verdict

Adopt it, starting with your most privileged workflows, and wire up the stale check on day one. This is the pinning model Actions should have shipped with: readable references, locked commits, transitive coverage. Just don't confuse a lockfile with a review. It records what you decided to trust. It has no opinion on whether you were right.

Source: GitHub Changelog (github.blog)

Related
Security & supply chain

GTIG's agentic threat report is a CI/CD problem, not just an AI problem

Google's Threat Intelligence Group documents DUSTMAKER, an OIDC-stealing supply-chain payload from UNC6780 that ships valid SLSA Build 3 attestations. The moment a signed provenance line stops being a defence is the moment CI/CD owners have to rethink runner trust.

September 10, 2026
Security & supply chain

The workstation is in scope now

A DevOps.com essay argues the laptop that pushes commits belongs inside the supply-chain threat model, citing the Megalodon campaign that injected malicious GitHub Actions workflows into thousands of repositories and a separate malicious VS Code extension incident. What CI-side controls actually catch this, and where the pipeline runs out of leverage.

July 19, 2026
Security & supply chain

A devops.com walkthrough stacks four open-source security gates into GitHub Actions

devops.com published a build-it-yourself piece that stitches npm audit, Snyk, Trivy, CodeQL and OWASP ZAP into a single GitHub Actions pipeline. It is a decent map of what teams can gate on without an enterprise SKU, but stacking five scanners has an operational cost the article does not spend on.

August 16, 2026

Turn this into your pipeline. Build it on Buddy.

Start free