DEV Community

Nicolás
Nicolás

Posted on

GitHub Actions: Why You Should Pin Your Actions to a Specific Version

GitHub is, without a doubt, the most popular version control platform on the planet. Millions of developers, companies, and institutions use it daily to collaborate and store their code.

But GitHub is not just “a place to store code.” It also offers GitHub Actions (GHA), a powerful tool that lets you build workflows simply by writing YAML files.

Thanks to this, you can automatically run tests, compile projects, or even deploy applications whenever something happens in your repo, like a push or a pull request.

These workflows run in environments called runners (Linux, Windows, or macOS) and rely on predefined actions or custom ones you create yourself.

Example

Let’s imagine we have a simple Python script called hello.py that just prints Hello!

If we want to run it using a GHA, we’d have a workflow like this:

name: Run Hello Script

on:
  workflow_dispatch:

jobs:
  run-hello:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@latest

      - name: Set up Python
        uses: actions/setup-python@latest
        with:
          python-version: '3.x'

      - name: Run hello.py
        run: python hello.py
Enter fullscreen mode Exit fullscreen mode

This workflow uses only workflow_dispatch, so our hello.py script will only run when we manually trigger the workflow through GitHub.

If you look closely, we’re using the checkout and setup-python actions with the latest tag. This tells the workflow to always use the most recent version of those actions.

Using latest ensures you’re always working with the newest version but it also brings two major risks related to stability and security.

⚙️ Stability

A new version might introduce breaking changes that make your workflow fail overnight.

🔒 Security

If an action gets compromised and malicious code is added to some versions, your workflow would execute it without any visible warning.

✅ The Solution

The good news is these issues are easy to fix: just pin your actions to a specific version that you’ve already tested and validated with your code.

Pinning Actions

There are three main ways to pin an action to a specific version:

Use a general version tag

uses: actions/checkout@v3

Use a more precise version tag

uses: actions/checkout@v3.5.2

Use a commit SHA

uses: actions/checkout@9e4...f2c3

The most secure and stable option is the third one, since a SHA always points to a specific, immutable commit in the repository.

It’s good practice to combine the SHA with a comment indicating which version the SHA corresponds to:

uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0

That way, you and your team know which version that SHA refers to, while keeping your workflow safe from unexpected changes.

How to Find the Commit SHA

Using checkout v3.6.0 as an example:

  • Go to the official repo and open the Releases section.

  • Find version 3.6.0 and click on the commit link.

  • The commit hash will appear clearly in the URL.

Making sure your actions are pinned to a specific version is easy as long as you only have a few.

For organizations with thousands of repositories and hundreds of actions, it’s a bit more complex.

Mainly because, until recently, there was no way to enforce SHA pinning across all repositories in an organization.

In other words, each team decided whether to do it or not, and there were no native mechanisms to block the use of latest or tags like v2.

Well… that was until now.

🧩 SHA Pinning Policy in GitHub

A couple of weeks ago, GitHub released an update that lets organizations apply two key new policies:

  • Block specific actions
  • Enforce pinning actions to a commit SHA

🔐 SHA Pinning

Thanks to the new update, organizations can now enable a policy that disables any actions not pinned to a commit SHA.

This policy can be set at both the organization level (affecting all repos) or at the individual repository level.

Once enabled, any action not properly pinned to a SHA will automatically throw an error.

🚫 Blocking Specific Actions or Versions

The update also adds the ability to block specific actions and/or versions by adding a special ! prefix to the action identifier and version you want to block.

This prevents any repository within the organization from running that action—even if it’s pinned to a SHA.

This feature is especially useful when a vulnerability is found in a specific version of an action and you want to make sure none of your repositories can use it.

🧭 In Summary

GitHub Actions is an incredibly powerful tool, but like any tool, its security depends on how you use it.

Pinning your actions to specific versions and applying centralized control policies are key steps to keeping your workflows stable, secure, and predictable.

💬 Are you already applying these practices in your repos?
If not, now’s a great time to start.

Top comments (0)