Pinning GitHub Actions and using ratchet

In the continuous missing to stay secure, I have earlier written about pinning your GitHub Actions in TIL posts: TIL: Pin Your Action Dependencies and TIL: How do I resolve the SHA checksums?. This is a good practice and with Dependabot helping you out, it makes it easier once you have the initial pinning done. For one of the projects I maintain, I got a PR and they stuck to the same good practice, but the comments was prefixed with the word "ratchet", which I had not seen before, so I had to do some research. Ratchet ratchet is a small tool to help you with your pinning. You can read more about it here: GitHub - sethvargo/ratchet Once installed you can quickly get an overview of it's capabilities by running: ratchet --help Usage: ratchet COMMAND lint Lint and report unpinned versions pin Resolve and pin all versions unpin Revert pinned versions to their unpinned values update Update all pinned versions to the latest value upgrade Upgrade all pinned versions to the latest version Available parsers: actions circleci cloudbuild drone gitlabci tekton So if we jump into one of our directories using GitHub Actions without pinning (at the time of writing): cd ~/develop/github-jonasbn/perl-test-timer/.github/workflows We can run: ratchet lint *.yml This will give us a report of all the unpinned versions, which in this case are: markdownlint.yml:10:13: Unpinned reference "nosborn/github-action-markdown-cli@v3.5.0" markdownlint.yml:9:13: Unpinned reference "actions/checkout@master" spellcheck.yml:9:13: Unpinned reference "actions/checkout@master" spellcheck.yml:10:13: Unpinned reference "rojopolis/spellcheck-github-actions@0.51.0" Next up we can run: ratchet pin *.yml And we then ask Git what has changed: git --no-pager diff --no-color diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml index 7952daa..e39bc96 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/markdownlint.yml @@ -6,9 +6,9 @@ jobs: name: Markdownlint runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - uses: nosborn/github-action-markdown-cli@v3.5.0 - name: Markdownlint - with: - files: . - config_file: ".markdownlint.json" + - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # ratchet:actions/checkout@master + - uses: nosborn/github-action-markdown-cli@508d6cefd8f0cc99eab5d2d4685b1d5f470042c1 # ratchet:nosborn/github-action-markdown-cli@v3.5.0 + name: Markdownlint + with: + files: . + config_file: ".markdownlint.json" diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index e8f5da0..b6b9e5c 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -6,6 +6,6 @@ jobs: name: Spellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - uses: rojopolis/spellcheck-github-actions@0.51.0 - name: Spellcheck + - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # ratchet:actions/checkout@master + - uses: rojopolis/spellcheck-github-actions@35a02bae020e6999c5c37fabaf447f2eb8822ca7 # ratchet:rojopolis/spellcheck-github-actions@0.51.0 + name: Spellcheck As you can read the line: uses: nosborn/github-action-markdown-cli@v3.5.0 Has been replaced with: uses: nosborn/github-action-markdown-cli@508d6cefd8f0cc99eab5d2d4685b1d5f470042c1 # ratchet:nosborn/github-action-markdown-cli@v3.5.0 So we have now pinned the action to a specific commit, which is best practice, as it will not change unless we change it and dependabot can even handle that. Let us check if the commit pinned is actually the same as the tag previously used. Open your browser and navigate to the nosborn/github-action-markdown-cli or any other relevant repository for the action in question. Click the "Releases" tab and find the tag you are interested in, in this case v3.5.0. Then click the commit hash link, which will take you to the commit page, where you can verify the commit hash matches the one ratchet has pinned. Maintaining the pinned versions is more secure, but it also requires some more work, dependabot gets you a long way and ratchet can also help you out. Using ratchet you could look into: update Update all pinned versions to the latest value upgrade Upgrade all pinned versions to the latest version And of course if this does not work you can always unpin. ratchet unpin *.yml And you should be back where you started, you might however need to checkout via Git since ratchet might change some white space, nothing big and ratchet it is not version control. If you want to follow best practices, the tooling is there you just need to make the decision and go for it. If you know of other tools or practices I should evaluate do let me know

Jun 24, 2025 - 19:30
 0
Pinning GitHub Actions and using ratchet

In the continuous missing to stay secure, I have earlier written about pinning your GitHub Actions in TIL posts: TIL: Pin Your Action Dependencies and TIL: How do I resolve the SHA checksums?.

This is a good practice and with Dependabot helping you out, it makes it easier once you have the initial pinning done.

For one of the projects I maintain, I got a PR and they stuck to the same good practice, but the comments was prefixed with the word "ratchet", which I had not seen before, so I had to do some research.

Ratchet

ratchet is a small tool to help you with your pinning.

You can read more about it here:

Once installed you can quickly get an overview of it's capabilities by running:

ratchet --help
Usage: ratchet COMMAND

  lint       Lint and report unpinned versions
  pin        Resolve and pin all versions
  unpin      Revert pinned versions to their unpinned values
  update     Update all pinned versions to the latest value
  upgrade    Upgrade all pinned versions to the latest version

Available parsers:

  actions
  circleci
  cloudbuild
  drone
  gitlabci
  tekton

So if we jump into one of our directories using GitHub Actions without pinning (at the time of writing):

cd ~/develop/github-jonasbn/perl-test-timer/.github/workflows

We can run:

ratchet lint *.yml

This will give us a report of all the unpinned versions, which in this case are:

markdownlint.yml:10:13: Unpinned reference "nosborn/github-action-markdown-cli@v3.5.0"
markdownlint.yml:9:13: Unpinned reference "actions/checkout@master"
spellcheck.yml:9:13: Unpinned reference "actions/checkout@master"
spellcheck.yml:10:13: Unpinned reference "rojopolis/spellcheck-github-actions@0.51.0"

Next up we can run:

ratchet pin *.yml

And we then ask Git what has changed:

 git --no-pager diff --no-color
diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml
index 7952daa..e39bc96 100644
--- a/.github/workflows/markdownlint.yml
+++ b/.github/workflows/markdownlint.yml
@@ -6,9 +6,9 @@ jobs:
     name: Markdownlint
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@master
-    - uses: nosborn/github-action-markdown-cli@v3.5.0
-      name: Markdownlint
-      with:
-        files: .
-        config_file: ".markdownlint.json"
+      - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # ratchet:actions/checkout@master
+      - uses: nosborn/github-action-markdown-cli@508d6cefd8f0cc99eab5d2d4685b1d5f470042c1 # ratchet:nosborn/github-action-markdown-cli@v3.5.0
+        name: Markdownlint
+        with:
+          files: .
+          config_file: ".markdownlint.json"
diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml
index e8f5da0..b6b9e5c 100644
--- a/.github/workflows/spellcheck.yml
+++ b/.github/workflows/spellcheck.yml
@@ -6,6 +6,6 @@ jobs:
     name: Spellcheck
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@master
-    - uses: rojopolis/spellcheck-github-actions@0.51.0
-      name: Spellcheck
+      - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # ratchet:actions/checkout@master
+      - uses: rojopolis/spellcheck-github-actions@35a02bae020e6999c5c37fabaf447f2eb8822ca7 # ratchet:rojopolis/spellcheck-github-actions@0.51.0
+        name: Spellcheck

As you can read the line:

uses: nosborn/github-action-markdown-cli@v3.5.0

Has been replaced with:

uses: nosborn/github-action-markdown-cli@508d6cefd8f0cc99eab5d2d4685b1d5f470042c1 # ratchet:nosborn/github-action-markdown-cli@v3.5.0

So we have now pinned the action to a specific commit, which is best practice, as it will not change unless we change it and dependabot can even handle that.

Let us check if the commit pinned is actually the same as the tag previously used.

Open your browser and navigate to the nosborn/github-action-markdown-cli or any other relevant repository for the action in question.

repository screenshot

Click the "Releases" tab and find the tag you are interested in, in this case v3.5.0.

Then click the commit hash link, which will take you to the commit page, where you can verify the commit hash matches the one ratchet has pinned.

release screenshot

Maintaining the pinned versions is more secure, but it also requires some more work, dependabot gets you a long way and ratchet can also help you out.

Using ratchet you could look into:

update     Update all pinned versions to the latest value
upgrade    Upgrade all pinned versions to the latest version

And of course if this does not work you can always unpin.

ratchet unpin *.yml

And you should be back where you started, you might however need to checkout via Git since ratchet might change some white space, nothing big and ratchet it is not version control.

If you want to follow best practices, the tooling is there you just need to make the decision and go for it. If you know of other tools or practices I should evaluate do let me know in the comments in below.