mirror of
https://github.com/github/codeql.git
synced 2026-03-20 14:36:46 +01:00
Improve privleged workflow detection
This commit is contained in:
@@ -20,7 +20,7 @@ module Utils {
|
||||
}
|
||||
|
||||
bindingset[str]
|
||||
string trimQuotes(string str) {
|
||||
private string trimQuotes(string str) {
|
||||
result = str.trim().regexpReplaceAll("^(\"|')", "").regexpReplaceAll("(\"|')$", "")
|
||||
}
|
||||
|
||||
@@ -212,6 +212,13 @@ class Workflow extends AstNode instanceof WorkflowImpl {
|
||||
}
|
||||
|
||||
predicate isPrivileged() {
|
||||
// The Workflow has a permission to write to some scope
|
||||
this.getPermissions().getAPermission() = "write" and
|
||||
// The Workflow accesses a secret
|
||||
exists(SecretsExpression expr |
|
||||
expr.getEnclosingWorkflow() = this and not expr.getFieldName() = "GITHUB_TOKEN"
|
||||
)
|
||||
or
|
||||
// The Workflow is triggered by an event other than `pull_request`
|
||||
not this.hasSingleTrigger("pull_request")
|
||||
or
|
||||
@@ -248,7 +255,11 @@ class Outputs extends AstNode instanceof OutputsImpl {
|
||||
override string toString() { result = "Job outputs node" }
|
||||
}
|
||||
|
||||
class Permissions extends AstNode instanceof PermissionsImpl { }
|
||||
class Permissions extends AstNode instanceof PermissionsImpl {
|
||||
string getPermission(string perm) { result = super.getPermission(perm) }
|
||||
|
||||
string getAPermission() { result = super.getAPermission() }
|
||||
}
|
||||
|
||||
class Strategy extends AstNode instanceof StrategyImpl {
|
||||
Expression getMatrixVarExpr(string varName) { result = super.getMatrixVarExpr(varName) }
|
||||
@@ -348,6 +359,8 @@ abstract class SimpleReferenceExpression extends AstNode instanceof SimpleRefere
|
||||
AstNode getTarget() { result = super.getTarget() }
|
||||
}
|
||||
|
||||
class SecretsExpression extends SimpleReferenceExpression instanceof SecretsExpressionImpl { }
|
||||
|
||||
class StepsExpression extends SimpleReferenceExpression instanceof StepsExpressionImpl {
|
||||
string getStepId() { result = super.getStepId() }
|
||||
}
|
||||
|
||||
@@ -484,6 +484,10 @@ class PermissionsImpl extends AstNodeImpl, TPermissionsNode {
|
||||
override Location getLocation() { result = n.getLocation() }
|
||||
|
||||
override YamlMapping getNode() { result = n }
|
||||
|
||||
string getPermission(string perm) { result = n.lookup(perm).(YamlScalar).getValue() }
|
||||
|
||||
string getAPermission() { result = this.getPermission(_) }
|
||||
}
|
||||
|
||||
class StrategyImpl extends AstNodeImpl, TStrategyNode {
|
||||
@@ -851,6 +855,25 @@ private string inputsCtxRegex() {
|
||||
Utils::wrapRegexp(["inputs\\.([A-Za-z0-9_-]+)", "github\\.event\\.inputs\\.([A-Za-z0-9_-]+)"])
|
||||
}
|
||||
|
||||
private string secretsCtxRegex() { result = Utils::wrapRegexp("secrets\\.([A-Za-z0-9_-]+)") }
|
||||
|
||||
/**
|
||||
* Holds for an expression accesing the `secrets` context.
|
||||
* e.g. `${{ secrets.FOO }}`
|
||||
*/
|
||||
class SecretsExpressionImpl extends SimpleReferenceExpressionImpl {
|
||||
string fieldName;
|
||||
|
||||
SecretsExpressionImpl() {
|
||||
Utils::normalizeExpr(expression).regexpMatch(secretsCtxRegex()) and
|
||||
fieldName = Utils::normalizeExpr(expression).regexpCapture(secretsCtxRegex(), 1)
|
||||
}
|
||||
|
||||
override string getFieldName() { result = fieldName }
|
||||
|
||||
override AstNodeImpl getTarget() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for an expression accesing the `steps` context.
|
||||
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @security-severity 9.3
|
||||
* @security-severity 5.0
|
||||
* @id actions/artifact-poisoning
|
||||
* @tags actions
|
||||
* security
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
contents: read
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
echo_trigger:
|
||||
|
||||
Reference in New Issue
Block a user