Pinner ๐งช
A high-performance Rust CLI utility to hash-pin GitHub Actions in your workflow files. Secure your CI/CD supply chain by converting volatile, mutable tags (like @v2) into immutable, cryptographic commit SHAs (like @df4cb1c...).
Why Pin? ๐
Using mutable tags like @v2 or @main in GitHub Actions introduces a security risk. If an attacker gains access to an action's repository, they can move the tag to a malicious commit, leading to a supply chain attack on your infrastructure.
Hash-pinning ensures that you run the exact code you've audited, every single time. Pinner automates this process while keeping your workflows readable by appending the original tag as a comment.
Features โจ
- Surgical Replacement: Uses
tree-sitterfor precise YAML parsing, preserving comments, indentation, and formatting perfectly. - Tag Preservation: Automatically appends the original tag as a comment (e.g.,
@<hash> # v2). - GitHub API Integration: Fetches the correct commit SHA for any tag or branch.
- Enterprise Support: Works with GitHub Enterprise via custom API URLs.
- Flexible Upgrades: Multiple strategies to keep your actions up to date (Major, Minor, Latest).
- CI Ready: Includes a
verifymode to ensure all actions remain pinned in your PRs.
Installation ๐ ๏ธ
One-line installation (Recommended)
macOS/Linux:
|
Windows:
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/ffalcinelli/pinner/main/install.ps1 | iex"
From source
Usage ๐
1. Pin all actions
Scans .github/workflows/ and converts all tags to pinned hashes.
Input: - uses: actions/checkout@v3
Output: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3
2. Upgrade to latest
Update pinned actions to their latest versions based on a strategy.
# Default: Upgrade to latest available release
# Upgrade only within the current major version (e.g., v2.1.0 -> v2.4.5)
# Upgrade to the latest commit on the default branch
3. Verify pinning
Ensure that all actions in your workflows are pinned. Perfect for CI pipelines.
4. Set a specific action
Forcibly updates a specific action across all workflows.
5. Generate Shell Completions
Generate autocompletion scripts for your favorite shell.
Configuration โ๏ธ
Pinner can be configured via a .pinner.toml file in your repository root.
# List of actions to ignore during pinning/upgrading
= ["my-org/private-action"]
# Number of concurrent GitHub API requests (default: 10)
= 5
# Custom GitHub API URL (for GitHub Enterprise)
= "https://github.mycompany.com/api/v3"
Global Flags ๐ฉ
-w, --workflows <PATH>: Files or directories to process (default:.github/workflows/).-y, --yes: Automatically confirm all replacements.--dry-run: Show diff without modifying files.--json: Output results in JSON format.--token <TOKEN>: GitHub API token (can also be set viaGITHUB_TOKENenv).--github-url <URL>: Custom GitHub API URL (for GHE).-q, --quiet: Suppress all console output.-v, --verbose: Print verbose output.
Rate Limiting & Authentication ๐
To avoid GitHub API rate limits, provide a token:
CI/CD Integration ๐ค
Add this to your workflow to ensure all actions stay pinned:
jobs:
verify-pinning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Pinner
run: curl -LsSf https://raw.githubusercontent.com/ffalcinelli/pinner/main/install.sh | sh
- name: Verify Pinning
run: pinner verify
Name Origin โ๏ธ
The name Pinner is inspired by the Pinner reaction in organic chemistry. Discovered by Adolf Pinner, this reaction involves the acid-catalyzed conversion of a reactive nitrile into a highly stable Pinner salt.
Just as the Pinner reaction transforms a volatile compound into a stable, fixed salt, this CLI transforms "floating" action tags into secure, immutable, and fixed commit SHAs.
License ๐
MIT License. See LICENSE for details.