Unpinned floating tags (e.g. `v4`) on immutable Actions are not flagged by `actions/unpinned-tag`
- Dominant language
- CodeQL
- Stars
- 10.1k
- Forks
- 2.1k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 141
Description
**Description of the issue**
The `actions/unpinned-tag` query (`actions/ql/src/Security/CWE-829/UnpinnedActionsTag.ql`) exempts any Action on the immutable-actions allow list from the unpinned-tag warning, regardless of the ref used. The exclusion is version-independent:
```ql
not exists(UsesStep step | uses = step and isImmutableAction(step, nwo))
```
and `isImmutableAction` (`actions/ql/lib/codeql/actions/security/UseOfUnversionedImmutableAction.qll`) only checks membership in `immutableActionsDataModel(nwo)`; it never inspects the version.
**Why this is a gap**
GitHub's immutability guarantee only applies to fully-expanded SemVer release tags (`vX.Y.Z`) and full commit SHAs. Floating tags such as `v4`, `v4.0` and `main` remain mutable: maintainers move them to the latest matching release, so they can change under a consumer exactly like any other tag. See [Using immutable releases and tags to manage your action's releases](https://docs.github.com/en/actions/how-tos/create-and-publish-actions/using-immutable-releases-and-tags-to-manage-your-actions-releases).
As a result, a reference like `actions/checkout@v2` is flagged by neither query:
- `UnpinnedActionsTag` skips it because `actions/checkout` is on the immutable list.
- `UnversionedImmutableAction` skips it because its `isSemVer` predicate accepts a bare major tag like `v2`.
So a genuinely mutable floating tag on an immutable Action goes unwarned.
**Suggested direction**
Narrow the exemption so an immutable Action is only exempt when pinned to a full `vX.Y.Z` (or a SHA), for example:
```ql
not (isImmutableAction(step, nwo) and isFullSemVer(version))
```
with an `isFullSemVer` stricter than the current `isSemVer` (which also matches floating `vX` and `vX.Y`). This would need care because the immutable-action model is shared with the experimental `UnversionedImmutableAction` query, and it would increase alert volume for consumers pinning immutable Actions to floating major tags, so it deserves its own change note and review.
Filed as a follow-up to #22409 (which is scoped to the trusted-owner allow list and does not address this).
Contributor guide
Research direction
Read actions/ql/src/Security/CWE-829/UnpinnedActionsTag.ql and actions/ql/lib/codeql/actions/security/UseOfUnversionedImmutableAction.qll, starting with isImmutableAction and the existing SemVer predicate. Done means full vX.Y.Z tags and full SHAs remain exempt while floating refs such as vX and vX.Y are reported, with the required change note included.
Written by the indexing model from the issue text.
Assessment
- Domain
- security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100