Last weekend, the popular GitHub Action tj-actions/changed-files was compromised.
- https://semgrep.dev/blog/2025/popular-github-action-tj-actionschanged-files-is-compromised/
- https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
The issue was solved, but similar incidents could happen again in the future.
To prevent such issues, pinning action versions by full commit hash is recommended.
👉 GitHub Docs:
Pin actions to a full length commit SHA
Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release.
Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.
When selecting a SHA, you should verify it is from the action's repository and not a repository fork.
This post introduces how to pin GitHub Action versions across all repositories in your organization.
pinact
You can pin GitHub Actions using a CLI tool called pinact.
It's so easy to use:
pinact run
If you want to fix composite actions and documents, you can specify file paths.
pinact run action.yaml README.md
You can also update actions using the -u
option:
pinact run -u
For more details, check out the pinact repository.
multi-gitter
You can apply pinact to all repositories using multi-gitter.
Create the following files:
config.yaml
run.sh
main.sh
config.yaml:
e.g.
git-type: cmd
branch: pin-github-actions
skip-forks: true
org:
- szksh-lab # Update with your organization
# repo:
# - szksh-lab/test-1 # For test
labels:
- pin-github-actions
pr-title: "ci: Pin versions of GitHub Actions to full commit hash"
pr-body: |
## What?
This PR pins versions of GitHub Actions to full commit hash by pinact.
In general, this PR doesn't change the behavior of the workflows, so you can merge this safely.
## Why?
Last weekend, the popular GitHub Action tj-actions/changed-files action was compromised.
- https://semgrep.dev/blog/2025/popular-github-action-tj-actionschanged-files-is-compromised/
- https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
All tags were tampered and they pointed to a revision with malicious code.
The issue was solved, but similar issues could happen again.
To avoid this kind of issues, we should pin versions of GitHub Actions.
This is a common practice of GitHub Actions.
https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-third-party-actions
> Pin actions to a full length commit SHA
> Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release.
> Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.
> When selecting a SHA, you should verify it is from the action's repository and not a repository fork.
## How was this pull request created?
This pull request was created by [pinact](https://github.com/suzuki-shunsuke/pinact) and [multi-gitter](https://github.com/lindell/multi-gitter).
## Due Date
Please merge this pull request by 2025-03-31.
If it's difficult, please ask at the Slack channel #sre.
## Contact
If you have any question, please ask at the Slack channel #sre.
run.sh:
#!/usr/bin/env bash
set -eu
export GITHUB_TOKEN=$(gh auth token)
multi-gitter run ./main.sh \
--config config.yaml
main.sh:
#!/usr/bin/env bash
set -eu
pinact run
Make main.sh executable:
chmod +x main.sh
Before running it across all repositories, test it on one repository:
config.yaml:
# org:
# - szksh-lab
repo:
- szksh-lab/test-1 # Please fix
Run run.sh
to create a pull request:
bash run.sh
Once confirmed, apply it to all repositories.
bash run.sh
Example Pull Request: https://github.com/szksh-lab/test-1/pull/23
For more details of multi-gitter, please see the multi-gitter repository.
Continuous Updates
You can update actions by Dependabot or Renovate.
Dependabot:
Renovate:
You can also run pinact in CI using pinact-action.
Conclusion
To improve security, you should pin GitHub Action versions to a full-length commit hash.
You can pin GitHub Actions across all repositories in your GitHub Organizations using pinact and multi-gitter.