dependabot / dependabot/dependabot-core

GitHub Actions: SHA-pinned actions updated to untagged branch HEAD commit when current SHA lacks a direct tag, leaving version comment stale

Open
#14,716 1 comment 3 reactions 0 assignees View on GitHub
L: github:actions
Dominant language
Ruby
Stars
5.8k
Forks
1.5k
Avg merge
2d 18h
Merged PRs (30d)
149

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Package ecosystem

github-actions

### Package manager version

N/A

### Language version

N/A

### Manifest location and content before the Dependabot update

Example from [awslabs/mcp](https://github.com/awslabs/mcp/blob/main/.github/workflows/cfn_nag.yml) before the update:

```yaml
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@c0fc915677567258ee3c194d03ffe7ae3dc8d741 # v4.31.9
```

### dependabot.yml content

```yaml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
```

### Updated dependency

`github/codeql-action` — SHA updated from `c0fc915677567258ee3c194d03ffe7ae3dc8d741` to `76a687e1d810ec603951c060d5afa98f121364a7`, but version comment remains `# v4.31.9`.

### What you expected to see, versus what you actually saw

**Expected:** Dependabot should update the SHA to the commit corresponding to the latest tagged release (`v4.35.1` = `c10b8064de6f491fea524254123dbe5e09572f13`, which is the HEAD of `releases/v4`) and update the version comment to `# v4.35.1`.

**Actual:** Dependabot updates the SHA to `76a687e1d810ec603951c060d5afa98f121364a7` — the HEAD of the `main` branch — which is **not** a tagged release. The version comment is left unchanged at `# v4.31.9`, which is now factually incorrect and actively misleading.

This is visible in [awslabs/mcp#2932](https://github.com/awslabs/mcp/pull/2932). In the same PR, actions where the SHA **does** correspond to a tagged release get their comments updated correctly. For example, `astral-sh/setup-uv` is correctly updated from `# v7.3.0` to `# v8.0.0`. But all `github/codeql-action` entries get a new SHA with a stale comment.

**Verification of the tag/SHA discrepancy:**

```
$ git ls-remote --tags https://github.com/github/codeql-action.git | grep v4.35.1
0e9f55954318745b37b7933c693bc093f7336125 refs/tags/v4.35.1
c10b8064de6f491fea524254123dbe5e09572f13 refs/tags/v4.35.1^{}

$ git ls-remote --heads https://github.com/github/codeql-action.git | grep releases/v4
c10b8064de6f491fea524254123dbe5e09572f13 refs/heads/releases/v4
```

The `v4.35.1` tag points to commit `c10b8064...` on the `releases/v4` branch. But Dependabot chose `76a687e1...` (HEAD of `main`), which has no tag.

### Root cause

The issue is in [`update_checker.rb:latest_commit_sha`](https://github.com/dependabot/dependabot-core/blob/main/github_actions/lib/dependabot/github_actions/update_checker.rb#L170-L178):

```ruby
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) # ✅ Correct: use the tagged release commit
else
latest_commit_for_pinned_ref # ❌ Bug: gets HEAD of containing branch
end
end
```

When `local_tag_for_pinned_sha` returns nil (the current SHA has no tag pointing to it), the code falls through to `latest_commit_for_pinned_ref`, which clones the repo, finds the branch containing the current SHA, and returns that branch's HEAD commit. This completely ignores the `new_tag` that was already resolved.

This happens with action repositories that use a **release branch workflow** (e.g., `github/codeql-action` where tags point to commits on `releases/v4` but development happens on `main`). Once a SHA ends up on `main` (either through this bug or manual error), subsequent updates will perpetually resolve to the HEAD of `main` — never a tagged release — creating a self-perpetuating cycle of stale comments and untagged SHAs.

The same `latest_commit_for_pinned_ref` / `find_container_branch` pattern exists in [`package_details_fetcher.rb`](https://github.com/dependabot/dependabot-core/blob/main/github_actions/lib/dependabot/github_actions/package/package_details_fetcher.rb#L212-L236) with the same issue.

### Native package manager behavior

N/A — GitHub Actions has no native package manager for version resolution.

### Images of the diff or a link to the PR, issue, or logs

- **PR exhibiting the bug:** [awslabs/mcp#2932](https://github.com/awslabs/mcp/pull/2932)
- Correctly updated (tag has matching SHA): [`aws-api-mcp-upgrade-version.yml` line 43](https://github.com/awslabs/mcp/blob/33f9e80f56f72d1b35d8a53d4ea78b0bb510fcd5/.github/workflows/aws-api-mcp-upgrade-version.yml#L43) — `astral-sh/setup-uv` comment updated from `# v7.3.0` → `# v8.0.0`
- **Not** updated (SHA on wrong branch): [`cfn_nag.yml` line 38](https://github.com/awslabs/mcp/blob/33f9e80f56f72d1b35d8a53d4ea78b0bb510fcd5/.github/workflows/cfn_nag.yml#L38) — `github/codeql-action` comment stuck at `# v4.31.9`

### Related issues

- #7912 — Version comment not updated if existing comment is already incorrect (open, 21 upvotes)
- #8011 — Hash-pinned `actions/checkout` v3→v4 doesn't always update version comments (open)
- #13466 — Hash pinned actions updated to latest commit instead of released version (closed by #14349, but fix only addressed mixed tag/SHA ref downgrade — not the branch-resolution fallback)
- #14685 — Dependabot puts incorrect version info into GHA update PRs (open)

PR #14349 fixed the narrow case where mixed tag/SHA refs caused downgrade via the shared `git_commit_checker`, but did not address the underlying `latest_commit_for_pinned_ref` fallback that resolves to untagged branch HEAD commits.

### Smallest manifest that reproduces the issue

Any workflow file SHA-pinned to a commit on `main` for an action that publishes releases on a separate branch (e.g., `releases/v4`):

```yaml
name: Reproduce
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
# Pin to a main-branch commit for codeql-action (tags are on releases/v4)
- uses: github/codeql-action/upload-sarif@76a687e1d810ec603951c060d5afa98f121364a7 # v4.31.9
```

Contributor guide

Open the contributing guide

Research direction

Start in github_actions/lib/dependabot/github_actions/update_checker.rb at latest_commit_sha and trace the latest_commit_for_pinned_ref fallback. Then inspect package_details_fetcher.rb around the corresponding latest_commit_for_pinned_ref and find_container_branch logic. Reproduce with the minimal SHA-pinned workflow described in the issue; done means updates use the tagged release commit and keep the version comment accurate in both paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions, ruby
Domain
ci-cd, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.