mirror of
https://github.com/github/codeql.git
synced 2025-12-28 22:56:32 +01:00
Support RunExpr's env vars
This commit is contained in:
@@ -169,6 +169,13 @@ class RunExpr extends StepStmt, Expression {
|
||||
|
||||
Expression getScriptExpr() { result = scriptExpr }
|
||||
|
||||
Expression getEnvExpr(string name) {
|
||||
exists(Actions::StepEnv env |
|
||||
env.getStep() = this and
|
||||
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
|
||||
)
|
||||
}
|
||||
|
||||
string getScript() { result = scriptExpr.getValue() }
|
||||
}
|
||||
|
||||
@@ -183,6 +190,7 @@ class ExprAccessExpr extends Expression instanceof YamlString {
|
||||
string getExpression() { result = expr }
|
||||
|
||||
JobStmt getJob() { result.getAChildNode*() = this }
|
||||
//override string toString() { result = expr }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -171,8 +171,18 @@ private class UsesTree extends StandardPreOrderTree instanceof UsesExpr {
|
||||
}
|
||||
|
||||
private class RunTree extends StandardPreOrderTree instanceof RunExpr {
|
||||
override ControlFlowTree getChildNode(int i) { result = super.getScriptExpr() and i = 0 }
|
||||
//override ControlFlowTree getChildNode(int i) { result = super.getScriptExpr() and i = 0 }
|
||||
override ControlFlowTree getChildNode(int i) {
|
||||
result =
|
||||
rank[i](Expression child, Location l |
|
||||
(child = super.getEnvExpr(_) or child = super.getScriptExpr()) and
|
||||
l = child.getLocation()
|
||||
|
|
||||
child
|
||||
order by
|
||||
l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine(), child.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ExprAccessTree extends LeafTree instanceof ExprAccessExpr { }
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ class AdditionalTaintStep extends Unit {
|
||||
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if actions-find-and-replace-string step is used.
|
||||
*/
|
||||
private class ActionsFindAndReplaceStringStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(UsesExpr u |
|
||||
@@ -29,3 +32,32 @@ private class ActionsFindAndReplaceStringStep extends AdditionalTaintStep {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a Run step declares an environment variable, uses it in its script and sets an output in its script.
|
||||
* e.g.
|
||||
* - name: Extract and Clean Initial URL
|
||||
* id: extract-url
|
||||
* env:
|
||||
* BODY: ${{ github.event.comment.body }}
|
||||
* run: |
|
||||
* INITIAL_URL=$(echo "$BODY" | grep -o 'https://github.com/github/release-assets/assets/[^ >]*')
|
||||
* echo "Cleaned Initial URL: $INITIAL_URL"
|
||||
* echo "::set-output name=initial_url::$INITIAL_URL"
|
||||
*/
|
||||
private class RunEnvToScriptStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) { test(pred, succ) }
|
||||
}
|
||||
|
||||
predicate test(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(RunExpr r, string varName |
|
||||
r.getEnvExpr(varName) = pred.asExpr() and
|
||||
exists(string script, string line |
|
||||
script = r.getScript() and
|
||||
line = script.splitAt("\n") and
|
||||
line.regexpMatch(".*::set-output\\s+name.*") and
|
||||
script.indexOf("$" + ["", "{", "ENV{"] + varName) > 0
|
||||
) and
|
||||
succ.asExpr() = r
|
||||
)
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos =
|
||||
*/
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { localFlowStep(nodeFrom, nodeTo) }
|
||||
|
||||
predicate stepOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
predicate usesOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
// nodeTo is an OutputVarAccessExpr scoped with the namespace of the nodeFrom Step output
|
||||
exists(UsesExpr uses, StepOutputAccessExpr outputRead |
|
||||
uses = nodeFrom.asExpr() and
|
||||
@@ -207,6 +207,16 @@ predicate stepOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate runOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
// nodeTo is an OutputVarAccessExpr scoped with the namespace of the nodeFrom Step output
|
||||
exists(RunExpr uses, StepOutputAccessExpr outputRead |
|
||||
uses = nodeFrom.asExpr() and
|
||||
outputRead = nodeTo.asExpr() and
|
||||
outputRead.getStepId() = uses.getId() and
|
||||
uses.getJob() = outputRead.getJob()
|
||||
)
|
||||
}
|
||||
|
||||
predicate jobOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
// nodeTo is a JobOutputAccessExpr and nodeFrom is the Job output expression
|
||||
exists(Expression astFrom, JobOutputAccessExpr astTo |
|
||||
@@ -223,7 +233,8 @@ predicate jobOutputDefToUse(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
stepOutputDefToUse(nodeFrom, nodeTo) or
|
||||
usesOutputDefToUse(nodeFrom, nodeTo) or
|
||||
runOutputDefToUse(nodeFrom, nodeTo) or
|
||||
jobOutputDefToUse(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user