GitHub Actions freezes third-party actions to reviewed commits
On 14 October 2026, GitHub opened workflow lockfiles to public preview: every action and reusable workflow is pinned to a specific commit, so the code you reviewed is the code that runs. Turn on locking for your critical repositories before a moved tag slips malicious code into your CI.
14 October 2026. GitHub opens workflow lockfiles for GitHub Actions in public preview. March 2025. The tj-actions/changed-files attack moves a tag to a poisoned commit and drains the CI secrets of thousands of repositories. 14 October 2026, again. The feature covers GitHub Enterprise Cloud, Team, and Free. Why it matters: a workflow that references actions/checkout@v4 does not run a version number — it runs whatever sits behind a mutable pointer, and almost nobody watches that pointer.
The hole: a tag that moves after review
The implicit security model of GitHub Actions rests on a fragile assumption. When you write uses: some-org/action@v1, you are trusting a tag or a branch. But a tag is not an artifact — it is a label its owner can move at any time, with no notice to your repository. The code review you did on the v1.2.0 commit protects nothing if, the following night, the maintainer — or an attacker who took over the account — reassigns v1 to a commit containing a secret stealer.
That is exactly what happened in the tj-actions/changed-files incident of March 2025. The action, used by tens of thousands of repositories, had its tags redirected to a malicious commit that exfiltrated CI tokens and environment secrets. The lesson was not that one action had a bug — it is that tag-based trust is structurally bypassable, and the manual fix, pinning every action to a commit SHA, is tedious, unreadable, and quickly abandoned. GitHub puts it plainly in the announcement: a tag or branch can move after your review, “so a later run might execute different code.”
The tj-actions case was not isolated. In December 2024, the ultralytics/actions repository suffered the same kind of hijack: a compromised PyPI token was used to publish a poisoned release of the action, and the tags were reassigned to match. Every time, the official advice was identical — pin to SHAs — and every time, most repositories did not do it. The problem is not a lack of advice; it is the absence of a tool that makes pinning sustainable over time. That is exactly what the lockfile provides.
The answer: a lockfile that pins commits
Workflow lockfiles bring package-manager logic to CI. Where package-lock.json and Cargo.lock freeze an application’s dependencies, the new .github/workflows/actions.lock freezes a workflow’s dependencies. Each action, its transitive dependencies, and any reusable workflows are recorded with their exact commit. The workflow keeps its readable reference (@v4), but GitHub Actions runs the locked commit — not the tag, not the branch.
Generation goes through a dedicated CLI extension, gh actions-lock, installed from the public gh-actions-lock repository. It works in three moves:
- Pin. The extension generates
actions.lockwith reviewable commits for each action, its transitive dependencies, and reusable workflows. - Adopt gradually. Onboarding is per workflow. Once a workflow is onboarded, each of its dependencies must have a lockfile entry, and GitHub Actions runs the recorded commit.
- Check for staleness. A command verifies the lockfile is current without touching files — ideal as a CI step that refuses to merge a desynchronized workflow.
Gradual adoption is the mechanism’s real strength. A team can lock its deployment workflow today, then extend coverage to the rest without ever breaking the estate. No all-or-nothing migration: the lockfile lands repository by repository, workflow by workflow.
Enforcing locking at scale
An opt-in feature only protects the teams that turn it on. GitHub knows this, and ships the Require lockfile policy in the same preview. Enterprise, organization, or repository administrators can require workflows to use a lockfile — and block any pull request that omits one. That is the switch that turns an individual best practice into governance policy.
The loop closes with Dependabot. When the bot opens a version update for an action in an already-locked workflow, it regenerates the lockfile entry in the same pull request. The updated workflow and its locked commit stay in sync with zero extra configuration. Without that integration, the lockfile would become a graveyard of stale commits nobody dares touch; with it, updating stays a single reviewed action.
This locking joins a string of platform supply-chain hardening moves: purpose-built secret detection, blocking Anthropic keys by default, pull-request scanning. The lockfile is not an isolated gadget — it is the missing piece in the “who runs what” chain of CI.
Setup in three commands
The base flow fits in a few lines: install the extension, generate the lockfile, then commit it.
gh extension install github/gh-actions-lock
gh actions-lock generate
git add .github/workflows/actions.lock Once generated, every workflow dependency is frozen to its commit. To catch a lockfile that has drifted — typically in a CI step that blocks the merge — the same extension offers a check mode:
- name: Verify lockfile
run: gh actions-lock check That check is the piece most teams forget. An unwatched lockfile turns into a padlock on an already-open door: it offers the illusion of security without stopping a tag from drifting silently.
What the lockfile does not do
The promise needs bounding, and GitHub does it itself: “locking does not determine whether the dependency itself is safe.” The lockfile guarantees immutability — you run the code you reviewed — not safety. Lock a compromised action and you freeze the harm in place. Dependency review therefore stays a prerequisite: you read an action before you lock it, not after.
The second limit is operational. A lockfile adds a maintenance step to every action upgrade. Without Dependabot or a staleness check in CI, teams end up pinning old commits that accumulate vulnerabilities — the mirror image of the first problem. Locking only pays off when it is paired with a regular update process.
Teams already pinning actions to raw SHAs get the easiest migration: gh actions-lock generate reads the existing references and emits the lockfile, and from there Dependabot can take over. The payoff is readability — a diff that moves actions/checkout@v4 from one commit to another is far easier to review than a wall of hashes — plus the enforcement policy, which a hand-maintained SHA convention can never give you. The lockfile does not ask you to abandon tags; it asks you to stop trusting them alone.
Verdict
If your repositories use third-party actions in sensitive workflows — deployment, release, secret access — install gh actions-lock this week and lock those workflows first. If you administer an organization, enable the Require lockfile policy on critical repositories and let Dependabot keep entries current. If your estate already pins actions to SHAs, migrate them to the lockfile: you gain the readability of tags and the immutability of commits, without the manual burden. The lockfile does not replace dependency review; it only guarantees that once you review, nothing moves. In a CI where a moved tag can empty a secret vault overnight, that guarantee is easily worth the maintenance step it adds.