Skip to content

Commit 1fdf76a

Browse files
author
Alvaro Muñoz
committed
Improve download artifact and untrusted checkout queries
1 parent bdaab69 commit 1fdf76a

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,33 @@ abstract class UntrustedArtifactDownloadStep extends Step {
1616
abstract string getPath();
1717
}
1818

19+
class GitHubDownloadArtifactActionStep extends UntrustedArtifactDownloadStep, UsesStep {
20+
GitHubDownloadArtifactActionStep() {
21+
// By default, the permissions are scoped so they can only download Artifacts within the current workflow run.
22+
// To elevate permissions for this scenario, you can specify a github-token along with other repository and run identifiers
23+
this.getCallee() = "actions/download-artifact" and
24+
this.getArgument("run-id").matches("%github.event.workflow_run.id%") and
25+
exists(this.getArgument("github-token"))
26+
}
27+
28+
override string getPath() {
29+
if exists(this.getArgument("path")) then result = this.getArgument("path") else result = ""
30+
}
31+
}
32+
1933
class DownloadArtifactActionStep extends UntrustedArtifactDownloadStep, UsesStep {
2034
DownloadArtifactActionStep() {
2135
this.getCallee() =
2236
[
23-
"actions/download-artifact", "dawidd6/action-download-artifact",
24-
"marcofaggian/action-download-multiple-artifacts", "benday-inc/download-latest-artifact",
25-
"blablacar/action-download-last-artifact", "levonet/action-download-last-artifact",
26-
"bettermarks/action-artifact-download", "aochmann/actions-download-artifact",
27-
"cytopia/download-artifact-retry-action", "alextompkins/download-prior-artifact",
28-
"nmerget/download-gzip-artifact", "benday-inc/download-artifact",
29-
"synergy-au/download-workflow-artifacts-action", "ishworkh/docker-image-artifact-download",
30-
"ishworkh/container-image-artifact-download", "sidx1024/action-download-artifact",
31-
"hyperskill/azblob-download-artifact", "ma-ve/action-download-artifact-with-retry"
37+
"dawidd6/action-download-artifact", "marcofaggian/action-download-multiple-artifacts",
38+
"benday-inc/download-latest-artifact", "blablacar/action-download-last-artifact",
39+
"levonet/action-download-last-artifact", "bettermarks/action-artifact-download",
40+
"aochmann/actions-download-artifact", "cytopia/download-artifact-retry-action",
41+
"alextompkins/download-prior-artifact", "nmerget/download-gzip-artifact",
42+
"benday-inc/download-artifact", "synergy-au/download-workflow-artifacts-action",
43+
"ishworkh/docker-image-artifact-download", "ishworkh/container-image-artifact-download",
44+
"sidx1024/action-download-artifact", "hyperskill/azblob-download-artifact",
45+
"ma-ve/action-download-artifact-with-retry"
3246
] and
3347
(
3448
not exists(this.getArgument(["branch", "branch_name"])) or

ql/lib/codeql/actions/security/UntrustedCheckoutQuery.qll

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ class ActionsMutableRefCheckout extends MutableRefCheckoutStep instanceof UsesSt
9393
// 3rd party actions returning the PR head sha/ref
9494
exists(UsesStep step |
9595
(
96-
step.getCallee() = ["eficode/resolve-pr-refs", "xt0rted/pull-request-comment-branch"] and
96+
step.getCallee() =
97+
[
98+
"eficode/resolve-pr-refs", "xt0rted/pull-request-comment-branch",
99+
"alessbell/pull-request-comment-branch", "gotson/pull-request-comment-branch"
100+
] and
97101
// TODO: This should be read step of the head_sha or head_ref output vars
98102
this.getArgument("ref").matches("%.head_ref%")
99103
or
@@ -229,10 +233,10 @@ class GhSHACheckout extends SHACheckoutStep instanceof Run {
229233
/** An If node that contains an actor, user or label check */
230234
abstract class ControlCheck extends If {
231235
predicate dominates(Step step) {
232-
step.getIf() = this or
236+
step.getIf() = this or
233237
step.getEnclosingJob().getIf() = this or
234-
step.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
235-
step.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
238+
step.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
239+
step.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
236240
}
237241
}
238242

@@ -259,7 +263,7 @@ class ActorControlCheck extends ControlCheck {
259263
.regexpFind([
260264
"\\bgithub\\.actor\\b", "\\bgithub\\.triggering_actor\\b",
261265
"\\bgithub\\.event\\.comment\\.user\\.login\\b",
262-
"\\bgithub\\.event\\.pull_request\\.user\\.login\\b",
266+
"\\bgithub\\.event\\.pull_request\\.user\\.login\\b",
263267
], _, _)
264268
)
265269
}
@@ -270,10 +274,7 @@ class RepositoryControlCheck extends ControlCheck {
270274
// eg: github.repository == 'test/foo'
271275
exists(
272276
normalizeExpr(this.getCondition())
273-
.regexpFind([
274-
"\\bgithub\\.repository\\b",
275-
"\\bgithub\\.repository_owner\\b",
276-
], _, _)
277+
.regexpFind(["\\bgithub\\.repository\\b", "\\bgithub\\.repository_owner\\b",], _, _)
277278
)
278279
}
279280
}

0 commit comments

Comments
 (0)