Merge pull request #30 from GitHubSecurityLab/untrusted_co

Improve UntrustedCheckout query
This commit is contained in:
Alvaro Muñoz
2024-03-14 14:52:39 +01:00
committed by GitHub
32 changed files with 822 additions and 155 deletions

View File

@@ -1,6 +1,16 @@
private import codeql.actions.ast.internal.Ast
private import codeql.Locations
module Utils {
bindingset[expr]
string normalizeExpr(string expr) {
result =
expr.regexpReplaceAll("\\['([a-zA-Z0-9_\\*\\-]+)'\\]", ".$1")
.regexpReplaceAll("\\[\"([a-zA-Z0-9_\\*\\-]+)\"\\]", ".$1")
.regexpReplaceAll("\\s*\\.\\s*", ".")
}
}
class AstNode instanceof AstNodeImpl {
AstNode getAChildNode() { result = super.getAChildNode() }
@@ -33,6 +43,8 @@ class Expression extends AstNode instanceof ExpressionImpl {
string getExpression() { result = expression }
string getRawExpression() { result = rawExpression }
string getNormalizedExpression() { result = Utils::normalizeExpr(expression) }
}
/** A common class for `env` in workflow, job or step. */
@@ -188,6 +200,8 @@ class Step extends AstNode instanceof StepImpl {
*/
class If extends AstNode instanceof IfImpl {
string getCondition() { result = super.getCondition() }
Expression getConditionExpr() { result = super.getConditionExpr() }
}
abstract class Uses extends AstNode instanceof UsesImpl {
@@ -212,20 +226,22 @@ class Run extends Step instanceof RunImpl {
Expression getAnScriptExpr() { result = super.getAnScriptExpr() }
}
abstract class ContextExpression extends AstNode instanceof ContextExpressionImpl {
abstract class SimpleReferenceExpression extends AstNode instanceof SimpleReferenceExpressionImpl {
string getFieldName() { result = super.getFieldName() }
AstNode getTarget() { result = super.getTarget() }
}
class StepsExpression extends ContextExpression instanceof StepsExpressionImpl { }
class StepsExpression extends SimpleReferenceExpression instanceof StepsExpressionImpl {
string getStepId() { result = super.getStepId() }
}
class NeedsExpression extends ContextExpression instanceof NeedsExpressionImpl { }
class NeedsExpression extends SimpleReferenceExpression instanceof NeedsExpressionImpl { }
class JobsExpression extends ContextExpression instanceof JobsExpressionImpl { }
class JobsExpression extends SimpleReferenceExpression instanceof JobsExpressionImpl { }
class InputsExpression extends ContextExpression instanceof InputsExpressionImpl { }
class InputsExpression extends SimpleReferenceExpression instanceof InputsExpressionImpl { }
class EnvExpression extends ContextExpression instanceof EnvExpressionImpl { }
class EnvExpression extends SimpleReferenceExpression instanceof EnvExpressionImpl { }
class MatrixExpression extends ContextExpression instanceof MatrixExpressionImpl { }
class MatrixExpression extends SimpleReferenceExpression instanceof MatrixExpressionImpl { }

View File

@@ -1,5 +1,6 @@
private import codeql.actions.ast.internal.Yaml
private import codeql.Locations
private import codeql.actions.Ast::Utils as Utils
/**
* Gets the length of each line in the StringValue .
@@ -18,24 +19,19 @@ int partialLineLengthSum(string text, int i) {
result = sum(int j, int length | j in [0 .. i] and length = lineLength(text, j) | length)
}
/**
* Holds if `${{ e }}` is a GitHub Actions expression evaluated within this YAML string.
* See https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions.
* Only finds simple expressions like `${{ github.event.comment.body }}`, where the expression contains only alphanumeric characters, underscores, dots, or dashes.
* Does not identify more complicated expressions like `${{ fromJSON(env.time) }}`, or ${{ format('{{Hello {0}!}}', github.event.head_commit.author.name) }}
*/
string getASimpleReferenceExpression(YamlString s, int offset) {
string getADelimitedExpression(YamlString s, int offset) {
// We use `regexpFind` to obtain *all* matches of `${{...}}`,
// not just the last (greedy match) or first (reluctant match).
result =
s.getValue()
.regexpFind("\\$\\{\\{\\s*[A-Za-z0-9_\\[\\]\\*\\(\\)\\.\\-]+\\s*\\}\\}", _, offset)
.regexpCapture("(\\$\\{\\{\\s*[A-Za-z0-9_\\[\\]\\*\\((\\)\\.\\-]+\\s*\\}\\})", 1)
.regexpFind("\\$\\{\\{(?:[^}]|}(?!}))*\\}\\}", _, offset)
.regexpCapture("(\\$\\{\\{(?:[^}]|}(?!}))*\\}\\})", 1)
.trim()
}
private newtype TAstNode =
TExpressionNode(YamlNode key, YamlScalar value, string raw, int exprOffset) {
raw = getASimpleReferenceExpression(value, exprOffset) and
raw = getADelimitedExpression(value, exprOffset) and
exists(YamlMapping m |
(
exists(int i | value = m.getValueNode(i) and key = m.getKeyNode(i))
@@ -45,6 +41,14 @@ private newtype TAstNode =
)
)
)
or
// `if`'s conditions do not need to be delimted with ${{}}
exists(YamlMapping m |
m.maps(key, value) and
key.(YamlScalar).getValue() = ["if"] and
value.getValue() = raw and
exprOffset = 1
)
} or
TCompositeAction(YamlMapping n) {
n instanceof YamlDocument and
@@ -123,7 +127,7 @@ class ScalarValueImpl extends AstNodeImpl, TScalarValueNode {
override Location getLocation() { result = value.getLocation() }
override YamlNode getNode() { result = value }
override YamlScalar getNode() { result = value }
}
class ExpressionImpl extends AstNodeImpl, TExpressionNode {
@@ -135,15 +139,16 @@ class ExpressionImpl extends AstNodeImpl, TExpressionNode {
ExpressionImpl() {
this = TExpressionNode(key, value, rawExpression, exprOffset - 1) and
expression =
rawExpression.regexpCapture("\\$\\{\\{\\s*([A-Za-z0-9_\\[\\]\\*\\((\\)\\.\\-]+)\\s*\\}\\}", 1)
if rawExpression.trim().regexpMatch("\\$\\{\\{.*\\}\\}")
then expression = rawExpression.trim().regexpCapture("\\$\\{\\{\\s*(.*)\\s*\\}\\}", 1).trim()
else expression = rawExpression.trim()
}
override string toString() { result = expression }
override AstNodeImpl getAChildNode() { none() }
override AstNodeImpl getParentNode() { result.getNode() = value }
override ScalarValueImpl getParentNode() { result.getNode() = value }
override string getAPrimaryQlClass() { result = "ExpressionNode" }
@@ -638,6 +643,9 @@ class IfImpl extends AstNodeImpl, TIfNode {
/** Gets the condition that must be satisfied for this job to run. */
string getCondition() { result = n.(YamlScalar).getValue() }
/** Gets the condition that must be satisfied for this job to run. */
ExpressionImpl getConditionExpr() { result.getParentNode().getNode() = n }
}
class EnvImpl extends AstNodeImpl, TEnvNode {
@@ -776,11 +784,29 @@ class RunImpl extends StepImpl {
}
}
/**
* Holds if `${{ e }}` is a GitHub Actions expression evaluated within this YAML string.
* See https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions.
* Only finds simple expressions like `${{ github.event.comment.body }}`, where the expression contains only alphanumeric characters, underscores, dots, or dashes.
* Does not identify more complicated expressions like `${{ fromJSON(env.time) }}`, or ${{ format('{{Hello {0}!}}', github.event.head_commit.author.name) }}
*/
bindingset[s]
string getASimpleReferenceExpression(string s, int offset) {
// We use `regexpFind` to obtain *all* matches of `${{...}}`,
// not just the last (greedy match) or first (reluctant match).
result =
s.trim()
.regexpFind("[A-Za-z0-9'\"_\\[\\]\\*\\(\\)\\.\\-]+", _, offset)
.regexpCapture("([A-Za-z0-9'\"_\\[\\]\\*\\(\\)\\.\\-]+)", 1)
}
/**
* A ${{}} expression accessing a context variable such as steps, needs, jobs, env, inputs, or matrix.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
*/
abstract class ContextExpressionImpl extends ExpressionImpl {
abstract class SimpleReferenceExpressionImpl extends ExpressionImpl {
SimpleReferenceExpressionImpl() { exists(getASimpleReferenceExpression(expression, _)) }
abstract string getFieldName();
abstract AstNodeImpl getTarget();
@@ -816,22 +842,24 @@ private string wrapRegexp(string regex) {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ steps.changed-files.outputs.all_changed_files }}`
*/
class StepsExpressionImpl extends ContextExpressionImpl {
class StepsExpressionImpl extends SimpleReferenceExpressionImpl {
string stepId;
string fieldName;
StepsExpressionImpl() {
expression.regexpMatch(stepsCtxRegex()) and
stepId = expression.regexpCapture(stepsCtxRegex(), 1) and
fieldName = expression.regexpCapture(stepsCtxRegex(), 2)
Utils::normalizeExpr(expression).regexpMatch(stepsCtxRegex()) and
stepId = Utils::normalizeExpr(expression).regexpCapture(stepsCtxRegex(), 1) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(stepsCtxRegex(), 2)
}
override string getFieldName() { result = fieldName }
override AstNodeImpl getTarget() {
this.getLocation().getFile() = result.getLocation().getFile() and
this.getEnclosingJob() = result.getEnclosingJob() and
result.(StepImpl).getId() = stepId
}
string getStepId() { result = stepId }
}
/**
@@ -839,21 +867,24 @@ class StepsExpressionImpl extends ContextExpressionImpl {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ needs.job1.outputs.foo}}`
*/
class NeedsExpressionImpl extends ContextExpressionImpl {
class NeedsExpressionImpl extends SimpleReferenceExpressionImpl {
JobImpl neededJob;
string fieldName;
NeedsExpressionImpl() {
expression.regexpMatch(needsCtxRegex()) and
fieldName = expression.regexpCapture(needsCtxRegex(), 2) and
neededJob.getId() = expression.regexpCapture(needsCtxRegex(), 1) and
Utils::normalizeExpr(expression).regexpMatch(needsCtxRegex()) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(needsCtxRegex(), 2) and
neededJob.getId() = Utils::normalizeExpr(expression).regexpCapture(needsCtxRegex(), 1) and
neededJob.getLocation().getFile() = this.getLocation().getFile()
}
override string getFieldName() { result = fieldName }
override AstNodeImpl getTarget() {
this.getEnclosingJob().getANeededJob() = neededJob and
(
this.getEnclosingJob().getANeededJob() = neededJob or
this.getEnclosingJob() = neededJob
) and
(
// regular jobs
neededJob.getOutputs() = result
@@ -869,14 +900,14 @@ class NeedsExpressionImpl extends ContextExpressionImpl {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ jobs.job1.outputs.foo}}` (within reusable workflows)
*/
class JobsExpressionImpl extends ContextExpressionImpl {
class JobsExpressionImpl extends SimpleReferenceExpressionImpl {
string jobId;
string fieldName;
JobsExpressionImpl() {
expression.regexpMatch(jobsCtxRegex()) and
jobId = expression.regexpCapture(jobsCtxRegex(), 1) and
fieldName = expression.regexpCapture(jobsCtxRegex(), 2)
Utils::normalizeExpr(expression).regexpMatch(jobsCtxRegex()) and
jobId = Utils::normalizeExpr(expression).regexpCapture(jobsCtxRegex(), 1) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(jobsCtxRegex(), 2)
}
override string getFieldName() { result = fieldName }
@@ -895,12 +926,12 @@ class JobsExpressionImpl extends ContextExpressionImpl {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ inputs.foo }}`
*/
class InputsExpressionImpl extends ContextExpressionImpl {
class InputsExpressionImpl extends SimpleReferenceExpressionImpl {
string fieldName;
InputsExpressionImpl() {
expression.regexpMatch(inputsCtxRegex()) and
fieldName = expression.regexpCapture(inputsCtxRegex(), 1)
Utils::normalizeExpr(expression).regexpMatch(inputsCtxRegex()) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(inputsCtxRegex(), 1)
}
override string getFieldName() { result = fieldName }
@@ -920,12 +951,12 @@ class InputsExpressionImpl extends ContextExpressionImpl {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ env.foo }}`
*/
class EnvExpressionImpl extends ContextExpressionImpl {
class EnvExpressionImpl extends SimpleReferenceExpressionImpl {
string fieldName;
EnvExpressionImpl() {
expression.regexpMatch(envCtxRegex()) and
fieldName = expression.regexpCapture(envCtxRegex(), 1)
Utils::normalizeExpr(expression).regexpMatch(envCtxRegex()) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(envCtxRegex(), 1)
}
override string getFieldName() { result = fieldName }
@@ -943,12 +974,12 @@ class EnvExpressionImpl extends ContextExpressionImpl {
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ matrix.foo }}`
*/
class MatrixExpressionImpl extends ContextExpressionImpl {
class MatrixExpressionImpl extends SimpleReferenceExpressionImpl {
string fieldName;
MatrixExpressionImpl() {
expression.regexpMatch(matrixCtxRegex()) and
fieldName = expression.regexpCapture(matrixCtxRegex(), 1)
Utils::normalizeExpr(expression).regexpMatch(matrixCtxRegex()) and
fieldName = Utils::normalizeExpr(expression).regexpCapture(matrixCtxRegex(), 1)
}
override string getFieldName() { result = fieldName }

View File

@@ -1,6 +1,6 @@
private import internal.ExternalFlowExtensions as Extensions
import codeql.actions.DataFlow
import actions
private import codeql.actions.DataFlow
private import actions
/**
* MaD sources

View File

@@ -1,6 +1,7 @@
import actions
import codeql.actions.DataFlow
import codeql.actions.dataflow.ExternalFlow
private import actions
private import codeql.actions.DataFlow
private import codeql.actions.dataflow.ExternalFlow
private import codeql.actions.Ast::Utils as Utils
/**
* A data flow source.
@@ -24,8 +25,11 @@ abstract class RemoteFlowSource extends SourceNode {
bindingset[context]
private predicate isExternalUserControlledIssue(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*issue\\s*\\.\\s*title\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*issue\\s*\\.\\s*body\\b")
exists(string reg |
reg = ["\\bgithub\\.event\\.issue\\.title\\b", "\\bgithub\\.event\\.issue\\.body\\b"]
|
Utils::normalizeExpr(context).regexpMatch(reg)
)
}
bindingset[context]
@@ -33,35 +37,39 @@ private predicate isExternalUserControlledPullRequest(string context) {
exists(string reg |
reg =
[
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*title\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*body\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*label\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*repo\\s*\\.\\s*default_branch\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*repo\\s*\\.\\s*description\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*repo\\s*\\.\\s*homepage\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*ref\\b",
"\\bgithub\\s*\\.\\s*head_ref\\b"
"\\bgithub\\.event\\.pull_request\\.title\\b", "\\bgithub\\.event\\.pull_request\\.body\\b",
"\\bgithub\\.event\\.pull_request\\.head\\.label\\b",
"\\bgithub\\.event\\.pull_request\\.head\\.repo\\.default_branch\\b",
"\\bgithub\\.event\\.pull_request\\.head\\.repo\\.description\\b",
"\\bgithub\\.event\\.pull_request\\.head\\.repo\\.homepage\\b",
"\\bgithub\\.event\\.pull_request\\.head\\.ref\\b", "\\bgithub\\.head_ref\\b"
]
|
context.regexpMatch(reg)
Utils::normalizeExpr(context).regexpMatch(reg)
)
}
bindingset[context]
private predicate isExternalUserControlledReview(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*review\\s*\\.\\s*body\\b")
Utils::normalizeExpr(context).regexpMatch("\\bgithub\\.event\\.review\\.body\\b")
}
bindingset[context]
private predicate isExternalUserControlledComment(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*comment\\s*\\.\\s*body\\b")
Utils::normalizeExpr(context).regexpMatch("\\bgithub\\.event\\.comment\\.body\\b")
}
bindingset[context]
private predicate isExternalUserControlledGollum(string context) {
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pages\\[[0-9]+\\]\\s*\\.\\s*page_name\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pages\\[[0-9]+\\]\\s*\\.\\s*title\\b")
exists(string reg |
reg =
[
"\\bgithub\\.event\\.pages\\[[0-9]+\\]\\.page_name\\b",
"\\bgithub\\.event\\.pages\\[[0-9]+\\]\\.title\\b"
]
|
Utils::normalizeExpr(context).regexpMatch(reg)
)
}
bindingset[context]
@@ -69,26 +77,29 @@ private predicate isExternalUserControlledCommit(string context) {
exists(string reg |
reg =
[
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits\\[[0-9]+\\]\\s*\\.\\s*message\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*message\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*author\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*author\\s*\\.\\s*name\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*committer\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*committer\\s*\\.\\s*name\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits\\[[0-9]+\\]\\s*\\.\\s*author\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits\\[[0-9]+\\]\\s*\\.\\s*author\\s*\\.\\s*name\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits\\[[0-9]+\\]\\s*\\.\\s*committer\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits\\[[0-9]+\\]\\s*\\.\\s*committer\\s*\\.\\s*name\\b",
"\\bgithub\\.event\\.commits\\[[0-9]+\\]\\.message\\b",
"\\bgithub\\.event\\.head_commit\\.message\\b",
"\\bgithub\\.event\\.head_commit\\.author\\.email\\b",
"\\bgithub\\.event\\.head_commit\\.author\\.name\\b",
"\\bgithub\\.event\\.head_commit\\.committer\\.email\\b",
"\\bgithub\\.event\\.head_commit\\.committer\\.name\\b",
"\\bgithub\\.event\\.commits\\[[0-9]+\\]\\.author\\.email\\b",
"\\bgithub\\.event\\.commits\\[[0-9]+\\]\\.author\\.name\\b",
"\\bgithub\\.event\\.commits\\[[0-9]+\\]\\.committer\\.email\\b",
"\\bgithub\\.event\\.commits\\[[0-9]+\\]\\.committer\\.name\\b",
]
|
context.regexpMatch(reg)
Utils::normalizeExpr(context).regexpMatch(reg)
)
}
bindingset[context]
private predicate isExternalUserControlledDiscussion(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*discussion\\s*\\.\\s*title\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*discussion\\s*\\.\\s*body\\b")
exists(string reg |
reg = ["\\bgithub\\.event\\.discussion\\.title\\b", "\\bgithub\\.event\\.discussion\\.body\\b"]
|
Utils::normalizeExpr(context).regexpMatch(reg)
)
}
bindingset[context]
@@ -96,18 +107,18 @@ private predicate isExternalUserControlledWorkflowRun(string context) {
exists(string reg |
reg =
[
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow\\s*\\.\\s*path\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_branch\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*display_title\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_repository\\b\\s*\\.\\s*description\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_commit\\b\\s*\\.\\s*message\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_commit\\b\\s*\\.\\s*author\\b\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_commit\\b\\s*\\.\\s*author\\b\\s*\\.\\s*name\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_commit\\b\\s*\\.\\s*committer\\b\\s*\\.\\s*email\\b",
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*workflow_run\\s*\\.\\s*head_commit\\b\\s*\\.\\s*committer\\b\\s*\\.\\s*name\\b",
"\\bgithub\\.event\\.workflow\\.path\\b",
"\\bgithub\\.event\\.workflow_run\\.head_branch\\b",
"\\bgithub\\.event\\.workflow_run\\.display_title\\b",
"\\bgithub\\.event\\.workflow_run\\.head_repository\\.description\\b",
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.message\\b",
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.author\\.email\\b",
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.author\\.name\\b",
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.committer\\.email\\b",
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.committer\\.name\\b",
]
|
context.regexpMatch(reg)
Utils::normalizeExpr(context).regexpMatch(reg)
)
}

View File

@@ -2,10 +2,10 @@
* Provides classes representing various flow steps for taint tracking.
*/
import actions
private import actions
private import codeql.util.Unit
private import codeql.actions.DataFlow
import codeql.actions.dataflow.ExternalFlow
private import codeql.actions.dataflow.ExternalFlow
/**
* A unit class for adding additional taint steps.

View File

@@ -271,7 +271,7 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) { none() }
* Holds if a Expression reads a field from a job (needs/jobs), step (steps) output via a read of `c` (fieldname)
*/
predicate ctxFieldReadStep(Node node1, Node node2, ContentSet c) {
exists(ContextExpression access |
exists(SimpleReferenceExpression access |
(
access instanceof NeedsExpression or
access instanceof StepsExpression or

View File

@@ -174,3 +174,17 @@ class FieldContent extends Content, TFieldContent {
override string toString() { result = name }
}
predicate hasLocalFlow(Node n1, Node n2) {
n1 = n2 or
simpleLocalFlowStep(n1, n2) or
exists(ContentSet c | ctxFieldReadStep(n1, n2, c))
}
predicate hasLocalFlowExpr(AstNode n1, AstNode n2) {
exists(Node dn1, Node dn2 |
dn1.asExpr() = n1 and
dn2.asExpr() = n2 and
hasLocalFlow(dn1, dn2)
)
}

View File

@@ -8,6 +8,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import PartialFlow::PartialPathGraph

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -12,6 +12,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -13,6 +13,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -13,6 +13,7 @@
*/
import actions
import codeql.actions.DataFlow
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow

View File

@@ -14,40 +14,121 @@
*/
import actions
import codeql.actions.DataFlow
/**
* An If node that contains an `actor` check
*/
class ActorCheck extends If {
ActorCheck() {
this.getCondition().regexpMatch(".*github\\.(triggering_)?actor.*") or
this.getCondition().regexpMatch(".*github\\.event\\.pull_request\\.user\\.login.*")
/** An If node that contains an actor, user or label check */
class ControlCheck extends If {
ControlCheck() {
exists(
Utils::normalizeExpr(this.getCondition())
.regexpFind([
"\\bgithub\\.actor\\b", // actor
"\\bgithub\\.triggering_actor\\b", // actor
"\\bgithub\\.event\\.comment\\.user\\.login\\b", //user
"\\bgithub\\.event\\.pull_request\\.user\\.login\\b", //user
"\\bgithub\\.event\\.pull_request\\.labels\\b", // label
"\\bgithub\\.event\\.label\\.name\\b" // label
], _, _)
)
}
}
/**
* An If node that contains a `label` check
*/
class LabelCheck extends If {
LabelCheck() {
this.getCondition().regexpMatch(".*github\\.event\\.pull_request\\.labels.*") or
this.getCondition().regexpMatch(".*github\\.event\\.label\\.name.*")
bindingset[s]
predicate containsHeadRef(string s) {
exists(
Utils::normalizeExpr(s)
.regexpFind([
"\\bgithub\\.event\\.number\\b", // The pull request number.
"\\bgithub\\.event\\.issue\\.number\\b", // The pull request number on issue_comment.
"\\bgithub\\.event\\.pull_request\\.head\\.ref\\b", // The ref name of head.
"\\bgithub\\.event\\.pull_request\\.head\\.sha\\b", // The commit SHA of head.
"\\bgithub\\.event\\.pull_request\\.id\\b", // The pull request ID.
"\\bgithub\\.event\\.pull_request\\.number\\b", // The pull request number.
"\\bgithub\\.event\\.pull_request\\.merge_commit_sha\\b", // The SHA of the merge commit.
"\\bgithub\\.head_ref\\b", // The head_ref or source branch of the pull request in a workflow run.
"\\bgithub\\.event\\.workflow_run\\.head_branch\\b", // The branch of the head commit.
"\\bgithub\\.event\\.workflow_run\\.head_commit\\.id\\b", // The SHA of the head commit.
"\\bgithub\\.event\\.workflow_run\\.head_sha\\b", // The SHA of the head commit.
"\\benv\\.GITHUB_HEAD_REF\\b", "\\bgithub\\.event\\.check_suite\\.after\\b",
"\\bgithub\\.event\\.check_suite\\.head_sha\\b",
"\\bgithub\\.event\\.check_suite\\.pull_requests\\[\\d+\\]\\.head\\.ref\\b",
"\\bgithub\\.event\\.check_suite\\.pull_requests\\[\\d+\\]\\.head\\.sha\\b",
"\\bgithub\\.event\\.check_suite\\.pull_requests\\[\\d+\\]\\.id\\b",
"\\bgithub\\.event\\.check_suite\\.pull_requests\\[\\d+\\]\\.number\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.after\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.head_sha\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.pull_requests\\[\\d+\\]\\.head\\.ref\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.pull_requests\\[\\d+\\]\\.head\\.sha\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.pull_requests\\[\\d+\\]\\.id\\b",
"\\bgithub\\.event\\.check_run\\.check_suite\\.pull_requests\\[\\d+\\]\\.number\\b",
"\\bgithub\\.event\\.check_run\\.head_sha\\b",
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.head\\.ref\\b",
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.head\\.sha\\b",
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.id\\b",
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.number\\b",
"\\bhead\\.sha\\b", "\\bhead\\.ref\\b"
], _, _)
)
}
/** Checkout of a Pull Request HEAD ref */
abstract class PRHeadCheckoutStep extends Step { }
/** Checkout of a Pull Request HEAD ref using actions/checkout action */
class ActionsCheckout extends PRHeadCheckoutStep instanceof UsesStep {
ActionsCheckout() {
this.getCallee() = "actions/checkout" and
(
// ref argument contains the head ref
exists(Expression e |
containsHeadRef(e.getExpression()) and
DataFlow::hasLocalFlowExpr(e, this.getArgumentExpr("ref"))
)
or
// 3rd party actions returning the PR head sha/ref
exists(UsesStep head |
head.getCallee() = ["eficode/resolve-pr-refs", "xt0rted/pull-request-comment-branch"] and
DataFlow::hasLocalFlowExpr(head, this.getArgumentExpr("ref"))
)
or
// heuristic base on the step id and field name
exists(StepsExpression e |
this.getArgumentExpr("ref") = e and
(
e.getStepId().matches(["%sha%", "%head%", "branch"]) or
e.getFieldName().matches(["%sha%", "%head%", "branch"])
)
)
)
}
}
from Workflow w, LocalJob job, UsesStep checkoutStep
/** Checkout of a Pull Request HEAD ref using git within a Run step */
class GitCheckout extends PRHeadCheckoutStep instanceof Run {
GitCheckout() {
exists(string line |
this.getScript().splitAt("\n") = line and
line.regexpMatch(".*git\\s+fetch.*") and
(
containsHeadRef(line)
or
exists(string varname |
containsHeadRef(this.getInScopeEnvVarExpr(varname).getExpression()) and
exists(line.regexpFind(varname, _, _))
)
)
)
}
}
from Workflow w, PRHeadCheckoutStep checkout
where
w.hasTriggerEvent("pull_request_target") and
w.getAJob() = job and
job.getAStep() = checkoutStep and
checkoutStep.getCallee() = "actions/checkout" and
checkoutStep
.getArgumentExpr("ref")
.getExpression()
.matches([
"%github.event.pull_request.head.ref%", "%github.event.pull_request.head.sha%",
"%github.event.pull_request.number%", "%github.event.number%", "%github.head_ref%"
]) and
not exists(ActorCheck check | job.getIf() = check or checkoutStep.getIf() = check) and
not exists(LabelCheck check | job.getIf() = check or checkoutStep.getIf() = check)
select checkoutStep, "Potential unsafe checkout of untrusted pull request on 'pull_request_target'."
w.hasTriggerEvent([
"pull_request_target", "issue_comment", "pull_request_review_comment", "pull_request_review",
"workflow_run", "check_run", "check_suite", "workflow_call"
]) and
w.getAJob().(LocalJob).getAStep() = checkout and
not exists(ControlCheck check |
checkout.getIf() = check or checkout.getEnclosingJob().getIf() = check
)
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."

View File

@@ -190,7 +190,7 @@ parentNodes
| .github/workflows/test.yml:34:9:34:23 | ${{ always() }} | .github/workflows/test.yml:34:9:34:23 | ${{ always() }} |
| .github/workflows/test.yml:34:9:34:23 | ${{ always() }} | .github/workflows/test.yml:34:9:34:23 | ${{ always() }} |
| .github/workflows/test.yml:34:10:34:24 | always() | .github/workflows/test.yml:34:9:34:23 | ${{ always() }} |
| .github/workflows/test.yml:34:10:34:24 | always() | .github/workflows/test.yml:34:9:34:23 | ${{ always() }} |
| .github/workflows/test.yml:34:11:34:25 | always() | .github/workflows/test.yml:34:9:34:23 | ${{ always() }} |
| .github/workflows/test.yml:36:12:36:15 | job1 | .github/workflows/test.yml:1:1:40:53 | on: push |
| .github/workflows/test.yml:36:12:36:15 | job1 | .github/workflows/test.yml:32:5:40:53 | Job: job2 |
| .github/workflows/test.yml:36:12:36:15 | job1 | .github/workflows/test.yml:32:5:40:53 | Job: job2 |
@@ -415,3 +415,8 @@ calls
| .github/workflows/test.yml:19:9:26:6 | Uses Step: step | mad9000/actions-find-and-replace-string |
needs
| .github/workflows/test.yml:40:20:40:53 | needs.job1.outputs.job_output |
testNormalizeExpr
| foo['bar'] == baz | foo.bar == baz |
| github.event.pull_request.user["login"] | github.event.pull_request.user.login |
| github.event.pull_request.user['login'] | github.event.pull_request.user.login |
| github.event.pull_request['user']['login'] | github.event.pull_request.user.login |

View File

@@ -1,4 +1,5 @@
import codeql.actions.Ast
import codeql.actions.Ast::Utils as Utils
import codeql.actions.Cfg as Cfg
import codeql.actions.DataFlow
import codeql.Locations
@@ -59,3 +60,12 @@ query predicate summaries(string action, string version, string input, string ou
query predicate calls(DataFlow::CallNode call, string callee) { callee = call.getCallee() }
query predicate needs(DataFlow::Node e) { e.asExpr() instanceof NeedsExpression }
query string testNormalizeExpr(string s) {
s =
[
"github.event.pull_request.user['login']", "github.event.pull_request.user[\"login\"]",
"github.event.pull_request['user']['login']", "foo['bar'] == baz"
] and
result = Utils::normalizeExpr(s)
}

View File

@@ -0,0 +1,20 @@
name: Test
on:
issue_comment:
types: [created]
jobs:
test1:
runs-on: ubuntu-22.04
outputs:
job_output: ${{ steps.source.outputs.value }}
steps:
- id: source
uses: mad9000/actions-find-and-replace-string@3
with:
source: ${{ github.event['head_commit']['message'] }}
find: 'foo'
replace: ''
- run: ${{ steps.source.outputs.value }}
- run: ${{ needs.test1.outputs.job_output }}

View File

@@ -12,7 +12,7 @@ jobs:
- id: step0
uses: mad9000/actions-find-and-replace-string@3
with:
source: ${{ github.event.head_commit.message }}
source: ${{ github.event['head_commit']['message'] }}
find: 'foo'
replace: ''
- id: step1
@@ -34,4 +34,4 @@ jobs:
needs: job1
steps:
- run: echo ${{needs.job1.outputs.job_output}}
- run: echo ${{needs.job1.outputs['job_output']}}

View File

@@ -3,6 +3,7 @@ edges
| .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE |
| .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] |
| .github/workflows/changed-files.yml:16:9:20:6 | Uses Step: changed-files | .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files |
| .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | .github/workflows/changelog.yml:58:26:58:39 | env.log |
| .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] | .github/workflows/cross3.yml:39:31:39:75 | steps.remove_quotations.outputs.replaced |
| .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] | .github/workflows/cross3.yml:57:29:57:73 | steps.remove_quotations.outputs.replaced |
| .github/workflows/cross3.yml:32:18:32:53 | github.event.commits[0].message | .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] |
@@ -38,15 +39,20 @@ edges
| .github/workflows/issues.yaml:4:16:4:46 | github.event.issue.title | .github/workflows/issues.yaml:15:19:15:39 | env.global_env |
| .github/workflows/issues.yaml:10:17:10:47 | github.event.issue.title | .github/workflows/issues.yaml:17:19:17:36 | env.job_env |
| .github/workflows/issues.yaml:20:20:20:50 | github.event.issue.title | .github/workflows/issues.yaml:18:19:18:37 | env.step_env |
| .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] | .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output |
| .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value | .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value |
| .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] |
| .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value |
| .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] |
| .github/workflows/simple2.yml:14:9:18:6 | Uses Step: source | .github/workflows/simple2.yml:22:20:22:64 | steps.source.outputs.all_changed_files |
| .github/workflows/simple2.yml:18:9:26:6 | Uses Step: step [value] | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value |
| .github/workflows/simple2.yml:22:20:22:64 | steps.source.outputs.all_changed_files | .github/workflows/simple2.yml:18:9:26:6 | Uses Step: step [value] |
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output |
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] |
| .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test | .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] |
| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value |
| .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] |
| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] |
| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG |
| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] |
| .github/workflows/test.yml:24:9:29:2 | Run Step: step2 [test] | .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test |
@@ -58,6 +64,8 @@ nodes
| .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | semmle.label | steps.remove_quotations.outputs.replaced |
| .github/workflows/changed-files.yml:16:9:20:6 | Uses Step: changed-files | semmle.label | Uses Step: changed-files |
| .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files | semmle.label | steps.changed-files.outputs.all_changed_files |
| .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/changelog.yml:58:26:58:39 | env.log | semmle.label | env.log |
| .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | semmle.label | github.event.comment.body |
| .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | semmle.label | github.event.comment.body |
| .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | semmle.label | github.event.issue.body |
@@ -159,6 +167,12 @@ nodes
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
| .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
| .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value | semmle.label | steps.source.outputs.value |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | semmle.label | Uses Step: source [value] |
| .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] |
| .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value | semmle.label | steps.source.outputs.value |
| .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output | semmle.label | needs.test1.outputs.job_output |
| .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] | semmle.label | Uses Step: summary [value] |
| .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
| .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | semmle.label | steps.summary.outputs.value |
@@ -169,12 +183,12 @@ nodes
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
| .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test | semmle.label | steps.step2.outputs.test |
| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] |
| .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] |
| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] |
| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value |
| .github/workflows/test.yml:24:9:29:2 | Run Step: step2 [test] | semmle.label | Run Step: step2 [test] |
| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG |
| .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | semmle.label | needs.job1.outputs.job_output |
| .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] |
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | semmle.label | github.event.workflow_run.display_title |
| .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | semmle.label | github.event.workflow_run.head_commit.message |
| .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | semmle.label | github.event.workflow_run.head_commit.author.email |
@@ -187,6 +201,7 @@ nodes
subpaths
#select
| .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | steps.remove_quotations.outputs.replaced |
| .github/workflows/changelog.yml:58:26:58:39 | env.log | .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | .github/workflows/changelog.yml:58:26:58:39 | env.log | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/changelog.yml:58:26:58:39 | env.log | env.log |
| .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | github.event.comment.body |
| .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | github.event.comment.body |
| .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | github.event.issue.body |
@@ -250,7 +265,7 @@ subpaths
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | github.event.commits[11].committer.name |
| .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | steps.summary.outputs.value |
| .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | .github/workflows/simple2.yml:14:9:18:6 | Uses Step: source | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | steps.step.outputs.value |
| .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | needs.job1.outputs.job_output |
| .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | needs.job1.outputs['job_output'] |
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | github.event.workflow_run.display_title |
| .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | github.event.workflow_run.head_commit.message |
| .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | github.event.workflow_run.head_commit.author.email |

View File

@@ -3,6 +3,7 @@ edges
| .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE |
| .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] |
| .github/workflows/changed-files.yml:16:9:20:6 | Uses Step: changed-files | .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files |
| .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | .github/workflows/changelog.yml:58:26:58:39 | env.log |
| .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] | .github/workflows/cross3.yml:39:31:39:75 | steps.remove_quotations.outputs.replaced |
| .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] | .github/workflows/cross3.yml:57:29:57:73 | steps.remove_quotations.outputs.replaced |
| .github/workflows/cross3.yml:32:18:32:53 | github.event.commits[0].message | .github/workflows/cross3.yml:27:7:37:4 | Uses Step: remove_quotations [replaced] |
@@ -38,15 +39,20 @@ edges
| .github/workflows/issues.yaml:4:16:4:46 | github.event.issue.title | .github/workflows/issues.yaml:15:19:15:39 | env.global_env |
| .github/workflows/issues.yaml:10:17:10:47 | github.event.issue.title | .github/workflows/issues.yaml:17:19:17:36 | env.job_env |
| .github/workflows/issues.yaml:20:20:20:50 | github.event.issue.title | .github/workflows/issues.yaml:18:19:18:37 | env.step_env |
| .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] | .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output |
| .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value | .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value |
| .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] |
| .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value |
| .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] |
| .github/workflows/simple2.yml:14:9:18:6 | Uses Step: source | .github/workflows/simple2.yml:22:20:22:64 | steps.source.outputs.all_changed_files |
| .github/workflows/simple2.yml:18:9:26:6 | Uses Step: step [value] | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value |
| .github/workflows/simple2.yml:22:20:22:64 | steps.source.outputs.all_changed_files | .github/workflows/simple2.yml:18:9:26:6 | Uses Step: step [value] |
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output |
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] |
| .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test | .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] |
| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value |
| .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] |
| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] |
| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG |
| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] |
| .github/workflows/test.yml:24:9:29:2 | Run Step: step2 [test] | .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test |
@@ -58,6 +64,8 @@ nodes
| .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | semmle.label | steps.remove_quotations.outputs.replaced |
| .github/workflows/changed-files.yml:16:9:20:6 | Uses Step: changed-files | semmle.label | Uses Step: changed-files |
| .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files | semmle.label | steps.changed-files.outputs.all_changed_files |
| .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/changelog.yml:58:26:58:39 | env.log | semmle.label | env.log |
| .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | semmle.label | github.event.comment.body |
| .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | semmle.label | github.event.comment.body |
| .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | semmle.label | github.event.issue.body |
@@ -159,6 +167,12 @@ nodes
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
| .github/workflows/self_needs.yml:11:7:12:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
| .github/workflows/self_needs.yml:11:20:11:52 | steps.source.outputs.value | semmle.label | steps.source.outputs.value |
| .github/workflows/self_needs.yml:13:9:19:6 | Uses Step: source [value] | semmle.label | Uses Step: source [value] |
| .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] |
| .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value | semmle.label | steps.source.outputs.value |
| .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output | semmle.label | needs.test1.outputs.job_output |
| .github/workflows/simple1.yml:8:9:14:6 | Uses Step: summary [value] | semmle.label | Uses Step: summary [value] |
| .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
| .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | semmle.label | steps.summary.outputs.value |
@@ -169,12 +183,12 @@ nodes
| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
| .github/workflows/test.yml:8:20:8:50 | steps.step2.outputs.test | semmle.label | steps.step2.outputs.test |
| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] |
| .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] |
| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] |
| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value |
| .github/workflows/test.yml:24:9:29:2 | Run Step: step2 [test] | semmle.label | Run Step: step2 [test] |
| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG |
| .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | semmle.label | needs.job1.outputs.job_output |
| .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] |
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | semmle.label | github.event.workflow_run.display_title |
| .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | semmle.label | github.event.workflow_run.head_commit.message |
| .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | semmle.label | github.event.workflow_run.head_commit.author.email |
@@ -188,6 +202,7 @@ subpaths
#select
| .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | ${{steps.remove_quotations.outputs.replaced}} |
| .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files | .github/workflows/changed-files.yml:16:9:20:6 | Uses Step: changed-files | .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/changed-files.yml:22:24:22:75 | steps.changed-files.outputs.all_changed_files | ${{ steps.changed-files.outputs.all_changed_files }} |
| .github/workflows/changelog.yml:58:26:58:39 | env.log | .github/workflows/changelog.yml:49:19:49:56 | github.event.pull_request.title | .github/workflows/changelog.yml:58:26:58:39 | env.log | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/changelog.yml:58:26:58:39 | env.log | ${{ env.log }} |
| .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:9:15:9:46 | github.event.comment.body | ${{ github.event.comment.body }} |
| .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:15:19:15:50 | github.event.comment.body | ${{ github.event.comment.body }} |
| .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/comment_issue.yml:16:19:16:48 | github.event.issue.body | ${{ github.event.issue.body }} |
@@ -255,9 +270,11 @@ subpaths
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | ${{ github.event.head_commit.committer.name }} |
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | ${{ github.event.commits[11].committer.email }} |
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | ${{ github.event.commits[11].committer.name }} |
| .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value | .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/self_needs.yml:19:15:19:47 | steps.source.outputs.value | ${{ steps.source.outputs.value }} |
| .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output | .github/workflows/self_needs.yml:16:20:16:64 | github.event['head_commit']['message'] | .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/self_needs.yml:20:15:20:51 | needs.test1.outputs.job_output | ${{ needs.test1.outputs.job_output }} |
| .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | .github/workflows/simple1.yml:11:20:11:58 | github.event.head_commit.message | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/simple1.yml:16:18:16:49 | steps.summary.outputs.value | ${{steps.summary.outputs.value}} |
| .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | .github/workflows/simple2.yml:14:9:18:6 | Uses Step: source | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/simple2.yml:29:24:29:54 | steps.step.outputs.value | ${{ steps.step.outputs.value }} |
| .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | .github/workflows/test.yml:15:20:15:58 | github.event.head_commit.message | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/test.yml:37:20:37:53 | needs.job1.outputs.job_output | ${{needs.job1.outputs.job_output}} |
| .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/test.yml:37:20:37:56 | needs.job1.outputs['job_output'] | ${{needs.job1.outputs['job_output']}} |
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | ${{ github.event.workflow_run.display_title }} |
| .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | ${{ github.event.workflow_run.head_commit.message }} |
| .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | Potential expression injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:11:19:11:75 | github.event.workflow_run.head_commit.author.email | ${{ github.event.workflow_run.head_commit.author.email }} |

View File

@@ -0,0 +1,135 @@
name: Python CI
on:
push:
branches: [ master ]
pull_request_target:
branches: [ master, stable ]
concurrency:
group: ${{ format('ci-{0}', github.head_ref && format('pr-{0}', github.event.pull_request.number) || github.sha) }}
cancel-in-progress: ${{ github.event_name == 'pull_request_target' }}
jobs:
lint:
runs-on: ubuntu-latest
env:
min-python-version: "3.10"
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Set up Python ${{ env.min-python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.min-python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Lint with flake8
run: flake8
- name: Check black formatting
run: black . --check
if: success() || failure()
- name: Check isort formatting
run: isort . --check
if: success() || failure()
- name: Check mypy formatting
run: mypy
if: success() || failure()
test:
permissions:
# Gives the action the necessary permissions for publishing new
# comments in pull requests.
pull-requests: write
# Gives the action the necessary permissions for pushing data to the
# python-coverage-comment-action branch, and for editing existing
# comments (to avoid publishing multiple comments in the same PR)
contents: write
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref || github.event.pull_request.base.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run unittest tests with coverage
run: |
pytest -n auto --cov=autogpt --cov-report term-missing --cov-branch --cov-report xml --cov-report term
env:
CI: true
PROXY: ${{ secrets.PROXY }}
AGENT_MODE: ${{ vars.AGENT_MODE }}
AGENT_TYPE: ${{ vars.AGENT_TYPE }}
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
- name: Stage new files and commit
id: stage_files
run: |
git add tests
git diff --cached --quiet && echo "No changes to commit" && exit 0
git config user.email "github-actions@github.com"
git config user.name "GitHub Actions"
git commit -m "Add new cassettes"
TIMESTAMP_COMMIT=$(date +%Y%m%d%H%M%S) # generate a timestamp
echo "TIMESTAMP_COMMIT=TIMESTAMP_COMMIT" >> $GITHUB_ENV
- name: Create PR
id: create_pr
if: ${{ env.TIMESTAMP_COMMIT != null }}
uses: peter-evans/create-pull-request@v5
with:
commit-message: Update cassettes
branch: cassette-diff-PR-${{ github.event.pull_request.number }}-${{ env.TIMESTAMP_COMMIT }}
title: "Update cassette-diff-PR${{ github.event.pull_request.number }}-${{ env.TIMESTAMP_COMMIT }}"
body: "This PR updates the cassettes. Please merge it."
- name: Check PR
if: ${{ env.TIMESTAMP_COMMIT != null }}
run: |
echo "Pull Request Number - ${{ steps.create_pr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.create_pr.outputs.pull-request-url }}"
- name: Comment PR URL in the current PR
if: ${{ env.TIMESTAMP_COMMIT != null }}
uses: thollander/actions-comment-pull-request@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
message: |
Please click [HERE](${{ steps.create_pr.outputs.pull-request-url }}) and merge this PR to update the cassettes.
- name: Fail if new PR created
if: ${{ env.TIMESTAMP_COMMIT != null }}
run: exit 1

View File

@@ -0,0 +1,23 @@
on:
pull_request_target
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
# 1. Check out the content from an incoming pull request
- run: |
git fetch origin $HEAD_BRANCH
git checkout origin/master
git config user.name "release-hash-check"
git config user.email "<>"
git merge --no-commit --no-edit origin/$HEAD_BRANCH
env:
HEAD_BRANCH: ${{ github.head_ref }}
- uses: actions/setup-node@v1
# 2. Potentially untrusted commands are being run during "npm install" or "npm build" as
# the build scripts and referenced packages are controlled by the author of the pull request
- run: |
npm install
npm build

View File

@@ -0,0 +1,52 @@
name: PR head from 3rd party action
on:
workflow_call:
workflow_dispatch:
jobs:
test1:
runs-on: ubuntu-20.04
steps:
- name: (PR comment) Get PR branch
if: ${{ github.event_name == 'issue_comment' }}
uses: xt0rted/pull-request-comment-branch@v2
id: comment-branch
- name: (PR comment) Checkout PR branch
if: ${{ github.event_name == 'issue_comment' }}
uses: actions/checkout@v3
with:
ref: ${{ steps.comment-branch.outputs.head_sha }}
test2:
runs-on: ubuntu-20.04
steps:
- name: (PR comment) Get PR branch
if: ${{ github.event_name == 'issue_comment' }}
uses: xt0rted/pull-request-comment-branch@v2
id: comment-branch
- name: (PR comment) Checkout PR branch
if: ${{ github.event_name == 'issue_comment' }}
uses: actions/checkout@v3
with:
ref: ${{ steps.comment-branch.outputs.head_ref }}
test3:
runs-on: ubuntu-20.04
steps:
- name: resolve pr refs
id: refs
uses: eficode/resolve-pr-refs@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
ref: ${{ steps.refs.outputs.head_ref }}
fetch-depth: 0
- uses: actions/checkout@v4
with:
ref: ${{ steps.refs.outputs.head_sha }}
fetch-depth: 0

View File

@@ -0,0 +1,46 @@
name: Direct access
on:
issue_comment:
types: [created]
jobs:
test1:
runs-on: ubuntu-latest
if: github.event_name == 'issue_comment' && github.event.issue.pull_request
steps:
- name: Unsafe Code Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref || github.head_ref }} # Checkout the branch that made the PR or the comment's PR branch
test2:
runs-on: ubuntu-latest
if: github.event.issue.pull_request && github.event.comment.body == '/trigger release'
steps:
- uses: actions/checkout@v4
with:
ref: refs/pull/${{ github.event.issue.number }}/merge
test3:
runs-on: ubuntu-latest
if: github.event.issue.pull_request && github.event.comment.body == '/trigger release'
steps:
- uses: actions/checkout@v4
with:
ref: ${{ format('refs/pull/{0}/merge', github.event.issue.number) }}
test4:
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v4
with:
ref: ${{ (github.event_name == 'pull_request_review_comment') && format('refs/pull/{0}/merge', github.event.pull_request.number) || '' }}
test5:
runs-on: ubuntu-latest
steps:
- name: Checkout Branch
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'issue_comment' && format('refs/pull/{0}/merge', github.event.issue.number) || '' }}

View File

@@ -0,0 +1,50 @@
name: Heuristic based
on:
issue_comment:
types: [created]
jobs:
test1:
runs-on: ubuntu-latest
steps:
- name: Get Info from comment
uses: actions/github-script@v7
id: get-pr-info
with:
script: |
const request = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.issue.number }},
}
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
const pr = await github.rest.pulls.get(request);
return pr.data;
- name: Debug
id: get-sha
run: |
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses: actions/checkout@v4
with:
ref: ${{ steps.get-sha.outputs.sha }}
test2:
runs-on: ubuntu-latest
steps:
- name: Detect branch for PR
id: vars
run: |
PR=$( echo "${{ github.event.comment.issue_url }}" | grep -oE 'issues/([0-9]+)$' | cut -d'/' -f 2 )
PR_INFO=$( curl \
--request GET \
--header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
--header 'content-type: application/json' \
--url https://api.github.com/repos/$GITHUB_REPOSITORY/pulls/$PR )
REF=$(echo "${PR_INFO}" | jq -r .head.ref)
echo "branch=$REF" >> $GITHUB_OUTPUT
- uses: actions/checkout@v4
with:
ref: ${{ steps.vars.outputs.branch }}

View File

@@ -0,0 +1,114 @@
name: Octokit (heuristics)
on:
issue_comment:
types: [created]
jobs:
test1:
if: github.event.comment.body == '@metabase-bot run visual tests'
runs-on: ubuntu-22.04
steps:
- name: Fetch issue
uses: octokit/request-action@v2.x
id: fetch_issue
with:
route: GET ${{ github.event.issue.url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch PR
uses: octokit/request-action@v2.x
id: fetch_pr
with:
route: GET ${{ fromJson(steps.fetch_issue.outputs.data).pull_request.url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
ref: ${{ fromJson(steps.fetch_pr.outputs.data).head.ref }}
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
ref: ${{ fromJson(steps.fetch_pr.outputs.data).head.sha }}
token: ${{ secrets.GITHUB_TOKEN }}
test2:
runs-on: ubuntu-latest
steps:
- name: Get Info from comment
uses: actions/github-script@v7
id: get-pr-info
with:
script: |
const request = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.issue.number }},
}
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
const pr = await github.rest.pulls.get(request);
return pr.data;
- name: Debug
id: get-sha
run: |
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses: actions/checkout@v4
with:
ref: ${{ steps.get-sha.outputs.sha }}
test3:
if: github.event.comment.body == '@excalibot trigger release' && github.event.issue.pull_request
runs-on: ubuntu-latest
steps:
- name: Get PR SHA
id: sha
uses: actions/github-script@v4
with:
result-encoding: string
script: |
const { owner, repo, number } = context.issue;
const pr = await github.pulls.get({
owner,
repo,
pull_number: number,
});
return pr.data.head.sha
- uses: actions/checkout@v2
with:
ref: ${{ steps.sha.outputs.result }}
test4:
if: github.event.issue.pull_request && contains(github.event.comment.body, '!bench_parser')
runs-on: ubuntu-latest
steps:
- name: Get PR SHA
id: sha
uses: actions/github-script@v6
with:
result-encoding: string
script: |
const response = await github.request(context.payload.issue.pull_request.url);
return response.data.head.sha;
- name: Checkout PR Branch
uses: actions/checkout@v3
with:
ref: ${{ steps.sha.outputs.result }}
test5:
runs-on: ubuntu-20.04
steps:
- id: request
uses: octokit/request-action@v2.0.2
with:
route: ${{ github.event.issue.pull_request.url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout PR Branch
uses: actions/checkout@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{fromJson(steps.request.outputs.data).head.repo.full_name}}
ref: ${{fromJson(steps.request.outputs.data).head.ref}}

View File

@@ -3,23 +3,13 @@ on:
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
env:
HEAD: ${{ github.event.pull_request.head.sha }}
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/checkout@v2
with:
ref: ${{ env.HEAD }}

View File

@@ -1,7 +1,14 @@
| .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:19:7:23:4 | Uses Step | Uses Step |
| .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Unpinned 3rd party Action 'actor_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/actor_trusted_checkout.yml:23:7:26:21 | Uses Step | Uses Step |
| .github/workflows/auto_ci.yml:93:9:96:6 | Uses Step | Unpinned 3rd party Action 'Python CI' step $@ uses 'codecov/codecov-action' with ref 'v3', not a pinned commit hash | .github/workflows/auto_ci.yml:93:9:96:6 | Uses Step | Uses Step |
| .github/workflows/auto_ci.yml:108:9:119:6 | Uses Step: create_pr | Unpinned 3rd party Action 'Python CI' step $@ uses 'peter-evans/create-pull-request' with ref 'v5', not a pinned commit hash | .github/workflows/auto_ci.yml:108:9:119:6 | Uses Step: create_pr | Uses Step: create_pr |
| .github/workflows/auto_ci.yml:125:9:133:6 | Uses Step | Unpinned 3rd party Action 'Python CI' step $@ uses 'thollander/actions-comment-pull-request' with ref 'v2', not a pinned commit hash | .github/workflows/auto_ci.yml:125:9:133:6 | Uses Step | Uses Step |
| .github/workflows/issue_comment_3rd_party_action.yml:12:9:16:6 | Uses Step: comment-branch | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'xt0rted/pull-request-comment-branch' with ref 'v2', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:12:9:16:6 | Uses Step: comment-branch | Uses Step: comment-branch |
| .github/workflows/issue_comment_3rd_party_action.yml:25:9:30:6 | Uses Step: comment-branch | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'xt0rted/pull-request-comment-branch' with ref 'v2', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:25:9:30:6 | Uses Step: comment-branch | Uses Step: comment-branch |
| .github/workflows/issue_comment_3rd_party_action.yml:39:9:45:6 | Uses Step: refs | Unpinned 3rd party Action 'PR head from 3rd party action' step $@ uses 'eficode/resolve-pr-refs' with ref 'main', not a pinned commit hash | .github/workflows/issue_comment_3rd_party_action.yml:39:9:45:6 | Uses Step: refs | Uses Step: refs |
| .github/workflows/issue_comment_octokit.yml:12:9:19:6 | Uses Step: fetch_issue | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/issue_comment_octokit.yml:12:9:19:6 | Uses Step: fetch_issue | Uses Step: fetch_issue |
| .github/workflows/issue_comment_octokit.yml:19:9:26:6 | Uses Step: fetch_pr | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.x', not a pinned commit hash | .github/workflows/issue_comment_octokit.yml:19:9:26:6 | Uses Step: fetch_pr | Uses Step: fetch_pr |
| .github/workflows/issue_comment_octokit.yml:103:9:109:6 | Uses Step: request | Unpinned 3rd party Action 'Octokit (heuristics)' step $@ uses 'octokit/request-action' with ref 'v2.0.2', not a pinned commit hash | .github/workflows/issue_comment_octokit.yml:103:9:109:6 | Uses Step: request | Uses Step: request |
| .github/workflows/label_trusted_checkout.yml:20:7:24:4 | Uses Step | Unpinned 3rd party Action 'label_trusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/label_trusted_checkout.yml:20:7:24:4 | Uses Step | Uses Step |
| .github/workflows/label_trusted_checkout.yml:24:7:27:21 | Uses Step | Unpinned 3rd party Action 'label_trusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/label_trusted_checkout.yml:24:7:27:21 | Uses Step | Uses Step |
| .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | Unpinned 3rd party Action 'unpinned_tags.yml' step $@ uses 'foo/bar' with ref 'v1', not a pinned commit hash | .github/workflows/unpinned_tags.yml:10:7:11:4 | Uses Step | Uses Step |
| .github/workflows/untrusted_checkout.yml:18:7:22:4 | Uses Step | Unpinned 3rd party Action 'untrusted_checkout.yml' step $@ uses 'completely/fakeaction' with ref 'v2', not a pinned commit hash | .github/workflows/untrusted_checkout.yml:18:7:22:4 | Uses Step | Uses Step |
| .github/workflows/untrusted_checkout.yml:22:7:25:21 | Uses Step | Unpinned 3rd party Action 'untrusted_checkout.yml' step $@ uses 'fakerepo/comment-on-pr' with ref 'v1', not a pinned commit hash | .github/workflows/untrusted_checkout.yml:22:7:25:21 | Uses Step | Uses Step |

View File

@@ -1 +1,22 @@
| .github/workflows/untrusted_checkout.yml:9:7:13:4 | Uses Step | Potential unsafe checkout of untrusted pull request on 'pull_request_target'. |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_3rd_party_action.yml:16:9:22:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_3rd_party_action.yml:30:9:36:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_3rd_party_action.yml:45:9:49:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_3rd_party_action.yml:49:9:52:25 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_direct.yml:12:9:16:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_direct.yml:20:9:24:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_direct.yml:28:9:32:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_direct.yml:35:9:40:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_direct.yml:43:9:46:126 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_heuristic.yml:28:9:33:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_heuristic.yml:48:7:50:46 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:26:9:30:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:30:9:35:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:57:9:62:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/untrusted_checkout.yml:10:9:13:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
| .github/workflows/untrusted_checkout.yml:13:9:15:31 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |