Using a branch name or tag name as a version for a GitHub action is dangerous as neither branches nor tags are immutable. (See GitHub's documentation for more details)
pin-github-actions
is a small command-line tool that replaces ("pins") branches or tag names with their corresponding commit sha.
You can see it in action in this commit:
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -7,9 +7,9 @@ jobs:
runs-on: macos-12
steps:
- - uses: actions/checkout@v3
- - uses: gradle/gradle-build-action@v2.2.1
- - uses: gradle/wrapper-validation-action@v1
+ - uses: actions/checkout@d0651293c4a5a52e711f25b41b05b2212f385d28 #v3
+ - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 #v2.2.1
+ - uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b #v1
- run: ./gradlew build
env:
brew install martinbonnin/repo/pin-github-actions
$ pin-github-actions --update .github
processing [2/2]... docs.yaml
done.
Q: Why pinning the first party actions like actions/checkout@v3
? GitHub runs the actions, so it should be trusted by construction?
A: It's true that GitHub has to be trusted to run the actions. Nevertheless, no one is immune to exploits and in the advent that GitHub gets hacked, pinning the GitHub actions reduces a tiny little bit the attack surface. What's more, it makes the yaml files more consistent.
Q: Can I have a GitHub action that automatically updates the pins?
A: Dependabot and Renovate do this. (albeit with a caveat in the dependabot case)