
Security News
CVE Volume Surges Past 48,000 in 2025 as WordPress Plugin Ecosystem Drives Growth
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.
gh-actions-lockfile
Advanced tools
Generate and verify lockfiles for GitHub Actions dependencies. Pins all actions (including transitive dependencies) to the exact commit SHAs with integrity hashes.
GitHub Actions has no native lockfile mechanism. Version tags like @v4 can be silently retagged, and composite actions pull in transitive dependencies you can't see. This tool fixes that.
See "GitHub Actions Has a Package Manager, and It Might Be the Worst" for more information.
Run an action in generate mode to create your lockfile:
name: Generate Lockfile
on: workflow_dispatch
jobs:
generate:
runs-on: ubuntu-latest
permissions:
# Gives the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- uses: actions/checkout@v6
- uses: gjtorikian/gh-actions-lockfile@v1
with:
mode: generate
- name: Commit lockfile
# Commit the changed lockfile back to the repository
uses: stefanzweifel/git-auto-commit-action@v7
# or, something like
# run: |
# git add .github/actions.lock.json
# git commit -m "Add actions lockfile"
# git push
Or, locally with the CLI:
npx gh-actions-lockfile generate
git add .github/actions.lock.json
git commit -m "Add actions lockfile"
You really only need to generate this initial lockfile once, so choose whichever version makes the most sense.
Add verification to your CI workflow. If verification fails, the lockfile is automatically regenerated and committed to the PR:
name: Verify Actions
# change this to whichever events matter to you
on: [pull_request]
permissions:
pull-requests: write
jobs:
verify-actions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: gjtorikian/gh-actions-lockfile@v1
with:
mode: verify
update-lockfile:
needs: verify-actions
if: failure()
runs-on: ubuntu-latest
permissions:
# Gives the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.head_ref }}
- uses: gjtorikian/gh-actions-lockfile@v1
with:
mode: generate
- uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: "Update actions lockfile"
file_pattern: ".github/actions.lock.json"
When you update an action version (e.g., actions/checkout@v4 to @v5), or if the action ref changes outside of your control, the verify job will fail, triggering the update job to regenerate and commit the lockfile to your PR automatically.
If you prefer to update the lockfile locally instead of auto-committing via GitHub Actions, you can:
npx gh-actions-lockfile generate
If verify fails, but you didn't change any actions, investigate:
For unexpected changes, review the upstream action's commit history before regenerating the lockfile.
When you run verify, the tool checks that all locked action refs still resolve to the same commit SHAs. This detects if an upstream maintainer has re-pointed a tag to a different commit (a supply chain concern known as "tag hijacking").
To skip SHA verification, use --skip-sha:
gh-actions-lockfile verify --skip-sha
The verify command also:
integrity hash in your lockfileIf any hash mismatches, verification fails. This detects if an action's content has been modified after your lockfile was generated—even if the commit SHA hasn't changed.
To skip integrity checking (e.g., for faster CI runs), use --skip-integrity:
gh-actions-lockfile verify --skip-integrity
By default, the verify command checks your locked actions against the GitHub Advisory Database for known vulnerabilities.
When vulnerabilities are found, they are reported as failures:
Checking security advisories...
actions/cache@v3
GHSA-xxxx-yyyy-zzzz (HIGH)
Cache poisoning vulnerability in versions < 3.2.0
https://github.com/advisories/GHSA-xxxx-yyyy-zzzz
Found 1 action(s) with known vulnerabilities
To disable advisory checking:
gh-actions-lockfile verify --skip-advisories
For maximum security, you can enforce that all action references in your workflows use full 40-character commit SHAs instead of tags or branches:
gh-actions-lockfile generate --require-sha
This fails if any workflow uses a tag like @v4 instead of a full SHA like @b4ffde65f46336ab88eb53be808477a3936bae11.
Add this action to your workflow to verify the lockfile:
- uses: gjtorikian/gh-actions-lockfile@v1
with:
mode: verify # or 'generate'
Action inputs:
| Input | Description | Default |
|---|---|---|
mode | Mode to run in: generate or verify | verify |
token | GitHub token for API access | ${{ github.token }} |
workflows | Path to workflows directory | .github/workflows |
output | Path to lockfile | .github/actions.lock.json |
comment | Post a PR comment when verification fails (verify mode only) | true |
require-sha | Require all action refs to be full SHAs (generate mode only) | false |
skip-sha | Skip SHA resolution verification (verify mode only) | false |
skip-integrity | Skip integrity hash verification (verify mode only) | false |
skip-advisories | Skip security advisory checking (verify mode only) | false |
When comment is enabled and verification fails in a pull request, the action posts a comment detailing what changed.
Install globally via npm:
npm install -g gh-actions-lockfile
Then run:
# Generate a lockfile from your workflows
gh-actions-lockfile generate
# Verify workflows match the lockfile (exits 1 on mismatch)
gh-actions-lockfile verify
# Show dependency tree
gh-actions-lockfile list
Or use npx without installing:
npx gh-actions-lockfile generate
[!WARNING] When running locally, set a
GITHUB_TOKENenvironment variable to avoid rate limits. Without it, you're limited to 60 API requests per hour. A personal access token with no special scopes is sufficient for public repositories.export GITHUB_TOKEN=ghp_your_token_here
generateGenerates (or updates) the lockfile. You'll always want to do this first.
verifyVerifies that the lockfile hasn't changed.
listVisualizes the actions dependency structure, like:
actions.lock.json (generated 2025-12-15 21:57:33)
+-- actions/checkout@v6 (8e8c483db84b)
+-- gjtorikian/actions/setup-languages@main (923ecf42f98c)
| +-- ruby/setup-ruby@v1 (ac793fdd38cc)
| +-- actions/setup-node@v4 (49933ea5288c)
| +-- denoland/setup-deno@v1 (11b63cf76cfc)
| +-- dtolnay/rust-toolchain@master (0b1efabc08b6)
| +-- Swatinem/rust-cache@v2 (779680da715d)
+-- actions/cache@v4 (0057852bfaa8)
+-- actions/configure-pages@v4 (1f0c5cde4bc7)
+-- actions/upload-pages-artifact@v3 (56afc609e742)
| +-- actions/upload-artifact@v4 (ea165f8d65b6)
+-- actions/deploy-pages@v4 (d6db90164ac5)
+-- googleapis/release-please-action@v4 (16a9c90856f4)
Global options (available on all commands):
| Option | Description | Default |
|---|---|---|
-w, --workflows <path> | Path to workflows directory | .github/workflows |
-o, --output <path> | Path to lockfile | .github/actions.lock.json |
-t, --token <token> | GitHub token (or use GITHUB_TOKEN env var) | - |
generate options:
| Option | Description | Default |
|---|---|---|
--require-sha | Require all action refs to be full SHAs | false |
verify options:
| Option | Description | Default |
|---|---|---|
-c, --comment | Post PR comment on verification failure | true |
--skip-sha | Skip SHA resolution verification | false |
--skip-integrity | Skip integrity hash verification | false |
--skip-advisories | Skip security advisory checking | false |
Use --no-comment to disable PR comments when running in CI.
{
"version": 1,
"generated": "2025-12-15T20:37:39.422Z",
"actions": {
"actions/checkout": [
{
"version": "v4",
// This is the Git commit SHA (the 40-character hex hash).
// It identifies the exact commit in the action's repository that will be checked out.
// It answers: "which version of the code should I fetch?"
"sha": "11bd71901bbe5b1630ceea73d27597364c9af683",
// This is a Subresource Integrity (SRI) hash of the action's content (using SHA-256).
// It answers: "is the content I fetched what I expected?"
"integrity": "sha256-abc123...",
// This tracks transitive dependencies — other GitHub Actions that a composite action uses internally.
"dependencies": []
}
]
}
}
Requires Node.js 24+ for building:
# Clone and install
git clone https://github.com/gjtorikian/gh-actions-lockfile.git
cd gh-actions-lockfile
# Install dependencies
npm install
# Run in development
npm start generate
# Build for distribution
npm run build
# Type check
npm run typecheck
# Run tests
npm test
FAQs
Generate and verify lockfiles for GitHub Actions dependencies
We found that gh-actions-lockfile demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.

Security News
Socket CEO Feross Aboukhadijeh joins Insecure Agents to discuss CVE remediation and why supply chain attacks require a different security approach.

Security News
Tailwind Labs laid off 75% of its engineering team after revenue dropped 80%, as LLMs redirect traffic away from documentation where developers discover paid products.