Fix GitHub Actions SHA-pinned refs being downgraded when mixed with tag refs#14349
Fix GitHub Actions SHA-pinned refs being downgraded when mixed with tag refs#14349
Conversation
…ag refs When a dependency has mixed tag-based (e.g., @v4) and SHA-pinned (e.g., @abc123 # v6.0.1) requirements across workflow files, the SHA-pinned refs were being incorrectly downgraded. Root cause: latest_commit_sha used the shared git_commit_checker (which picks the first requirement's source ref, e.g., 'v4'). Since 'v4' is not a SHA, local_tag_for_pinned_sha returned nil, causing the code to follow the v4 branch and return v4's latest SHA instead of the target version's SHA. Fix: Pass the source-specific git_commit_checker to latest_commit_sha so it checks local_tag_for_pinned_sha against the actual SHA-pinned ref, correctly taking the path that returns the target version's commit SHA. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a GitHub Actions update-checking bug where dependencies with mixed tag refs and SHA-pinned refs across workflow files could incorrectly apply the tag ref’s commit SHA to SHA-pinned requirements (effectively downgrading them).
Changes:
- Update the GitHub Actions
UpdateCheckerto pass a source-specificGitCommitCheckerintolatest_commit_shawhen resolving updates for SHA-pinned requirements. - Add an RSpec regression test covering mixed tag + SHA requirements across multiple workflow files.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| github_actions/lib/dependabot/github_actions/update_checker.rb | Uses the per-requirement GitCommitChecker when computing the latest commit SHA for SHA-pinned refs. |
| github_actions/spec/dependabot/github_actions/update_checker_spec.rb | Adds coverage for mixed tag and SHA requirements to prevent SHA-pinned refs being updated via the tag ref’s source. |
Comments suppressed due to low confidence (1)
github_actions/lib/dependabot/github_actions/update_checker.rb:178
latest_commit_shanow checkssource_checker.local_tag_for_pinned_sha, but the fallback still callslatest_commit_for_pinned_ref, which is memoized and computed via the sharedgit_commit_checker(based ondependency.source_details, i.e., typically the first requirement’s ref). In mixed-requirement dependencies, this can still yield the wrong commit (e.g., for a SHA requirement wherelocal_tag_for_pinned_shais nil, the fallback may follow the first requirement’s tag/branch instead). Consider making the fallback source-specific as well (e.g., passsource_checkerthrough and memoize per ref) so mixed refs can’t influence each other.
sig { params(source_checker: Dependabot::GitCommitChecker).returns(T.nilable(String)) }
def latest_commit_sha(source_checker)
new_tag = T.must(latest_version_finder).latest_version_tag
return unless new_tag
if source_checker.local_tag_for_pinned_sha
new_tag.fetch(:commit_sha)
else
latest_commit_for_pinned_ref
end
VerificationTested end-to-end using the Dependabot CLI against a local reproduction repo. Repo setupThree workflow files referencing
uses: actions/checkout@v4
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2Before fixAfter fixBuilt the Docker image locally with |
Problem
When a repository references the same GitHub Action with a mix of tag refs (
@v4) and SHA-pinned refs (@<sha> # v6), the SHA-pinned refs get downgraded instead of upgraded.For example, given three workflow files:
codeql-rust.ymlactions/checkout@v4@v6rust.ymlactions/checkout@<sha> # v6.0.1@<sha> # v6.0.2security-workflow.ymlactions/checkout@<sha> # v6.0.2Dependabot was updating the SHA-pinned v6 refs to the v4 branch HEAD SHA (v4.3.1), effectively downgrading them.
Root cause
DependencySet.combined_versionpicks the lowest version across all requirements, so the combined dependency version becomes "4" rather than "6.0.1". TheUpdateCheckercreates a source-specificgit_commit_checkerper requirement (correct), butlatest_commit_shaused the sharedgit_commit_checkerwhich gets its ref from the first requirement's source:ref: "v4"(a tag, not a SHA).Since "v4" is not a SHA,
local_tag_for_pinned_shareturns nil, and the code falls through tolatest_commit_for_pinned_ref, which follows the v4 ref and returns the v4.3.1 SHA. That wrong SHA then gets applied to all SHA-pinned requirements.Fix
Pass the source-specific
git_commit_checker(which has the actual SHA ref for each requirement) tolatest_commit_sha, solocal_tag_for_pinned_shacorrectly resolves the tag from the SHA and returns the right commit.4 lines changed in production code.
Fixes #13677.