pin-actions
GitHub Actions referenced by mutable tags (@v4) are vulnerable to supply chain attacks —
a compromised maintainer can silently move the tag to malicious code. Pinning to a commit
SHA makes the reference immutable and tamper-evident.
Script Location
~/.claude/skills/pin-actions/scripts/resolve_action_sha.sh
Interface: ./resolve_action_sha.sh <owner/repo[/path]> <tag> → prints 40-char SHA to stdout
Workflow 1: Scan Mode (pin all unpinned actions in a workflow file)
- Read the workflow file to identify all
uses:lines - Filter to unpinned actions — skip:
- Already-pinned:
uses: owner/repo@<40-char hex SHA> - Docker-based:
uses: docker://... - Local actions:
uses: ./path/to/action
- Already-pinned:
- For each unpinned action, extract
owner/repo[/subpath]andref:- Pattern:
uses: {owner}/{repo}@{ref} - Pattern:
uses: {owner}/{repo}/{path}@{ref}(sub-path actions)
- Pattern:
- Resolve each SHA using the script:
SHA=$(~/.claude/skills/pin-actions/scripts/resolve_action_sha.sh "owner/repo" "v4") - Replace
owner/repo@v4→owner/repo@<SHA> # v4- Always preserve the original tag as a trailing comment for human readability
Example transformation
Before:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: docker/build-push-action/push@v6
After:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: pnpm/action-setup@a3252b7a1b87b11f31ef2a5405c6fe64a35b06b8 # v4
- uses: docker/build-push-action/push@263435318d21b8e681c14492fe198d362a7d2c83 # v6
Workflow 2: Lookup Mode (resolve a single action on demand)
When asked to look up the SHA for a specific action:
~/.claude/skills/pin-actions/scripts/resolve_action_sha.sh "actions/checkout" "v4"
# → 11bd71901bbe5b1630ceea73d27597364c9af683
Report the SHA and the pinned form:
actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
Tag Types
The script handles both GitHub tag types transparently:
- Lightweight tags: point directly to a commit (most common for action releases)
- Annotated tags: contain metadata and point to a tag object, which in turn points to a commit — the script dereferences this automatically
Error Handling
If the script exits with code 1, the tag likely doesn't exist for that repo. Verify:
- Correct owner/repo spelling
- Tag exists:
gh api repos/{owner}/{repo}/git/ref/tags/{tag} - The repo has releases (not all action repos use tags)
微信扫一扫