-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathSpoofableActorCheck.ql
More file actions
50 lines (47 loc) · 1.67 KB
/
SpoofableActorCheck.ql
File metadata and controls
50 lines (47 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* @name Spoofable actor check used as security control
* @description Checking `github.actor` or `github.triggering_actor` against a bot name
* is spoofable and should not be used as a security control.
* @kind problem
* @precision high
* @security-severity 7.0
* @problem.severity warning
* @id actions/spoofable-actor-check
* @tags actions
* security
* experimental
* external/cwe/cwe-290
*/
import actions
/**
* Holds if `ifNode` contains a spoofable bot actor check.
*
* Matches conditions like:
* `github.actor == 'dependabot[bot]'`
* `github.triggering_actor == 'renovate[bot]'`
* `'dependabot[bot]' == github.actor`
*
* These are spoofable because `github.actor` refers to the last actor
* to act on the triggering context, not necessarily the actor that
* caused the trigger.
*/
predicate isSpoofableBotCheck(If ifNode) {
exists(string cond |
cond = normalizeExpr(ifNode.getCondition()) and
(
// github.actor == 'something[bot]' or github.triggering_actor == 'something[bot]'
cond.regexpMatch("(?s).*\\bgithub\\.(actor|triggering_actor)\\s*==\\s*'[^']*\\[bot\\][^']*'.*")
or
// reversed: 'something[bot]' == github.actor
cond.regexpMatch("(?s).*'[^']*\\[bot\\][^']*'\\s*==\\s*github\\.(actor|triggering_actor)\\b.*")
)
)
}
from If ifNode, Event event
where
isSpoofableBotCheck(ifNode) and
event = ifNode.getATriggerEvent() and
event.isExternallyTriggerable()
select ifNode,
"This condition checks `github.actor` against a bot name, which is spoofable on $@ triggers. Use `github.event.pull_request.user.login` or similar non-spoofable context instead.",
event, event.getName()