Newshot
Account

Lock your GitHub Actions

Original text(via Lobsters)

GitHub Actions now supports workflow lockfiles.

Because GitHub Actions are fetched from Git, the previous advice was to pin to a full SHA instead of a tag. This is because tags are mutable and susceptible to supply-chain attacks where an attacker points a previously safe tag at malicious code.

For example, an old workflow looks like:


        name: Lint

on: [push, pull_request, workflow_dispatch]

permissions: {}

env:
  FORCE_COLOR: 1
  RUFF_OUTPUT_FORMAT: github

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: j178/prek-action@44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d # v3.1.0
      

Here’s how I set up lockfiles.

Install

Install the gh-actions-lock extension to the gh CLI:


        $ gh extension install github/gh-actions-lock
✓ Installed extension github/gh-actions-lock
      

Lock ’em

In your repo, run:


        $ gh actions-lock

✓ All 1 workflows valid
      

The workflow now uses vX.Y.Z tags and looks like this:


        diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 946971c..3503607 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,7 +13,7 @@ jobs:
     runs-on: ubuntu-latest

     steps:
-      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+      - uses: actions/[email protected]
         with:
           persist-credentials: false
-      - uses: j178/prek-action@44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d # v3.1.0
+      - uses: j178/[email protected]
      

And it generates a lockfile at .github/workflows/actions.lock:


        # This file is machine-generated by `gh actions-lock`.
# Do not edit by hand; run `gh actions-lock` to update.
# Docs: https://gh.io/actions-lockfile
version: 'v0.0.3'
workflows:
    '.github/workflows/lint.yml':
        - 'actions/[email protected]'
        - 'j178/[email protected]'
dependencies:
    'actions/[email protected]':
        ref: 'v7.0.1'
        commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1'
        owner_id: 44036562
        repo_id: 197814629
    'j178/[email protected]':
        ref: 'v3.1.0'
        commit: 'sha1-44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d'
        owner_id: 10510431
        repo_id: 1052387486
      

Commit modified workflows and the new lockfile.

Renovate and Dependabot

Good news, both already support lockfiles! Your periodic updates will also update the lockfile. Remember to use cooldowns.

Validate

GitHub also recommends verifying lockfiles in CI to ensure it’s up-to-date and not corrupt.

They suggest copying this verify-lockfile.yml into your repo. I decided to put it into my existing lint workflow, but in its own job so it runs independently and in parallel:


        name: Lint

on: [push, pull_request, workflow_dispatch]

permissions: {}

env:
  FORCE_COLOR: 1
  RUFF_OUTPUT_FORMAT: github

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/[email protected]
        with:
          persist-credentials: false
      - uses: j178/[email protected]

  # Fails when .github/workflows/actions.lock is out of sync with the
  # workflows or a locked pin no longer verifies upstream.
  lockfile:
    runs-on: ubuntu-slim
    env:
      GH_TOKEN: ${{ github.token }}

    steps:
      - uses: actions/[email protected]
        with:
          persist-credentials: false
      - run: gh extension install github/gh-actions-lock --pin v0.4.1
      - run: gh actions-lock --verify
      

Note I’m using the lightweight ubuntu-slim runner here. Also, it’s pinning to v0.4.1; we’ll have to update that at some point or figure out a way to automate it. That’s for another time.

Don’t forget that we just modified the actions in a workflow, so need to relock with gh actions-lock. Nothing actually changes if adding to lint.yml because it’s already locking actions/checkout. But if you created a new file like verify-lockfile.yml, you’ll need to relock for that. The CI will let you know.

zizmor

zizmor is a security linter for GitHub Actions and strongly recommended. If you don’t use it, please do.

Versions before v1.32.0 tell you to hash-pin actions, and v1.32.0 is the first to support lockfiles.

I use zizmor in prek, so add/update zizmor in .pre-commit-config.yaml:


        - repo: https://github.com/zizmorcore/zizmor-pre-commit
    rev: v1.32.0
    hooks:
      - id: zizmor
      

Locked!

OK, commit and push!

Examples

  • python-pillow/Pillow#10428
  • python/release-tools#477
  • python/miss-islington#758
  • python/cpython#161811

Header photo: Slaymaker Barry Co. Sprocket Locks in The Bearings (vol. XII no. 23, 2nd January 1896) in the Smithsonian Libraries and Archives, with no known copyright restrictions.

The text above was extracted automatically from the source page and may miss images, tables or code blocks. The original is authoritative.

Published by Lobsters
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗