1 Installation
Choose the installation method that best fits your environment.
Shell (macOS & Linux)
curl -LsSf https://raw.githubusercontent.com/ffalcinelli/pinner/main/install.sh | sh
PowerShell (Windows)
powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/ffalcinelli/pinner/main/install.ps1 | iex"
Cargo (Rust)
cargo install pinner
2 Pin Your First Workflow
Navigate to your repository and run the pin command.
By default, Pinner looks for files in .github/workflows/.
$ pinner pin
Searching for workflows in .github/workflows/...
Found 2 workflow files.
actions/checkout@v4 -> actions/checkout@8f4b7f84... # v4
Successfully pinned 3 actions! ✅
Tip: Use --dry-run to see changes without writing to files.
3 Security Scan & Vetting
Audit your dependencies for vulnerabilities. Pinner queries the OpenSSF OSV database for both current pinned hashes and proposed upgrade candidates. It also executes Sigstore/Cosign signature/provenance verification on container images.
Run the scan command to inspect your dependencies:
$ pinner scan
Scanning dependencies with OSV database...
✔ Clean Dependencies:
actions/checkout@8f4b7f84... (Upgrade candidate: df4cb1c0... # v6.0.3)
alpine@sha256:12345... (Upgrade candidate: sha256:67890...)
Select clean dependencies to add to the vetted whitelist in .pinner.toml: [actions/checkout@8f4b7f84..., actions/checkout@df4cb1c0...]
This adds vetted hashes to your whitelist in .pinner.toml. When proposing upgrades or pinning, Pinner displays visual feedback (e.g. [✓ vetted]) to ensure supply-chain integrity.
4 Supported Platforms & Forges
Pinner is designed for multi-forge environments and enterprise setups.
| Forge / Registry | API Environment Variable | Default URL |
|---|---|---|
| GitHub | GITHUB_TOKEN |
https://api.github.com |
| GitLab | GITLAB_TOKEN |
https://gitlab.com |
| Bitbucket | BITBUCKET_TOKEN |
https://api.bitbucket.org/2.0 |
| Forgejo/Gitea | FORGEJO_TOKEN |
https://codeberg.org |
| Azure DevOps | GITHUB_TOKEN |
Monorepo Mapping |
| AWS ECR | PINNER_OCI_PASSWORD |
Private Registries |
| CircleCI | CIRCLECI_TOKEN |
Docker Image Pinning |
5 Configuration File
Create a .pinner.toml file in your repository root to customize behavior globally and share with your team.
# Actions to exclude from processing
ignore = ["actions/checkout", "my-org/private-repo"]
# Concurrency and Caching settings
concurrency = 5
no_cache = false
cache_ttl = 7200 # Persistent caching duration in seconds (2h)
# API URL overrides (for Enterprise instances)
github_url = "https://github.mycompany.com/api/v3"
gitlab_url = "https://gitlab.mycompany.com/api/v4"
# Whitelist of vetted dependency references (compact inline array)
vetted = [
"actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332",
{ ref = "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10", tag = "v6.0.3", timestamp = "2026-06-18T15:28:25Z" }
]
6 Verify in CI
Prevent unpinned actions from being merged into your codebase by adding Pinner to your CI pipeline. You can enable vulnerability checks using check-osv and require explicit vetting with strict mode:
name: Pinning Check
on: [pull_request]
jobs:
verify-pinning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v4
- name: Verify Pinning & Audit OSV
uses: ffalcinelli/pinner/action@main
with:
command: 'verify'
check-osv: true
strict: true
Pinnerception Warning Recursive
Remember to pin the pinner! Trusting a security tool to verify your pinned dependencies using a mutable tag is like hiring a security guard who leaves the keys under the doormat. If we didn't pin the pinner, who would pin the pinner's pinners?
Alternatively, you can install the CLI tool directly:
name: Pinning Check
on: [pull_request]
jobs:
verify-pinning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v4
- name: Install Pinner
run: curl -LsSf https://raw.githubusercontent.com/ffalcinelli/pinner/main/install.sh | sh
- name: Verify Pinning
run: pinner verify --check-osv --strict
7 Shell Completion
Generate tab-completion scripts. If you omit the shell argument, Pinner will attempt to detect your current shell automatically:
Auto-Detection
pinner generate-completion > ~/.pinner_completion
Bash (Explicit)
pinner generate-completion bash > /etc/bash_completion.d/pinner
Zsh (Explicit)
pinner generate-completion zsh > "${fpath[1]}/_pinner"
Next Steps
-
Learn about Upgrades: Use
pinner upgradeto move to newer versions.Security Note: Automatic upgrades can undermine security. Use
upgradeas an intentional step followed by a manual check of changes. - API Reference: Check out the Rust API documentation for library usage details.