Skip to content

Commit 6802cd2

Browse files
author
Alvaro Muñoz
committed
Improve checkout trigger events checks
1 parent dbcf113 commit 6802cd2

3 files changed

Lines changed: 25 additions & 33 deletions

File tree

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

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ string checkoutTriggers() {
1313
*/
1414
private module ActionsMutableRefCheckoutConfig implements DataFlow::ConfigSig {
1515
predicate isSource(DataFlow::Node source) {
16-
source.asExpr().getATriggerEvent().getName() = checkoutTriggers() and
16+
//source.asExpr().getATriggerEvent().getName() = checkoutTriggers() and
1717
(
1818
// remote flow sources
1919
source instanceof ArtifactSource
@@ -209,29 +209,24 @@ abstract class SHACheckoutStep extends PRHeadCheckoutStep { }
209209
class ActionsMutableRefCheckout extends MutableRefCheckoutStep instanceof UsesStep {
210210
ActionsMutableRefCheckout() {
211211
this.getCallee() = "actions/checkout" and
212+
//this.getEnclosingJob().getATriggerEvent().getName() = checkoutTriggers() and
212213
(
213214
exists(
214215
ActionsMutableRefCheckoutFlow::PathNode source, ActionsMutableRefCheckoutFlow::PathNode sink
215216
|
216217
ActionsMutableRefCheckoutFlow::flowPath(source, sink) and
217-
sink.getNode().asExpr() = this.getArgumentExpr(["ref", "repository"])
218+
this.getArgumentExpr(["ref", "repository"]) = sink.getNode().asExpr()
218219
)
219220
or
220221
// heuristic base on the step id and field name
221-
exists(string value |
222-
this.getArgumentExpr("ref")
223-
.(SimpleReferenceExpression)
224-
.getEnclosingJob()
225-
.getATriggerEvent()
226-
.getName() = checkoutTriggers() and
227-
value.regexpMatch(".*(head|branch|ref).*")
222+
exists(string value, Expression expr |
223+
value.regexpMatch(".*(head|branch|ref).*") and expr = this.getArgumentExpr("ref")
228224
|
229-
this.getArgumentExpr("ref").(StepsExpression).getStepId() = value or
230-
this.getArgumentExpr("ref").(StepsExpression).getFieldName() = value or
231-
this.getArgumentExpr("ref").(NeedsExpression).getNeededJobId() = value or
232-
this.getArgumentExpr("ref").(NeedsExpression).getFieldName() = value or
233-
this.getArgumentExpr("ref").(JsonReferenceExpression).getAccessPath() = value or
234-
this.getArgumentExpr("ref").(JsonReferenceExpression).getInnerExpression() = value
225+
expr.(StepsExpression).getStepId() = value or
226+
expr.(SimpleReferenceExpression).getFieldName() = value or
227+
expr.(NeedsExpression).getNeededJobId() = value or
228+
expr.(JsonReferenceExpression).getAccessPath() = value or
229+
expr.(JsonReferenceExpression).getInnerExpression() = value
235230
)
236231
)
237232
}
@@ -247,27 +242,22 @@ class ActionsMutableRefCheckout extends MutableRefCheckoutStep instanceof UsesSt
247242
class ActionsSHACheckout extends SHACheckoutStep instanceof UsesStep {
248243
ActionsSHACheckout() {
249244
this.getCallee() = "actions/checkout" and
245+
//this.getEnclosingJob().getATriggerEvent().getName() = checkoutTriggers() and
250246
(
251247
exists(ActionsSHACheckoutFlow::PathNode source, ActionsSHACheckoutFlow::PathNode sink |
252248
ActionsSHACheckoutFlow::flowPath(source, sink) and
253-
sink.getNode().asExpr() = this.getArgumentExpr(["ref", "repository"])
249+
this.getArgumentExpr(["ref", "repository"]) = sink.getNode().asExpr()
254250
)
255251
or
256252
// heuristic base on the step id and field name
257-
exists(string value |
258-
this.getArgumentExpr("ref")
259-
.(SimpleReferenceExpression)
260-
.getEnclosingJob()
261-
.getATriggerEvent()
262-
.getName() = checkoutTriggers() and
263-
value.regexpMatch(".*(head|sha|commit).*")
253+
exists(string value, Expression expr |
254+
value.regexpMatch(".*(head|sha|commit).*") and expr = this.getArgumentExpr("ref")
264255
|
265-
this.getArgumentExpr("ref").(StepsExpression).getStepId() = value or
266-
this.getArgumentExpr("ref").(StepsExpression).getFieldName() = value or
267-
this.getArgumentExpr("ref").(NeedsExpression).getNeededJobId() = value or
268-
this.getArgumentExpr("ref").(NeedsExpression).getFieldName() = value or
269-
this.getArgumentExpr("ref").(JsonReferenceExpression).getAccessPath() = value or
270-
this.getArgumentExpr("ref").(JsonReferenceExpression).getInnerExpression() = value
256+
expr.(StepsExpression).getStepId() = value or
257+
expr.(SimpleReferenceExpression).getFieldName() = value or
258+
expr.(NeedsExpression).getNeededJobId() = value or
259+
expr.(JsonReferenceExpression).getAccessPath() = value or
260+
expr.(JsonReferenceExpression).getInnerExpression() = value
271261
)
272262
)
273263
}
@@ -283,7 +273,7 @@ class ActionsSHACheckout extends SHACheckoutStep instanceof UsesStep {
283273
class GitMutableRefCheckout extends MutableRefCheckoutStep instanceof Run {
284274
GitMutableRefCheckout() {
285275
exists(string cmd | this.getScript().getACommand() = cmd |
286-
this.getATriggerEvent().getName() = checkoutTriggers() and
276+
//this.getATriggerEvent().getName() = checkoutTriggers() and
287277
cmd.regexpMatch("git\\s+(fetch|pull).*") and
288278
(
289279
(containsHeadRef(cmd) or containsPullRequestNumber(cmd))
@@ -307,7 +297,7 @@ class GitMutableRefCheckout extends MutableRefCheckoutStep instanceof Run {
307297
class GitSHACheckout extends SHACheckoutStep instanceof Run {
308298
GitSHACheckout() {
309299
exists(string cmd | this.getScript().getACommand() = cmd |
310-
this.getATriggerEvent().getName() = checkoutTriggers() and
300+
//this.getATriggerEvent().getName() = checkoutTriggers() and
311301
cmd.regexpMatch("git\\s+(fetch|pull).*") and
312302
(
313303
containsHeadSHA(cmd)
@@ -328,7 +318,7 @@ class GitSHACheckout extends SHACheckoutStep instanceof Run {
328318
class GhMutableRefCheckout extends MutableRefCheckoutStep instanceof Run {
329319
GhMutableRefCheckout() {
330320
exists(string cmd | this.getScript().getACommand() = cmd |
331-
this.getATriggerEvent().getName() = checkoutTriggers() and
321+
//this.getATriggerEvent().getName() = checkoutTriggers() and
332322
cmd.regexpMatch(".*(gh|hub)\\s+pr\\s+checkout.*") and
333323
(
334324
(containsHeadRef(cmd) or containsPullRequestNumber(cmd))
@@ -351,7 +341,7 @@ class GhMutableRefCheckout extends MutableRefCheckoutStep instanceof Run {
351341
class GhSHACheckout extends SHACheckoutStep instanceof Run {
352342
GhSHACheckout() {
353343
exists(string cmd | this.getScript().getACommand() = cmd |
354-
this.getATriggerEvent().getName() = checkoutTriggers() and
344+
//this.getATriggerEvent().getName() = checkoutTriggers() and
355345
cmd.regexpMatch("gh\\s+pr\\s+checkout.*") and
356346
(
357347
containsHeadSHA(cmd)

ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ where
4848
// the checkout occurs in a privileged context
4949
inPrivilegedContext(poisonable, event) and
5050
inPrivilegedContext(checkout, event) and
51+
event.getName() = checkoutTriggers() and
5152
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout")) and
5253
not exists(ControlCheck check | check.protects(poisonable, event, "untrusted-checkout"))
5354
select poisonable, checkout, poisonable,

ql/src/Security/CWE-829/UntrustedCheckoutHigh.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ where
2424
not checkout.getAFollowingStep() instanceof PoisonableStep and
2525
// the checkout occurs in a privileged context
2626
inPrivilegedContext(checkout, event) and
27+
event.getName() = checkoutTriggers() and
2728
(
2829
// issue_comment: check for date comparison checks and actor/access control checks
2930
event.getName() = "issue_comment" and

0 commit comments

Comments
 (0)