gha-hashpinner
Finds mutable pins in GitHub Actions config and replaces them with immutable commit SHAs.
This is a security best practice that protects against supply chain attacks.
The immutable hashpins generated by this tool include version comments which are Dependabot-compatible.
⚠️ SHA pinning isn't a perfect solution and GitHub should be ashamed. If someone opens a PR to update a SHA pin, close it and let Dependabot do it instead (or manually verify the SHA is a member of the correct repo).
Example
❌ Mutable pins are a bad practice (you might get pwned!):
jobs:
my-job:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
✅ This tool will convert them to immutable pins:
jobs:
my-job:
steps:
- name: "Checkout"
uses: "actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5" # v4
Install
uv tool install gha-hashpinner
Usage
From a GitHub repository containing GitHub Actions workflows in .github/workflows:
gha-hashpinner .
Or, update a specific workflow file:
gha-hashpinner .github/workflows/my-workflow.yml
GitHub API rate limiting
The GitHub API rate-limits unauthenticated requests to 60/hour.
You may want to provide a token with the --token= argument to avoid rate limits.
This tool only needs read access.
It's very important to minimize access granted to any tool to only what's required. Only use fine-grained personal access tokens (PATs) with no extra permissions. Never click the "Add permissions" button.
In other words, keep everything default. The only thing selected in the fine-grained PAT UI should be "Public repositories (Read-only access to public repositories)". If you need to run this tool against private repositories, select "All repositories" or "Only select repositories".
With GitHub Actions
TODO
With pre-commit / prek
TODO
Alternatives
- https://github.com/azat-io/actions-up: NPM package
- https://github.com/Skipants/update-action-pins: Go package
Why?
I deeply distrust the NPM ecosystem. The Go package above is not user-friendly to install.
I wanted something I could install with uv tool install.
LLMs plus a dash of review and engineering judgement make it fast and easy to build tools like this.
Limitations
- Does not update your actions -- only pins them immutably to the same version they're already pinned to. I recommend using Dependabot (with a cooldown) to upgrade your actions after pinning with this tool.
- This tool detects mutable refs with regex, i.e. a 40-character hexadecimal string is considered to be an immutable ref. There's no way to be sure without making API calls. See the relevant issue (#13) for details.
- When not given an explicit file path, only checks workflow files in
.github/workflows.
Metadata
Release files for gha-hashpinner 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gha_hashpinner-0.0.3.tar.gz | 63.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gha_hashpinner-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.1 kB
Release files / gha_hashpinner-0.0.3.tar.gz
| Download URL | gha_hashpinner-0.0.3.tar.gz |
|---|---|
| Size | 63.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d41e7b5cefdaa0665508af58eb900d397f27c1449f2f621b53cc4e6d3e7949ec
|
|
BLAKE2b-256 checksum How to use checksums |
4fa61d387293146b1ce3a03f5fa155b0d227e4a4aad68e2d89ea9c6a61f2372d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.
Transparency logRelease files / gha_hashpinner-0.0.3-py3-none-any.whl
| Download URL | gha_hashpinner-0.0.3-py3-none-any.whl |
|---|---|
| Size | 15.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
17fc5570dd76e1f5e376147f7fbc6d0d668bdb8d67c74b469f91d8151dd96d7b
|
|
BLAKE2b-256 checksum How to use checksums |
9a61a4a412cf2bfaf8c970b9c2d0b061dd00f4f463b692439b297301a2aa9e32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.
Transparency log