Enhancing GitHub Actions Security: Workflow Dependency Locking and Code Review Analytics

Workflow diagram with locked dependencies, emphasizing security and reproducibility.
Workflow diagram with locked dependencies, emphasizing security and reproducibility.

GitHub Actions Dependency Locking: A Leap Towards Secure and Reproducible Workflows

GitHub is taking a significant step towards bolstering the security and reliability of GitHub Actions with a new proposal for workflow-level dependency locking. This initiative, previewed in their 2026 GitHub Actions Security Roadmap, aims to address critical gaps in how workflows manage and record their dependencies, ultimately enhancing reproducibility and providing clearer insights for code review analytics.

The Problem: Non-Deterministic Workflows and Hidden Dependencies

Currently, GitHub Actions lack a persistent record of the exact dependencies resolved during a workflow run. Resolution happens at runtime, the results are discarded, and there's no easy way to track changes or ensure determinism. This is exacerbated by composite actions, which can embed invisible nested dependencies. The absence of a lockfile, common in mature package ecosystems like npm or Go, leads to:

  • No Determinism: The same workflow file can produce different outcomes.
  • No Diffability: Dependency changes, especially transitive ones, are hidden from pull request reviews.
  • No Receipts: No committed record of the precise dependency graph that executed.

These issues make workflows vulnerable to supply chain attacks, where mutable references (tags) can be silently moved to malicious commits. The proposed solution seeks to provide a point-in-time resolution that is auditable and reviewable.

The Solution: A dependencies: Contract and gh actions pin CLI

GitHub proposes introducing a new dependencies: section directly within workflow YAML files. This section will lock every direct and transitive dependency to an exact commit SHA, akin to Go's go.mod + go.sum. The gh actions pin CLI command will generate and maintain this section, ensuring that what was resolved and pinned is exactly what executes, even if the original ref changes.

Here's an example of how the generated dependencies: section might look:

name: Happy path
on: workflow_dispatch:
jobs:
  lint:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v6
      - uses: nodeselector/actions-test-fixtures/nested-composite@updated
  build:
    uses: nodeselector/actions-test-fixtures/.github/workflows/reusable-build.yml@main
# Automatically generated and managed by gh-actions-pin
dependencies:
  - github.com/actions/checkout@v6:sha1-34e114876b0b11c390a56381ad16ebd13914f8d5
  - github.com/nodeselector/actions-test-fixtures/nested-composite@updated:sha1-ea53476fdc172d8552df5af9658a45a367e4f41d
  # Transitive dependencies (via nodeselector/actions-test-fixtures/nested-composite@updated)
  - github.com/nodeselector/actions-test-fixtures/simple-composite@main:sha1-d010fee89969c44873ca2c1b501905190eb7410d
  # Transitive dependencies (via nodeselector/actions-test-fixtures/simple-composite@main)
  - github.com/nodeselector/actions-test-fixtures-b/simple-echo@main:sha1-92b7b0058bc223c6e9dd4e19ef9247c934ba7637
  - github.com/nodeselector/actions-test-fixtures/simple-node@main:sha1-d010fee89969c44873ca2c1b501905190eb7410d

This approach promises deterministic runs, reviewable updates (critical for code review analytics), fail-fast verification, and full visibility into all dependencies, including transitive ones.

Community Insights and Feedback

The community discussion highlighted several key considerations:

  • Separate Lockfile Preference: Many users, including @martincostello, @ljharb, @thehale, and @woodruffw, expressed a strong preference for a separate lockfile (e.g., .github/actions.lock.yml) rather than embedding the dependencies: block directly in the workflow YAML. This would reduce visual noise, simplify CODEOWNERS control, and manage diff churn, especially in repositories with numerous workflows.
  • Beyond SHA-pinning: @provinzkraut suggested that SHA-based locking might not be sufficient, advocating for hashing the contents of dependencies (similar to Python's pip) to ensure that external changes within an action are also caught.
  • Complex Dependency Scenarios: @jsoref raised concerns about workflows with diverse and often optional dependencies (CPAN, Apt, GitHub releases, runtime-selected actions), questioning how a static lockfile would handle such dynamic environments without forcing unnecessary downloads or becoming overly complex. The need for an SBOM-like reporting mechanism was also suggested.
  • Structured Transitive Dependencies: @thehale and @woodruffw noted that communicating transitive relationships via YAML comments is non-semantic and difficult to parse programmatically. They proposed a more structured, machine-readable format within the lockfile.
  • Pre-execution Policy Enforcement: @pinfloyd emphasized the potential for dependency locking to serve as an input for pre-execution policy and security tooling, enabling automation-created or AI-assisted workflow changes to fail closed before any job runs. This could significantly enhance supply chain security.
  • Mandatory Locking and Global Scope: @woodruffw also advocated for making locked resolutions mandatory in the long term and for a single, global lockfile across all workflows in a repository.

Looking Ahead

This proposal represents a crucial step for GitHub Actions, promising to bring them in line with best practices for dependency management seen in other mature ecosystems. While the initial feedback indicates a strong desire for a separate, more structured lockfile and consideration for complex real-world scenarios, the core initiative to enhance determinism, auditability, and security is widely welcomed. This will undoubtedly improve the quality of developer reports and the confidence in CI/CD pipelines.

Developer reviewing a dependency lockfile, with analytics on screen.
Developer reviewing a dependency lockfile, with analytics on screen.

|

Dashboards, alerts, and review-ready summaries built on your GitHub activity.

 Install GitHub App to Start
Dashboard with engineering activity trends