A command-line tool for pinning GitHub Actions to specific commit hashes to improve security and ensure reproducible builds.
- Action Pinning: Converts version tags (e.g.,
v3,v4) to commit hashes - Batch File Processing: Process multiple repositories from a file list
- Organization Processing: Process entire organizations or individual repositories
- Local Repository Support: Pin actions in local repositories
- Fork Synchronization: Automatically syncs forks with upstream before processing
- Automated PR Creation: Creates pull requests with pinned actions
- No-PR Mode: Skip PR creation and only fix repositories locally for review
- Custom Output Directory: Specify where to save repositories in no-PR mode
- Enhanced Duplicate Prevention: Detects existing PRs to avoid duplicates
- PR Template Support: Automatically detects and fills out repository PR templates
- Fork Support: Automatically forks repositories when write access is not available
- Performance Optimized: Uses GitHub API for faster resolution and caches action repositories
- Security Focused: Prevents supply chain attacks through immutable references
- Comment Preservation: Shows original version and date for auditing
- Account Switching: Switch between different GitHub accounts
- Concurrent Processing: Processes multiple actions simultaneously for better performance
- Flexible URL Parsing: Supports various GitHub URL formats (HTTPS, SSH, owner/repo)
- Go 1.21 or later
- Git installed and configured
- GitHub authentication via one of:
ghCLI (default mode)- Personal Access Token in
GITHUB_TOKENorGH_TOKEN(PAT mode)
go install github.com/harekrishnarai/gha-pinner/cmd/gha-pinner@latestThis will install the gha-pinner binary to your $GOPATH/bin directory (typically ~/go/bin). Make sure this directory is in your PATH.
git clone https://github.com/harekrishnarai/gha-pinner
cd gha-pinner
go build -o gha-pinner ./cmd/gha-pinner# Pin actions in a local repository
gha-pinner local-repository <path> [--debug] [--ignore-templates] [--no-pr] [--output <dir>]
# Pin actions in a remote repository
gha-pinner repository <repo-name> [--debug] [--ignore-templates] [--no-pr] [--output <dir>] [--auth-mode <gh|pat>] [--repo-workers <n>]
# Pin actions in all repositories of an organization
gha-pinner organization <org-name> [--debug] [--ignore-templates] [--no-pr] [--output <dir>] [--auth-mode <gh|pat>] [--repo-workers <n>]
# Process multiple repositories from a file
gha-pinner file <path-to-repos-file> [--debug] [--ignore-templates] [--no-pr] [--output <dir>] [--auth-mode <gh|pat>] [--repo-workers <n>]
# Resolve a specific action version to commit hash
gha-pinner action <action-name> <version> [--debug]
# Switch between GitHub accounts
gha-pinner switch-account <username> [--debug]--debug: Enable debug output with timing information--ignore-templates: Ignore PR templates and use full PR body instead of filling templates--no-pr: Skip PR creation, only fix repositories locally for manual review--output <dir>: Custom output directory for repositories (only with --no-pr)--auth-mode <gh|pat>: Select authentication mode (ghdefault, or PAT without gh CLI)--repo-workers <n>: Number of repositories to process in parallel fororganizationandfilecommands (default: 4)
# Process local repository
gha-pinner local-repository ./my-repo
# Process remote repository
gha-pinner repository owner/repo-name
# Process entire organization
gha-pinner organization my-org
# Process organization at scale with PAT auth and 12 workers
export GITHUB_TOKEN=ghp_xxx
gha-pinner organization my-org --auth-mode pat --repo-workers 12
# Process multiple repositories from a file
gha-pinner file repos.txt
# Process repositories but skip PR creation (for manual review)
gha-pinner file repos.txt --no-pr
# Process with custom output directory
gha-pinner file repos.txt --no-pr --output ./fixed-repos
# Resolve specific action version
gha-pinner action actions/checkout v3
# Switch GitHub account
gha-pinner switch-account myusername
# Enable debug output
gha-pinner repository owner/repo-name --debug
# Ignore PR templates and use full description
gha-pinner repository owner/repo-name --ignore-templatesWhen using the file command, create a text file with one repository URL per line:
# Security-focused repositories
https://github.com/slsa-framework/slsa
https://github.com/ossf/scorecard
https://github.com/sigstore/cosign
owner/repository-name
The tool supports various URL formats:
https://github.com/owner/repohttps://github.com/owner/repo.gitgit@github.com:owner/repo.gitowner/repo(simple format)
Comments (lines starting with #) and empty lines are ignored.
- Discovery: Scans
.github/workflows/*.ymlfiles for GitHub Actions - Resolution: Resolves version tags to specific commit hashes
- Replacement: Replaces version tags with commit hashes while preserving original version in comments
- Validation: Ensures all changes maintain workflow functionality
Before:
- name: Checkout code
uses: actions/checkout@v3After:
- name: Checkout code
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 on 2025-06-27- Permission Check: Verifies write access, forks repository if needed
- Fork Synchronization: If using a fork, syncs with upstream to ensure latest code
- Clone: Clones the target repository (or fork) to a temporary directory
- Patch: Processes all workflow files to pin actions concurrently
- Branch: Creates a new branch with timestamp for uniqueness
- Commit: Commits changes with natural-sounding commit message
- Push: Pushes branch to origin (or fork)
- Duplicate Detection: Checks for existing PRs to avoid duplicates
- PR Template Detection: Detects and fills out repository PR templates
- PR: Creates pull request with filled template or custom description
When using the file command for batch processing:
- File Parsing: Reads repository URLs from the file, skipping comments and empty lines
- URL Normalization: Converts various GitHub URL formats to standard
owner/repoformat - Sequential Processing: Processes repositories one by one with progress reporting
- Error Isolation: Continues processing other repositories if one fails
- Summary Report: Provides success/failure statistics at the end
When using --no-pr flag:
- Local Processing: Performs all repository operations without creating PRs
- Change Preview: Shows a diff of all changes made to workflow files
- Repository Preservation: Keeps repositories in temp directory (or custom output) for manual review
- Manual Instructions: Provides commands for manual commit and push operations
This mode is perfect for:
- Testing changes before creating PRs
- Reviewing multiple repositories at once
- Custom workflow scenarios
- Compliance requirements
The tool automatically detects PR templates in repositories and intelligently fills them out:
- Template Detection: Searches for common PR template files (
.github/pull_request_template.md, etc.) - Smart Filling: Fills out description, testing, and security sections with relevant information
- Checkbox Handling: Automatically checks relevant boxes (security improvement, code review, etc.)
- Professional Output: Creates PRs that look manually crafted rather than automated
Use --ignore-templates to bypass template detection and use the full custom PR body instead.
- Immutable References: Commit hashes cannot be changed, preventing malicious updates
- Reproducible Builds: Ensures the exact same action version across all runs
- Audit Trail: Clear tracking of which specific version is being used with dates
- Follows GitHub's recommended security practices
- Maintains backward compatibility
- Preserves original version information for reference
- Natural commit messages and PR descriptions to avoid detection as automated tools
- GitHub API First: Attempts to resolve versions via API before cloning repositories
- Action Repository Caching: Caches cloned action repositories for faster subsequent runs
- Shallow Clones: Uses minimal git history for faster cloning
- Concurrent Processing: Processes multiple actions within workflows simultaneously
- Persistent Cache: Maintains cache between runs for repeated operations
Enable --debug flag to see detailed timing information:
- Individual action resolution times
- API vs clone resolution methods
- Cache hits and misses
- Total execution time
--debug: Enable detailed debug output with timing information--ignore-templates: Skip PR template detection and use full custom PR body--no-pr: Skip PR creation and only fix repositories locally for manual review--output <dir>: Custom output directory for repositories (only effective with --no-pr)
DEBUG: Enable debug output (alternative to--debugflag)GITHUB_TOKENorGH_TOKEN: Required when--auth-mode patis used
Use either mode:
--auth-mode gh(default): Requires GitHub CLI authentication--auth-mode pat: Uses direct GitHub REST API + git over HTTPS with your token, no gh CLI required
For gh mode:
# Install GitHub CLI
# See: https://cli.github.com/
# Authenticate with GitHub (ensure you have repo and workflow scopes)
gh auth login
# Check authentication status
gh auth status
# Switch between accounts if needed
gha-pinner switch-account usernameFor PAT mode:
export GITHUB_TOKEN=ghp_xxx
gha-pinner organization my-org --auth-mode patImportant: Make sure your GitHub token has the following scopes:
repo: Full control of repositories (required for forking and creating PRs)workflow: Update GitHub Action workflowsread:org: Read organization and team membership (for organization processing)
Create a repos.txt file with repositories you want to process:
# SLSA and Supply Chain Security
https://github.com/slsa-framework/slsa
https://github.com/ossf/scorecard
https://github.com/in-toto/in-toto
# Sigstore Ecosystem
https://github.com/sigstore/cosign
https://github.com/sigstore/fulcio
https://github.com/sigstore/rekor
# Vulnerability Scanning
https://github.com/anchore/grype
https://github.com/aquasecurity/trivy
https://github.com/google/osv-scanner
The included repos.txt contains 50 curated security-focused repositories for testing.
For processing multiple repositories efficiently:
# 1. Review the repository list
cat repos.txt
# 2. Test with no-PR mode first
gha-pinner file repos.txt --no-pr --debug
# 3. Review changes in preserved repositories
ls -la /tmp/repos/
# 4. When satisfied, run with PR creation
gha-pinner file repos.txt --debug# Process with custom output for compliance review
gha-pinner file security-repos.txt --no-pr --output ./compliance-review
# Process organization with no-PR for testing
gha-pinner organization my-org --no-pr --debug
# Process single repository without PR for manual testing
gha-pinner repository critical-app/main --no-pr
# Process and ignore PR templates for consistent formatting
gha-pinner file repos.txt --ignore-templates# In CI environment, use no-PR mode and commit to branch
gha-pinner file repos.txt --no-pr --output ./pinned-repos
cd pinned-repos/my-repo
git add .
git commit -m "security: pin GitHub Actions to commit hashes"
git push origin security-pinning-branch# Generate detailed logs for security auditing
gha-pinner file repos.txt --debug > security-pinning-report.log 2>&1
# Process with progress tracking
gha-pinner file repos.txt --debug | tee security-improvements.logAction repositories are cached in:
- Linux/macOS:
/tmp/gha-pinner-cache/actions/ - Windows:
%TEMP%\gha-pinner-cache\actions\
gha-pinner/
├── cmd/
│ └── gha-pinner/
│ ├── main.go # Main application logic
│ ├── main_test.go # Unit tests
│ └── pr-body.md # Template PR body
├── go.mod # Go module definition
├── go.sum # Go dependencies
└── README.md # This file
The application follows a modular design with clear separation of concerns:
- Command Processing: Handles CLI argument parsing and command routing
- Repository Operations: Manages git operations and GitHub API interactions
- Workflow Processing: Parses and modifies YAML workflow files
- Action Resolution: Resolves version tags to commit hashes
- Error Handling: Comprehensive error handling with cleanup
go test ./cmd/gha-pinner -v# Build for current platform
go build -o gha-pinner ./cmd/gha-pinner
# Build for multiple platforms
GOOS=linux GOARCH=amd64 go build -o gha-pinner-linux ./cmd/gha-pinner
GOOS=windows GOARCH=amd64 go build -o gha-pinner-windows.exe ./cmd/gha-pinner
GOOS=darwin GOARCH=amd64 go build -o gha-pinner-macos ./cmd/gha-pinnerThe tool includes comprehensive error handling:
- Graceful Degradation: Continues processing other repositories on individual failures
- Fork Synchronization: Automatically syncs forks with upstream to prevent outdated PRs
- Duplicate Prevention: Detects existing PRs to avoid creating duplicates
- Authentication Handling: Provides clear error messages for token permission issues
- Cleanup: Removes temporary directories on exit (except in --no-pr mode)
- Detailed Logging: Debug mode shows full execution traces
- Recovery: Handles common failure scenarios (network issues, authentication, etc.)
- Progress Reporting: Shows real-time progress for batch operations
403 Forbidden Errors:
- Ensure your GitHub token has proper scopes (
repo,workflow) - Re-authenticate with
gh auth loginif using environment tokens
Fork Permission Issues:
- Tool automatically handles forking when you don't have write access
- Syncs forks with upstream to ensure latest code
Duplicate PRs:
- Tool checks for existing PRs before creating new ones
- Enhanced detection includes PRs from forks to upstream repositories
- Requires GitHub authentication (
ghmode or PAT mode) - Only processes public repositories or those accessible with current authentication
- Some semantic versions may not be resolvable to specific commits
- Rate limiting may apply for large organizations
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For issues, questions, or contributions, please:
- Check existing issues on GitHub
- Create a new issue with detailed information
- Include debug output when reporting problems
- New: Batch file processing with
filecommand for multiple repositories - New: Fork synchronization to prevent duplicate PRs and ensure latest code
- New:
--no-prflag for local processing without PR creation - New:
--outputflag for custom output directories in no-PR mode - New: Enhanced duplicate PR prevention with fork detection
- New: Support for various GitHub URL formats (HTTPS, SSH, owner/repo)
- New: Comprehensive progress reporting for batch operations
- New: Change preview in no-PR mode with diff output
- Improved: Better error handling and authentication guidance
- Improved: Enhanced repository preservation for manual review
- Added: Sample
repos.txtwith 50 security-focused repositories
- Initial release
- Support for local repository processing
- Support for remote repository processing
- Support for organization-wide processing
- Action version resolution
- Automated PR creation
- Comprehensive error handling