ghtier
← Action pinning
Action pinningOpen source

pinact

Rewrites uses: references in workflows to full commit SHAs with the version kept as a comment.

github.com/suzuki-shunsuke/pinact ↗
Stars
★ 1,222
License
MIT
Language
Go
Last push
10 Oct 2026
OpenSSF Scorecard
Not in the weekly scan
ghtier ratingRated 4 of 5, Recommended4/5 · Recommended

The simplest way to bulk-pin a repository's actions to SHAs, maintained by a prolific Actions tool author.

How it works

pinact is a Go CLI that finds every uses: line in workflow and action files, resolves the tag or branch to a commit through the GitHub API, and rewrites the line as owner/repo@<sha> # vX.Y.Z. The trailing comment is the format Dependabot and Renovate understand, so they can keep the pins current afterwards.

It can also update pins to the latest release, and a check mode exits non-zero when something is unpinned, so it works as a CI guard.

What it catches

  • Tag and branch references in workflows and composite actions
  • Pins without a version comment
  • Out-of-date pins, when run with update

Run it

brew install suzuki-shunsuke/pinact/pinact
pinact run

What leaves your machine

Calls the GitHub API to resolve tags to SHAs. Set GITHUB_TOKEN to avoid the unauthenticated rate limit.

Limits

  • Only pins the top-level uses: line. Nested actions inside a composite action stay as their author wrote them.
  • Does not check that a SHA is reachable from the real repository; zizmor's impostor-commit audit does.

Links

Related tools

Related incidents

ApplicationMarch 2025

tj-actions/changed-files supply-chain compromise (CVE-2025-30066)

The attacker used a previously obtained GitHub token with write permissions to push a commit disguised as renovate[bot], slipped into a legitimate auto-merged PR, then retroactively repointed multiple version tags at the malicious commit, affecting over 23,000 repositories. The payload dumped runner memory to logs, exposing access keys, PATs, npm tokens, and private RSA keys. Upstream, reviewdog/action-setup (CVE-2025-30154) was backdoored first, and researchers traced the original target to Coinbase's agentkit repo. The permission abused, contents:write on an Action repo, implies tag-write, which implies control of every consumer pinning by tag.

Click to open →
OrganizationMarch – April 2026

TeamPCP tag force-overwrite campaign

The most complete demonstration of tag-write as a permission tier. On 19 March 2026 (CVE-2026-33634), continuing an attack that began in late February, the actors used credentials with tag-write privileges to publish Trivy v0.69.4 and force-overwrite 76 of 77 tags in aquasecurity/trivy-action and all seven in aquasecurity/setup-trivy, redirecting trusted versions to malicious commits with no visible change in release metadata. Checkmarx's KICS GitHub Action followed on 23 March, when all 35 of its tags were moved through a compromised service account, and on 24 March LiteLLM versions 1.82.7 and 1.82.8 were uploaded straight to PyPI with credentials taken from LiteLLM's own CI, where Trivy ran. Researchers traced at least seven waves through to @bitwarden/cli hijacked with stolen KICS npm tokens, and elementary-data via Actions script injection. Each compromised environment yielded the credentials for the next.

Click to open →

GitHub stats as of 10 Oct 2026. How ratings work.