Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ class UnversionedImmutableAction extends UsesStep {
}
}

/**
* Holds if `version` is a complete SemVer version (`X.Y.Z`, optionally with a `v` prefix,
* pre-release and build metadata), as opposed to a floating tag such as `v4` or `v4.1`.
*
* Only complete version tags (and full commit SHAs) of an immutable Action are immutable.
* Floating tags are moved by the Action's maintainers and so can change under a consumer.
*/
bindingset[version]
predicate isSemVer(string version) {
predicate isFullSemVer(string version) {
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string with optional v prefix
version
.regexpMatch("^v?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$") or
.regexpMatch("^v?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$")
}

bindingset[version]
predicate isSemVer(string version) {
isFullSemVer(version) or
// or N or N.x or N.N.x with optional v prefix
version.regexpMatch("^v?[1-9]\\d*$") or
version.regexpMatch("^v?[1-9]\\d*\\.(x|0|([1-9]\\d*))$") or
Expand Down
4 changes: 3 additions & 1 deletion actions/ql/src/Security/CWE-829/UnpinnedActionsTag.ql
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ where
then isPinnedContainer(version)
else isPinnedCommit(version)
) and
not exists(UsesStep step | uses = step and isImmutableAction(step, nwo)) and
// An immutable Action is only immutable when referenced by a complete version tag (or SHA).
// Floating tags such as `v4` or `v4.1` are moved by the maintainers and remain mutable.
not exists(UsesStep step | uses = step and isImmutableAction(step, nwo) and isFullSemVer(version)) and
if uses instanceof ExternalJob
then
message =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `actions/unpinned-tag` query no longer treats an immutable Action as pinned when it is referenced by a floating tag such as `v4`, `v4.1`, `main` or `latest`. Only complete version tags (for example `v4.2.2`) and full commit SHAs are immutable, so floating tags are now reported for immutable Actions that are not covered by a trusted owner.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Immutable Actions
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
# `actions` is distrusted via `!actions`. `actions/checkout` is an immutable Action, but only
# a complete version tag (or a commit SHA) is immutable, so floating tags are still reported.
- uses: actions/checkout@v4 # $ Alert
- uses: actions/checkout@v4.1 # $ Alert
- uses: actions/checkout@main # $ Alert
- uses: actions/checkout@latest # $ Alert
# Complete version tags of an immutable Action are not reported.
- uses: actions/checkout@v4.2.2
- uses: actions/checkout@4.2.2
- uses: actions/checkout@v4.2.2-rc.1
# A pinned commit is not reported.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# `octokit` is not trusted by default; `octokit/request-action` is an immutable Action.
- uses: octokit/request-action@v2 # $ Alert
- uses: octokit/request-action@v2.x # $ Alert
- uses: octokit/request-action@v2.1.9
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
| .github/workflows/unpinned_first_party.yml:9:15:9:42 | actions/first-interaction@v1 | Unpinned 3rd party Action 'Unpinned first-party actions' step $@ uses 'actions/first-interaction' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_first_party.yml:9:9:11:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_first_party.yml:13:15:13:24 | foo/bar@v1 | Unpinned 3rd party Action 'Unpinned first-party actions' step $@ uses 'foo/bar' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_first_party.yml:13:9:13:35 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:9:15:9:33 | actions/checkout@v4 | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'actions/checkout' with ref 'v4', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:9:9:10:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:10:15:10:35 | actions/checkout@v4.1 | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'actions/checkout' with ref 'v4.1', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:10:9:11:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:11:15:11:35 | actions/checkout@main | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'actions/checkout' with ref 'main', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:11:9:12:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:12:15:12:37 | actions/checkout@latest | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'actions/checkout' with ref 'latest', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:12:9:14:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:20:15:20:39 | octokit/request-action@v2 | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'octokit/request-action' with ref 'v2', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:20:9:21:6 | Uses Step | Uses Step |
| .github/workflows/unpinned_immutable.yml:21:15:21:41 | octokit/request-action@v2.x | Unpinned 3rd party Action 'Immutable Actions' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/unpinned_immutable.yml:21:9:22:6 | Uses Step | Uses Step |
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
| .github/workflows/issue_comment_3rd_party_action.yml:14:15:14:52 | xt0rted/pull-request-comment-branch@v2 | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'xt0rted/pull-request-comment-branch' with ref 'v2', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:12:9:16:6 | Uses Step: comment-branch | Uses Step: comment-branch |
| .github/workflows/issue_comment_3rd_party_action.yml:27:15:27:52 | xt0rted/pull-request-comment-branch@v2 | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'xt0rted/pull-request-comment-branch' with ref 'v2', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:25:9:30:6 | Uses Step: comment-branch | Uses Step: comment-branch |
| .github/workflows/issue_comment_3rd_party_action.yml:41:15:41:42 | eficode/resolve-pr-refs@main | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'eficode/resolve-pr-refs' with ref 'main', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:39:9:45:6 | Uses Step: refs | Uses Step: refs |
| .github/workflows/issue_comment_octokit2.yml:13:15:13:41 | octokit/request-action@v2.x | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/issue_comment_octokit2.yml:12:9:19:6 | Uses Step: fetch_issue | Uses Step: fetch_issue |
| .github/workflows/issue_comment_octokit2.yml:20:15:20:43 | octokit/request-action@v2.x.x | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x.x', not a pinned commit hash | .github/workflows/issue_comment_octokit2.yml:19:9:26:6 | Uses Step: fetch_pr | Uses Step: fetch_pr |
| .github/workflows/issue_comment_octokit2.yml:34:15:34:42 | some-action/some-repo@latest | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'some-action/some-repo' with ref 'latest', not a pinned commit hash | .github/workflows/issue_comment_octokit2.yml:33:9:37:6 | Uses Step | Uses Step |
| .github/workflows/issue_comment_octokit.yml:13:15:13:41 | octokit/request-action@v2.x | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/issue_comment_octokit.yml:12:9:19:6 | Uses Step: fetch_issue | Uses Step: fetch_issue |
| .github/workflows/issue_comment_octokit.yml:20:15:20:41 | octokit/request-action@v2.x | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/issue_comment_octokit.yml:19:9:26:6 | Uses Step: fetch_pr | Uses Step: fetch_pr |
| .github/workflows/label_trusted_checkout1.yml:20:13:20:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'label_trusted_checkout1.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/label_trusted_checkout1.yml:20:7:24:4 | Uses Step | Uses Step |
| .github/workflows/label_trusted_checkout1.yml:24:13:24:37 | fakerepo/comment-on-pr@v1 | Unpinned 3rd party Action 'label_trusted_checkout1.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/label_trusted_checkout1.yml:24:7:27:21 | Uses Step | Uses Step |
| .github/workflows/label_trusted_checkout2.yml:21:13:21:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'label_trusted_checkout2.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/label_trusted_checkout2.yml:21:7:25:4 | Uses Step | Uses Step |
Expand Down
Loading