GitHub Actions workflow lockfiles bring package-manager-style dependency pinning to CI/CD pipelines. Instead of trusting mutable tags like v1 or main, workflows now lock actions to specific commit SHAs. This creates an immutable execution graph that prevents compromised action updates from poisoning every dependent workflow.
The feature entered public preview in October 2026 for Enterprise Cloud, Team, and Free plans. It addresses a critical attack vector: if an action maintainer's credentials are stolen or a tag is force-pushed, every workflow using that action immediately runs the malicious code. Lockfiles break that transitive trust chain.
The Problem with Mutable References
Most GitHub Actions workflows reference dependencies by tag:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v5
Tags are Git references that can move. If v4 points to commit abc123 today and def456 tomorrow, your workflow executes different code without any change to your repository. Semantic versioning helps with accidental breakage, but it does nothing against intentional compromise.
The attack surface is broad:
- Maintainer account takeover
- Force-pushed tags after code review
- Compromised release automation
- Transitive dependencies in composite actions
Dependabot can pin actions to full SHAs in workflow files, but that creates a different problem: every SHA update requires a pull request and manual review. Lockfiles separate the pinning mechanism from the workflow definition.
How Workflow Lockfiles Work
A lockfile lives at .github/workflows/actions.lock and maps each action reference to a commit SHA:
{
"actions/checkout@v4": {
"resolved": "a1b2c3d4e5f6...",
"integrity": "sha256-..."
},
"docker/build-push-action@v5": {
"resolved": "f6e5d4c3b2a1...",
"integrity": "sha256-..."
}
}
When a workflow runs, GitHub Actions reads the lockfile and executes the recorded commits, ignoring any tag movements. The workflow file still uses human-readable tags, but the runtime uses immutable SHAs.
The gh actions-lock CLI extension manages the lockfile:
# Generate lockfile for all workflows
gh actions-lock generate
# Update a single action
gh actions-lock update actions/checkout
# Verify lockfile matches workflow definitions
gh actions-lock verify
Workflows onboard individually. Once a workflow is locked, GitHub Actions requires lockfile entries for all its dependencies. Missing entries cause the workflow to fail.
Transitive Dependencies and Composite Actions
Composite actions can call other actions. If my-org/deploy-action@v1 internally uses actions/checkout@v4 and aws-actions/configure-aws-credentials@v2, the lockfile must pin all three.
The generate command walks the dependency graph:
- Parse workflow YAML for
uses:statements - Fetch each action's
action.yml - Recursively resolve composite action dependencies
- Record commit SHAs for the entire tree
Reusable workflows (workflows that call other workflows) are also locked. The lockfile pins both the reusable workflow's commit and any actions it uses.
This creates a complete dependency graph. If any transitive dependency is compromised, the lockfile prevents execution until you explicitly update and review the change.
Failure Modes and Cache Behavior
Lockfiles do not create local caches. If a pinned commit is deleted or force-pushed, the workflow fails. GitHub Actions fetches actions from the repository at runtime, so a missing SHA is a hard error.
This is intentional. A deleted commit signals either repository corruption or an attempt to hide malicious code. Failing loudly is safer than falling back to a mutable reference.
If an action repository is deleted entirely, workflows fail until you remove the dependency or point to a fork. There is no automatic fallback.
Lockfile Policy Enforcement
The "Require lockfile" policy lets administrators mandate lockfiles at the enterprise, organization, or repository level. When enabled:
- Workflows without lockfiles fail
- Workflows with stale lockfiles (missing entries for new actions) fail
- Manual workflow runs cannot bypass the requirement
This creates a security boundary. Developers cannot opt out by removing the lockfile or skipping gh actions-lock verify in CI.
Policy enforcement works at the workflow level, not the repository level. You can onboard high-risk workflows (those with write permissions or access to secrets) first, then expand coverage.
Comparison with Other Pinning Strategies
| Approach | Immutability | Review Overhead | Transitive Deps | Policy Enforcement |
|---|---|---|---|---|
Mutable tags (@v4) |
None | Low | Implicit | No |
| SHA pinning in YAML | Full | High (PR per update) | Manual | No |
| Dependabot SHA pins | Full | Medium (automated PRs) | Manual | No |
| Workflow lockfiles | Full | Low (batch updates) | Automatic | Yes |
Lockfiles reduce review overhead by batching updates. Instead of 10 pull requests for 10 action updates, you get one lockfile update with a diff showing all changes.
Integration with Dependabot
Dependabot can update lockfiles automatically. When a new action version is released, Dependabot:
- Runs
gh actions-lock update <action> - Commits the updated lockfile
- Opens a pull request with the SHA diff
You review the lockfile change, not the workflow YAML. The workflow file stays readable with semantic tags, while the lockfile enforces immutability.
Dependabot respects lockfile policies. If a workflow is locked, Dependabot will not propose updates that bypass the lockfile.
Observability and Audit Trail
Lockfile changes are Git commits, so you get a full audit trail. Each update shows:
- Which action was updated
- Old and new commit SHAs
- Who approved the change
- When the change was deployed
This is critical for incident response. If a compromised action reaches production, you can trace which workflows were affected and when they started using the malicious commit.
GitHub Actions logs include the resolved SHA for each action, so you can correlate runtime behavior with lockfile state.
Deployment Shape
Lockfiles are repository-scoped. Each repository maintains its own .github/workflows/actions.lock. There is no centralized lockfile for an organization or enterprise.
This matches the trust boundary: each repository controls its own execution graph. Shared actions (like organization-wide deployment scripts) are pinned per-repository, so a compromise in one repository does not cascade.
For monorepos with multiple workflow directories, you can maintain separate lockfiles per directory by running gh actions-lock generate --workflow-dir <path>.
Security Boundaries
Lockfiles protect against:
- Tag hijacking (attacker moves
v1to malicious commit) - Maintainer account compromise (attacker pushes malicious release)
- Transitive supply-chain attacks (compromised composite action)
Lockfiles do not protect against:
- Malicious code in the initial locked commit
- Vulnerabilities in the action's dependencies (npm packages, Docker images)
- Secrets exfiltration if the action already has access
You still need to review actions before locking them. The lockfile ensures you run the code you reviewed, not whatever the maintainer pushes later.
Technical Verdict
Use workflow lockfiles if:
- Your workflows have write permissions or access to production secrets
- You use third-party actions from outside your organization
- You need audit trails for compliance or incident response
- You want to enforce supply-chain security policies at scale
Avoid lockfiles if:
- Your workflows are read-only and run in isolated environments
- You only use first-party actions from your own organization
- You prefer manual SHA pinning and can tolerate high review overhead
Lockfiles are most valuable for high-risk workflows. Start with deployment pipelines, release automation, and anything that touches production infrastructure. Expand to lower-risk workflows as you build confidence with the tooling.
The gh actions-lock verify command belongs in CI. Fail the build if the lockfile is stale, forcing developers to update it before merging.
Top comments (0)