New recipes every week

Turn Complexity Into
Cloud Recipes

Learn Kubernetes, AI, DevOps and DevSecOps the CloudChef way. Practical guides, real-world examples, no fluff.

✓Free forever ✓No paywall ✓Practical guides ✓Real-world examples
50+Guides
WeeklyNew posts
K8s + AITop topics
FreeAlways
CI/CD CloudChef DevSecOps GitHub Actions Security Monday, November 2, 2026 ⏱ Calculating...

Stop Running Code You Never Reviewed: GitHub Actions Workflow Lockfiles Explained

CC
CloudChef
thecloudchef.io
GitHub Actions workflow lockfiles explained: pin every action to an exact commit - CloudChef

Imagine your recipe says "use Brand X flour." You tasted the dish, you approved it, you wrote it down. Then one night somebody swaps what's inside the bag. Same label. Different contents. Your recipe didn't change, but dinner did.

That's a moved tag in a CI pipeline. When your workflow says uses: some/action@v4, v4 is a label, and labels can be re-pointed. In March 2025, the widely reported tj-actions/changed-files compromise worked this way: existing version tags were repointed at malicious code, so pipelines that hadn't changed a single line ran it anyway.

On October 14, 2026, GitHub put a direct answer into public preview: workflow dependency lockfiles. Let's cook with them.

What We Are Cooking Today

  • Understand what a workflow lockfile pins, and what it doesn't
  • Compare tag pinning, SHA pinning and lockfiles
  • Roll lockfiles out one workflow at a time
  • Add a least-privilege baseline using two new September features

How It Works (Facts From GitHub's Changelog)

  • The gh actions-lock extension for the GitHub CLI generates .github/workflows/actions.lock.
  • The file records reviewable commits for your actions, their transitive dependencies, and reusable workflow dependencies.
  • You onboard workflows one at a time. Once a workflow is onboarded, every dependency must have a lockfile entry, and Actions runs the recorded commit even if the tag or branch has moved.
  • The extension can check whether the lockfile is stale without modifying files, including inside a CI check.
  • A Require lockfile policy lets enterprise, org and repo admins enforce this. It's in public preview too.
  • When Dependabot bumps an action in an onboarded workflow, it regenerates the matching lockfile entry in the same pull request.
  • Availability: public preview on Enterprise Cloud, Enterprise Cloud with data residency, Team and Free plans. GitHub Enterprise Server isn't in that list, so check before planning around it.

The catch, straight from GitHub: locking doesn't tell you whether a dependency is safe. If you lock a bad commit, you've locked a bad commit very reliably.

Tag vs SHA vs Lockfile

ApproachReadableCan it move?Covers transitive dependencies?
Tag (@v4)YesYesNo
Full commit SHA (@abc123...)No, it's a wall of hexNoNot by itself. Composite actions can pull in their own dependencies.
LockfileYes, your workflow keeps readable refsNot for locked entriesYes, per GitHub

My take (opinion): SHA pinning was always the right idea with terrible ergonomics. Nobody enjoys reviewing a Dependabot PR full of 40-character hashes. A lockfile keeps the human-friendly ref in the workflow and moves the exact commit into a file built for machines and reviewers. That's the bit I like.

Ingredients

  • A repo on an eligible plan
  • GitHub CLI (gh) installed and authenticated
  • Dependabot enabled for the github-actions ecosystem
  • Admin rights if you want to turn on the Require lockfile policy

Recipe Steps

1. Install the extension

gh extension install github/gh-actions-lock

2. Generate the lockfile for one workflow

Preview tools change flags faster than I change coffee orders, so I'm not going to guess the exact subcommands here. Follow the README in the github/gh-actions-lock repo and GitHub's "workflow dependency lockfiles" docs, and start with a low-risk workflow like your lint job.

3. Review the diff like it matters

Open .github/workflows/actions.lock and look at the commits it records, including the transitive ones. This is the moment to notice an action you didn't know you depended on. Because locking blesses whatever is there, review before you commit.

4. Commit and run the workflow

Commit the lockfile and workflow changes together, open a PR, and confirm the run still goes green.

5. Add the stale check to CI

Use the extension's check mode (see the README for the exact invocation) in a small workflow so a PR that edits a uses: line without updating the lockfile fails fast.

6. Let Dependabot do the boring part

version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

For onboarded workflows, those PRs now carry the refreshed lockfile entry too.

7. Roll out, then enforce

Onboard workflows in batches. Once most of a repo or org is covered, consider the Require lockfile policy so nobody quietly skips it.

Bonus: A Least-Privilege Baseline

Locking controls what code runs. Permissions control what that code can touch. You want both. GitHub's September 2026 updates added two relevant pieces:

  • A vulnerability-alerts permission for GITHUB_TOKEN, with read and none values, so a workflow can read Dependabot alerts without broader scopes.
  • New job context properties for reusable workflows, including job.workflow_ref, so a reusable workflow can know which workflow file defines the current job. These aren't available on GitHub Enterprise Server.
name: ci
on:
  pull_request:

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - run: make test

  alerts-report:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      vulnerability-alerts: read
    steps:
      - run: echo "Running from ${{ job.workflow_ref }}"

When to use it: every workflow, as a default. When not to: jobs that truly need to write (releases, deployments). Grant those permissions at the job level, never at the top.

Chef Tips

  • Start with workflows that have the most third-party actions. That's where your exposure lives.
  • Treat a lockfile change in a PR like a dependency change in application code: someone reads it.
  • Combine this with branch protection on the workflow files themselves. A lockfile doesn't help if anyone can edit the workflow freely.

Kitchen Disasters

SymptomLikely causeFix
Onboarded workflow fails on a new actionEvery dependency of an onboarded workflow must be in the lockfileRegenerate the lockfile and commit it with the workflow change
Stale-lockfile check failsSomeone edited a uses: line by handRegenerate, or let Dependabot's PR do it
Everything is locked, yet you still got burnedYou locked a commit that was already badReview before locking, and keep scanning dependencies
Feature isn't availablePlan not eligible, or you're on GitHub Enterprise ServerFall back to SHA pinning plus Dependabot

Serving Suggestions

  • Run the same exercise for container images in your pipeline: pin by digest, not by tag.
  • Pair this with the DevSecOps posts on this site for scanning and policy gates.

Cleanup and Rollback

Because onboarding is per workflow, the blast radius of a bad rollout is small. If a workflow misbehaves, revert the PR that onboarded it. Remember this is a public preview, so test in a non-critical repo first and expect rough edges.

FAQ

Do lockfiles replace SHA pinning?

For onboarded workflows they give you the same "exact commit" guarantee, plus transitive dependencies, while keeping readable refs in the workflow.

Does a lockfile make an action safe?

No. GitHub says so explicitly. It makes runs consistent with what you reviewed.

Can I use it on GitHub Enterprise Server?

The announcement lists Enterprise Cloud, Team and Free plans. Check GitHub's docs for Enterprise Server status.

Final Thoughts

Most pipeline attacks don't break down the front door. They swap a label on something you already trusted. Lockfiles won't make a bad dependency good, but they'll make sure "the code I reviewed" and "the code that ran" are the same code. That's a low bar, and an awful lot of pipelines still miss it.

References


πŸ”₯ Trending CloudChef Recipes

⭐ Popular CloudChef Recipes

No comments:

Post a Comment

πŸ’‘ Found this useful?

Share it with your Team or DevOps Friends πŸ‘‡