📰 AI NewsAgileIntermediate✨ AI-assisted

GitHub Actions Lockfiles Pin Workflow Dependencies by Commit

WittyTech Daily··5 min read
#github-actions#supply-chain#lockfiles#dependabot

GitHub put GitHub Actions lockfiles into public preview today. A new file, .github/workflows/actions.lock, records the exact commit behind every action, transitive dependency and reusable workflow your pipelines call, so a moved tag can no longer change what runs. This piece covers what shipped, what it does not do, and how to onboard a repo this week.

What GitHub Actions lockfiles record

Tags and branches move. If someone compromises an action and repoints v4, your next run executes new code, and nothing changed in your repo. That is the attack shape behind the March 2025 tj-actions/changed-files incident, where version tags were moved to a malicious commit.

Per GitHub's announcement, the lockfile ties runs to the commits you reviewed. The gh actions-lock GitHub CLI extension generates it, and you should never edit it by hand. A workflows section lists what each onboarded workflow uses. A dependencies section maps each reference to its ref, commit, owner_id and repo_id. At run time, Actions uses the two IDs to confirm the repository behind a name is still the one you locked.

This is an abridged sketch based on the lockfile docs. The real file has more entries, so check the docs for the full layout.

# This file is machine-generated by `gh actions-lock`.
version: 'v0.0.2'
workflows:
  '.github/workflows/ci.yml':
    - 'octo-org/deploy-action@v3.1.0'
dependencies:
  'octo-org/deploy-action@v3.1.0':
    ref: 'v3.1.0'
    commit: 'sha1-...'
    owner_id: 44036562
    repo_id: 197814629

The side benefit: the docs say repos that adopt a lockfile no longer need SHA pinning in the workflow files. Your YAML keeps readable versions and the lockfile holds the hashes.

Why this matters if you ship AI

Your deploy pipelines hold registry pushes, cloud roles and model API keys. A build step that silently changes is a direct path to all of them.

Locking is not vetting, though. It does not judge whether a dependency is safe. It only guarantees that the code you reviewed is the code that runs.

Onboard one workflow with gh actions-lock

Start with a single workflow. Passing a path onboards just that file, and running with no arguments scans every workflow under .github/workflows/. The docs recommend enabling Dependabot before you create the lockfile.

gh extension install github/gh-actions-lock
gh actions-lock .github/workflows/ci.yml
git diff

The extension also rewrites references, for example octo-org/deploy-action@v3 becomes @v3.1.0, and local uses: ./ references become uses: $/. Read the whole diff, then commit the lockfile and the workflow changes together. A changed commit is code that will run, so review it like a dependency bump. A changed owner_id or repo_id should be rare, so investigate before merging.

When a tag legitimately moves, re-resolve it:

gh actions-lock --relock
# Only if the locked commit is unreachable upstream, and you have investigated why:
gh actions-lock --relock --accept-moved

Verify the lockfile in CI

gh actions-lock --verify checks the lockfile without writing anything and exits with an error if it is stale. Run it on pull requests and make it a required check. This is a minimal sketch. The docs don't state token requirements for --verify, so the GH_TOKEN wiring is my assumption. GitHub's enforcement guide points to the gh-actions-lock repo for fuller versions.

name: actions-lock
on:
  pull_request:
    paths:
      - '.github/workflows/**'
permissions:
  contents: read
jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Install the extension
        run: gh extension install github/gh-actions-lock
        env:
          GH_TOKEN: ${{ github.token }}
      - name: Fail if actions.lock is stale
        run: gh actions-lock --verify
        env:
          GH_TOKEN: ${{ github.token }}

Onboard this workflow too, since it has dependencies of its own. For a fast local check, gh actions-lock --verify-local --no-fix works offline as a pre-commit hook. It only confirms every reference has an entry and does not re-verify pins against GitHub.

Keep it current with Dependabot, enforce it with Require lockfile

For onboarded workflows, a Dependabot action update now regenerates the matching lockfile entry in the same pull request. Dependabot never onboards a workflow, so it maintains coverage without extending it.

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly

Then add a code owner so lockfile changes get a human:

# .github/CODEOWNERS
.github/workflows/actions.lock  @<your-org>/<platform-team>

The Require lockfile policy, also in preview, blocks runs of targeted workflows that have action dependencies but are not onboarded. It can be set at enterprise, organization or repository level. Pilot it in Evaluate mode (GitHub Enterprise only) and read Policy insights. Switch to Active once the targeted repos and workflows are onboarded. The enforcement guide is explicit that the policy blocks runs but does not keep lockfiles fresh, so keep the CI check.

Gotchas

  • It is a public preview and subject to change, on Enterprise Cloud (including data residency), Team and Free plans.
  • Allowlists: tag entries like actions/checkout@v6 no longer match locked SHAs. Use a wildcard or the full commit SHA.
  • A reusable workflow is locked by the lockfile in the repo where it is defined, so onboard shared workflow repos first.
  • Branch and partial version references like main or v3 are not re-resolved on a normal run. Use --relock.
  • The lockfile covers only workflows in its own repository.

What to do on Monday morning

  1. Enable Dependabot for the github-actions ecosystem.
  2. Onboard your least scary workflow and review the full diff.
  3. Add the --verify check and a CODEOWNERS line.
  4. Turn on Require lockfile in Evaluate mode and read the insights before going Active.

Your AI pipelines hold the keys to your models and data, so knowing exactly which commits execute inside them is a production requirement.

← More in Agile