Skip to content

Commit 8a199f9

Browse files
authored
Merge pull request #21692 from github/copilot/update-codeql-query-for-composite-actions
Extend `actions/unpinned-tag` to analyze composite action metadata (`action.yml` / `action.yaml`)
2 parents fcdce55 + b204603 commit 8a199f9

5 files changed

Lines changed: 31 additions & 8 deletions

File tree

actions/ql/src/Security/CWE-829/UnpinnedActionsTag.ql

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @name Unpinned tag for a non-immutable Action in workflow
2+
* @name Unpinned tag for a non-immutable Action in workflow or composite action
33
* @description Using a tag for a non-immutable Action that is not pinned to a commit can lead to executing an untrusted Action through a supply chain attack.
44
* @kind problem
55
* @security-severity 5.0
@@ -31,15 +31,26 @@ private predicate isPinnedContainer(string version) {
3131
bindingset[nwo]
3232
private predicate isContainerImage(string nwo) { nwo.regexpMatch("^docker://.+") }
3333

34-
from UsesStep uses, string nwo, string version, Workflow workflow, string name
34+
private predicate getStepContainerName(UsesStep uses, string name) {
35+
exists(Workflow workflow |
36+
uses.getEnclosingWorkflow() = workflow and
37+
(
38+
workflow.getName() = name
39+
or
40+
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
41+
)
42+
)
43+
or
44+
exists(CompositeAction action |
45+
uses.getEnclosingCompositeAction() = action and
46+
name = action.getLocation().getFile().getBaseName()
47+
)
48+
}
49+
50+
from UsesStep uses, string nwo, string version, string name
3551
where
3652
uses.getCallee() = nwo and
37-
uses.getEnclosingWorkflow() = workflow and
38-
(
39-
workflow.getName() = name
40-
or
41-
not exists(workflow.getName()) and workflow.getLocation().getFile().getBaseName() = name
42-
) and
53+
getStepContainerName(uses, name) and
4354
uses.getVersion() = version and
4455
not isTrustedOwner(nwo) and
4556
not (if isContainerImage(nwo) then isPinnedContainer(version) else isPinnedCommit(version)) and
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The `actions/unpinned-tag` query now analyzes composite action metadata (`action.yml`/`action.yaml` files) in addition to workflow files, providing more comprehensive detection of unpinned action references across the entire Actions ecosystem.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: Composite unpinned tag test
2+
runs:
3+
using: "composite"
4+
steps:
5+
- uses: foo/bar@v2
6+
- uses: foo/bar@25b062c917b0c75f8b47d8469aff6c94ffd89abb

actions/ql/test/query-tests/Security/CWE-829/UnpinnedActionsTag.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
| .github/actions/unpinned-tag/action.yml:5:13:5:22 | foo/bar@v2 | Unpinned 3rd party Action 'action.yml' step $@ uses 'foo/bar' with ref 'v2', not a pinned commit hash | .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | Uses Step |
12
| .github/workflows/actor_trusted_checkout.yml:19:13:19:36 | completely/fakeaction@v2 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Uses Step |
23
| .github/workflows/actor_trusted_checkout.yml:23:13:23:37 | fakerepo/comment-on-pr@v1 | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Uses Step |
34
| .github/workflows/artifactpoisoning21.yml:13:15:13:49 | dawidd6/action-download-artifact@v2 | Unpinned 3rd party Action 'Pull Request Open' step $@ uses 'dawidd6/action-download-artifact' with ref 'v2', not a pinned commit hash | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | Uses Step |

actions/ql/test/query-tests/Security/CWE-829/UntrustedCheckoutCritical.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edges
88
| .github/actions/download-artifact/action.yaml:25:7:29:4 | Run Step | .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step |
99
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/artifactpoisoning91.yml:19:9:25:6 | Run Step: metadata |
1010
| .github/actions/download-artifact/action.yaml:29:7:32:18 | Run Step | .github/workflows/resolve-args.yml:22:9:36:13 | Run Step: resolve-step |
11+
| .github/actions/unpinned-tag/action.yml:5:7:6:4 | Uses Step | .github/actions/unpinned-tag/action.yml:6:7:6:61 | Uses Step |
1112
| .github/workflows/actor_trusted_checkout.yml:9:7:14:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step |
1213
| .github/workflows/actor_trusted_checkout.yml:14:7:15:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step |
1314
| .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step |

0 commit comments

Comments
 (0)