Skip to content

Pin third-party GitHub Actions to full-length commit SHAs (supply-chain hardening) #57

Description

@dmchaledev

Problem

Both workflow files reference third-party GitHub Actions by mutable version tag rather than an immutable commit SHA:

.github/workflows/validate-openapi.yml

- uses: actions/checkout@v4
- uses: actions/setup-node@v4

.github/workflows/deploy-docs.yml

- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
- uses: actions/deploy-pages@v4

A version tag like v4 can be repointed to a different commit at any time — either by the action maintainer, or by an attacker who compromises the action's repo/publishing credentials. If that happens, the next CI run silently pulls the new (possibly malicious) code with no diff for anyone to review, since nothing changes in this repo. This is exactly the mechanism used in the March 2025 tj-actions/changed-files supply-chain compromise, where a retagged release exfiltrated CI secrets from thousands of repos. deploy-docs.yml in particular runs with pages: write / id-token: write permissions, so a compromised action there could push arbitrary content to the live docs site.

GitHub's own CI hardening guidance, OpenSSF Scorecard's "Pinned-Dependencies" check, and step-security/harden-runner all recommend pinning uses: references to a full 40-character commit SHA instead of a tag.

Proposed fix

For each uses: line in both workflow files, replace the tag with the commit SHA it currently resolves to, keeping the version as a trailing comment for readability, e.g.:

- uses: actions/checkout@<full-40-char-sha>  # v4.x.x

The exact SHAs should be pulled fresh at implementation time (e.g. via git ls-remote --tags https://github.com/actions/checkout or the action's GitHub Releases page) rather than copied from anywhere else, since a stale/wrong SHA is worse than a tag.

Dependabot (already configured for the github-actions ecosystem in .github/dependabot.yml) natively supports keeping SHA-pinned actions up to date — it updates both the SHA and the trailing version comment in its PRs, so no loss of update automation.

Sequencing note

There are currently 5 open Dependabot PRs (#51#55) bumping these same uses: lines to newer tags (checkout v4→v7, setup-node v4→v7, configure-pages v5→v6, upload-pages-artifact v3→v5, deploy-pages v4→v5). To avoid merge conflicts / duplicate churn on the same lines, this should either:

Scope

.github/workflows/validate-openapi.yml, .github/workflows/deploy-docs.yml only — no functional change, just replacing tag refs with SHA refs.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions