mirror of
https://github.com/github/codeql.git
synced 2026-03-06 07:36:47 +01:00
Improve Control Checks
This commit is contained in:
@@ -79,8 +79,6 @@ class CompositeAction extends AstNode instanceof CompositeActionImpl {
|
||||
UsesStep getACallerStep() { result = super.getACallerStep() }
|
||||
|
||||
predicate isPrivileged() { super.isPrivileged() }
|
||||
|
||||
predicate isPrivilegedExternallyTriggerable() { super.isPrivilegedExternallyTriggerable() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,7 +198,9 @@ abstract class Job extends AstNode instanceof JobImpl {
|
||||
|
||||
predicate isPrivileged() { super.isPrivileged() }
|
||||
|
||||
predicate isPrivilegedExternallyTriggerable() { super.isPrivilegedExternallyTriggerable() }
|
||||
predicate isPrivilegedExternallyTriggerable(Event event) {
|
||||
super.isPrivilegedExternallyTriggerable(event)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class StepsContainer extends AstNode instanceof StepsContainerImpl {
|
||||
|
||||
@@ -238,44 +238,12 @@ predicate fileToGitHubPath(Run run, string path) {
|
||||
fileToFileWrite(run.getScript(), "GITHUB_PATH", path)
|
||||
}
|
||||
|
||||
predicate inPrivilegedCompositeAction(AstNode node) {
|
||||
exists(CompositeAction a |
|
||||
a = node.getEnclosingCompositeAction() and
|
||||
a.isPrivilegedExternallyTriggerable()
|
||||
)
|
||||
}
|
||||
|
||||
predicate inPrivilegedExternallyTriggerableJob(AstNode node) {
|
||||
exists(Job j |
|
||||
j = node.getEnclosingJob() and
|
||||
j.isPrivilegedExternallyTriggerable()
|
||||
)
|
||||
}
|
||||
|
||||
predicate inPrivilegedContext(AstNode node) {
|
||||
inPrivilegedCompositeAction(node)
|
||||
or
|
||||
inPrivilegedExternallyTriggerableJob(node)
|
||||
}
|
||||
|
||||
predicate inNonPrivilegedCompositeAction(AstNode node) {
|
||||
exists(CompositeAction a |
|
||||
a = node.getEnclosingCompositeAction() and
|
||||
not a.isPrivilegedExternallyTriggerable()
|
||||
)
|
||||
}
|
||||
|
||||
predicate inNonPrivilegedJob(AstNode node) {
|
||||
exists(Job j |
|
||||
j = node.getEnclosingJob() and
|
||||
not j.isPrivilegedExternallyTriggerable()
|
||||
)
|
||||
predicate inPrivilegedContext(AstNode node, Event event) {
|
||||
node.getEnclosingJob().isPrivilegedExternallyTriggerable(event)
|
||||
}
|
||||
|
||||
predicate inNonPrivilegedContext(AstNode node) {
|
||||
inNonPrivilegedCompositeAction(node)
|
||||
or
|
||||
inNonPrivilegedJob(node)
|
||||
not node.getEnclosingJob().isPrivilegedExternallyTriggerable(_)
|
||||
}
|
||||
|
||||
string partialFileContentRegexp() {
|
||||
|
||||
@@ -359,18 +359,6 @@ class CompositeActionImpl extends AstNodeImpl, TCompositeAction {
|
||||
}
|
||||
|
||||
EventImpl getATriggerEvent() { result = this.getACallerJob().getATriggerEvent() }
|
||||
|
||||
/** Holds if the action is privileged and externally triggerable. */
|
||||
predicate isPrivilegedExternallyTriggerable() {
|
||||
// the action is externally triggerable
|
||||
exists(JobImpl caller, EventImpl event |
|
||||
caller = this.getACallerJob() and
|
||||
event = caller.getATriggerEvent() and
|
||||
event.isExternallyTriggerable() and
|
||||
// the action is privileged
|
||||
(this.isPrivileged() or caller.isPrivileged())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class WorkflowImpl extends AstNodeImpl, TWorkflowNode {
|
||||
@@ -970,31 +958,30 @@ class JobImpl extends AstNodeImpl, TJobNode {
|
||||
}
|
||||
|
||||
/** Holds if the action is privileged and externally triggerable. */
|
||||
predicate isPrivilegedExternallyTriggerable() {
|
||||
exists(EventImpl e | this.getATriggerEvent() = e |
|
||||
// job is triggereable by an external user
|
||||
e.isExternallyTriggerable() and
|
||||
// no matter if `pull_request` is granted write permissions or access to secrets
|
||||
// when the job is triggered by a `pull_request` event from a fork, they will get revoked
|
||||
not e.getName() = "pull_request" and
|
||||
(
|
||||
// job is privileged (write access or access to secrets)
|
||||
this.isPrivileged()
|
||||
or
|
||||
// the trigger event is __normally__ privileged
|
||||
e.isPrivileged() and
|
||||
// and we have no runtime data to prove otherwise
|
||||
not this.hasRuntimeData() and
|
||||
// and the job is not explicitly non-privileged
|
||||
not (
|
||||
(
|
||||
this.hasExplicitNonePermission() or
|
||||
this.hasImplicitNonePermission() or
|
||||
this.hasExplicitReadPermission() or
|
||||
this.hasImplicitReadPermission()
|
||||
) and
|
||||
not this.hasExplicitSecretAccess()
|
||||
)
|
||||
predicate isPrivilegedExternallyTriggerable(EventImpl event) {
|
||||
this.getATriggerEvent() = event and
|
||||
// job is triggereable by an external user
|
||||
event.isExternallyTriggerable() and
|
||||
// no matter if `pull_request` is granted write permissions or access to secrets
|
||||
// when the job is triggered by a `pull_request` event from a fork, they will get revoked
|
||||
not event.getName() = "pull_request" and
|
||||
(
|
||||
// job is privileged (write access or access to secrets)
|
||||
this.isPrivileged()
|
||||
or
|
||||
// the trigger event is __normally__ privileged
|
||||
event.isPrivileged() and
|
||||
// and we have no runtime data to prove otherwise
|
||||
not this.hasRuntimeData() and
|
||||
// and the job is not explicitly non-privileged
|
||||
not (
|
||||
(
|
||||
this.hasExplicitNonePermission() or
|
||||
this.hasImplicitNonePermission() or
|
||||
this.hasExplicitReadPermission() or
|
||||
this.hasImplicitReadPermission()
|
||||
) and
|
||||
not this.hasExplicitSecretAccess()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1073,6 +1060,12 @@ class StepImpl extends AstNodeImpl, TStepNode {
|
||||
|
||||
override YamlMapping getNode() { result = n }
|
||||
|
||||
override JobImpl getEnclosingJob() {
|
||||
// if a step is within a composite action, we should follow the caller job
|
||||
result = this.getEnclosingCompositeAction().getACallerJob() or
|
||||
result = super.getEnclosingJob()
|
||||
}
|
||||
|
||||
EnvImpl getEnv() { result.getNode() = n.lookup("env") }
|
||||
|
||||
/** Gets the ID of this step, if any. */
|
||||
|
||||
@@ -38,9 +38,12 @@ abstract class ControlCheck extends AstNode {
|
||||
}
|
||||
|
||||
predicate protects(Step step, Event event, string category) {
|
||||
event = step.getEnclosingWorkflow().getATriggerEvent() and
|
||||
// The check dominates the step it should protect
|
||||
this.dominates(step) and
|
||||
this.protectsCategoryAndEvent(category, event.getName())
|
||||
// The check is effective against the event and category
|
||||
this.protectsCategoryAndEvent(category, event.getName()) and
|
||||
// The check can be triggered by the event
|
||||
this.getEnclosingJob().getATriggerEvent() = event
|
||||
}
|
||||
|
||||
predicate dominates(Step step) {
|
||||
|
||||
@@ -18,25 +18,20 @@ import codeql.actions.dataflow.ExternalFlow
|
||||
import OutputClobberingFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from OutputClobberingFlow::PathNode source, OutputClobberingFlow::PathNode sink
|
||||
from OutputClobberingFlow::PathNode source, OutputClobberingFlow::PathNode sink, Event event
|
||||
where
|
||||
OutputClobberingFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr()) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
// exclude paths to file read sinks from non-artifact sources
|
||||
(
|
||||
not source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "code-injection")
|
||||
check.protects(sink.getNode().asExpr(), event, "code-injection")
|
||||
)
|
||||
or
|
||||
source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(),
|
||||
["untrusted-checkout", "artifact-poisoning"])
|
||||
check.protects(sink.getNode().asExpr(), event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
(
|
||||
sink.getNode() instanceof OutputClobberingFromFileReadSink or
|
||||
|
||||
@@ -17,24 +17,19 @@ import codeql.actions.security.EnvPathInjectionQuery
|
||||
import EnvPathInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from EnvPathInjectionFlow::PathNode source, EnvPathInjectionFlow::PathNode sink
|
||||
from EnvPathInjectionFlow::PathNode source, EnvPathInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
EnvPathInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr()) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
(
|
||||
not source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "code-injection")
|
||||
check.protects(sink.getNode().asExpr(), event, "code-injection")
|
||||
)
|
||||
or
|
||||
source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(),
|
||||
["untrusted-checkout", "artifact-poisoning"])
|
||||
check.protects(sink.getNode().asExpr(), event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
sink.getNode() instanceof EnvPathInjectionFromFileReadSink
|
||||
)
|
||||
|
||||
@@ -18,30 +18,23 @@ import codeql.actions.dataflow.ExternalFlow
|
||||
import EnvVarInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from EnvVarInjectionFlow::PathNode source, EnvVarInjectionFlow::PathNode sink
|
||||
from EnvVarInjectionFlow::PathNode source, EnvVarInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
EnvVarInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr()) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "envvar-injection")
|
||||
check.protects(sink.getNode().asExpr(), event, "envvar-injection")
|
||||
) and
|
||||
// exclude paths to file read sinks from non-artifact sources
|
||||
(
|
||||
not source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "code-injection")
|
||||
check.protects(sink.getNode().asExpr(), event, "code-injection")
|
||||
)
|
||||
or
|
||||
source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(),
|
||||
["untrusted-checkout", "artifact-poisoning"])
|
||||
check.protects(sink.getNode().asExpr(), event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
(
|
||||
sink.getNode() instanceof EnvVarInjectionFromFileReadSink or
|
||||
|
||||
@@ -17,10 +17,10 @@ import actions
|
||||
import codeql.actions.security.CommandInjectionQuery
|
||||
import CommandInjectionFlow::PathGraph
|
||||
|
||||
from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink
|
||||
from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CommandInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr())
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential command injection in $@, which may be controlled by an external user.", sink,
|
||||
sink.getNode().asExpr().(Expression).getRawExpression()
|
||||
|
||||
@@ -16,14 +16,12 @@ import codeql.actions.security.ArgumentInjectionQuery
|
||||
import ArgumentInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from ArgumentInjectionFlow::PathNode source, ArgumentInjectionFlow::PathNode sink
|
||||
from ArgumentInjectionFlow::PathNode source, ArgumentInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
ArgumentInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr()) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "argument-injection")
|
||||
check.protects(sink.getNode().asExpr(), event, "argument-injection")
|
||||
)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential argument injection in $@ command, which may be controlled by an external user.", sink,
|
||||
|
||||
@@ -19,15 +19,11 @@ import codeql.actions.security.CodeInjectionQuery
|
||||
import CodeInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr()) and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(),
|
||||
source.getNode().asExpr().getEnclosingJob().getATriggerEvent(), "code-injection")
|
||||
) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check | check.protects(sink.getNode().asExpr(), event, "code-injection")) and
|
||||
// exclude cases where the sink is a JS script and the expression uses toJson
|
||||
not exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
|
||||
@@ -18,27 +18,27 @@ import codeql.actions.security.CachePoisoningQuery
|
||||
import CodeInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, LocalJob j, Event e
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, LocalJob job, Event event
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
j = sink.getNode().asExpr().getEnclosingJob() and
|
||||
j.getATriggerEvent() = e and
|
||||
job = sink.getNode().asExpr().getEnclosingJob() and
|
||||
job.getATriggerEvent() = event and
|
||||
// job can be triggered by an external user
|
||||
e.isExternallyTriggerable() and
|
||||
event.isExternallyTriggerable() and
|
||||
// the checkout is not controlled by an access check
|
||||
not exists(ControlCheck check |
|
||||
check.protects(source.getNode().asExpr(), j.getATriggerEvent(), "code-injection")
|
||||
check.protects(source.getNode().asExpr(), event, "code-injection")
|
||||
) and
|
||||
// excluding privileged workflows since they can be exploited in easier circumstances
|
||||
not j.isPrivileged() and
|
||||
not job.isPrivileged() and
|
||||
(
|
||||
// the workflow runs in the context of the default branch
|
||||
runsOnDefaultBranch(e)
|
||||
runsOnDefaultBranch(event)
|
||||
or
|
||||
// the workflow caller runs in the context of the default branch
|
||||
e.getName() = "workflow_call" and
|
||||
event.getName() = "workflow_call" and
|
||||
exists(ExternalJob caller |
|
||||
caller.getCallee() = j.getLocation().getFile().getRelativePath() and
|
||||
caller.getCallee() = job.getLocation().getFile().getRelativePath() and
|
||||
runsOnDefaultBranch(caller.getATriggerEvent())
|
||||
)
|
||||
)
|
||||
|
||||
@@ -43,10 +43,10 @@ predicate controlledCachePath(string cache_path, string untrusted_path) {
|
||||
|
||||
query predicate edges(Step a, Step b) { a.getNextStep() = b }
|
||||
|
||||
from LocalJob j, Event e, Step source, Step s, string message, string path
|
||||
from LocalJob job, Event event, Step source, Step step, string message, string path
|
||||
where
|
||||
// the job checkouts untrusted code from a pull request or downloads an untrusted artifact
|
||||
j.getAStep() = source and
|
||||
job.getAStep() = source and
|
||||
(
|
||||
source instanceof PRHeadCheckoutStep and
|
||||
message = "due to privilege checkout of untrusted code." and
|
||||
@@ -58,35 +58,36 @@ where
|
||||
) and
|
||||
// the checkout/download is not controlled by an access check
|
||||
not exists(ControlCheck check |
|
||||
check.protects(source, j.getATriggerEvent(), ["untrusted-checkout", "artifact-poisoning"])
|
||||
check.protects(source, event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
j.getATriggerEvent() = e and
|
||||
job.getATriggerEvent() = event and
|
||||
// job can be triggered by an external user
|
||||
e.isExternallyTriggerable() and
|
||||
event.isExternallyTriggerable() and
|
||||
(
|
||||
// the workflow runs in the context of the default branch
|
||||
runsOnDefaultBranch(e)
|
||||
runsOnDefaultBranch(event)
|
||||
or
|
||||
// the workflow's caller runs in the context of the default branch
|
||||
e.getName() = "workflow_call" and
|
||||
event.getName() = "workflow_call" and
|
||||
exists(ExternalJob caller |
|
||||
caller.getCallee() = j.getLocation().getFile().getRelativePath() and
|
||||
caller.getCallee() = job.getLocation().getFile().getRelativePath() and
|
||||
runsOnDefaultBranch(caller.getATriggerEvent())
|
||||
)
|
||||
) and
|
||||
// the job writes to the cache
|
||||
// (No need to follow the checkout/download step since the cache is normally write after the job completes)
|
||||
j.getAStep() = s and
|
||||
s instanceof CacheWritingStep and
|
||||
job.getAStep() = step and
|
||||
step instanceof CacheWritingStep and
|
||||
(
|
||||
// we dont know what code can be controlled by the attacker
|
||||
path = "?"
|
||||
or
|
||||
// we dont know what files are being cached
|
||||
s.(CacheWritingStep).getPath() = "?"
|
||||
step.(CacheWritingStep).getPath() = "?"
|
||||
or
|
||||
// the cache writing step reads from a path the attacker can control
|
||||
not path = "?" and controlledCachePath(s.(CacheWritingStep).getPath(), path)
|
||||
not path = "?" and controlledCachePath(step.(CacheWritingStep).getPath(), path)
|
||||
) and
|
||||
not s instanceof PoisonableStep
|
||||
select s, source, s, "Potential cache poisoning in the context of the default branch " + message
|
||||
not step instanceof PoisonableStep
|
||||
select step, source, step,
|
||||
"Potential cache poisoning in the context of the default branch " + message
|
||||
|
||||
@@ -20,10 +20,10 @@ import codeql.actions.security.ControlChecks
|
||||
|
||||
query predicate edges(Step a, Step b) { a.getNextStep() = b }
|
||||
|
||||
from LocalJob j, Event e, Step source, Step s, string message, string path
|
||||
from LocalJob job, Event event, Step source, Step step, string message, string path
|
||||
where
|
||||
// the job checkouts untrusted code from a pull request or downloads an untrusted artifact
|
||||
j.getAStep() = source and
|
||||
job.getAStep() = source and
|
||||
(
|
||||
source instanceof PRHeadCheckoutStep and
|
||||
message = "due to privilege checkout of untrusted code." and
|
||||
@@ -35,26 +35,27 @@ where
|
||||
) and
|
||||
// the checkout/download is not controlled by an access check
|
||||
not exists(ControlCheck check |
|
||||
check.protects(source, j.getATriggerEvent(), ["untrusted-checkout", "artifact-poisoning"])
|
||||
check.protects(source, event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
j.getATriggerEvent() = e and
|
||||
job.getATriggerEvent() = event and
|
||||
// job can be triggered by an external user
|
||||
e.isExternallyTriggerable() and
|
||||
event.isExternallyTriggerable() and
|
||||
(
|
||||
// the workflow runs in the context of the default branch
|
||||
runsOnDefaultBranch(e)
|
||||
runsOnDefaultBranch(event)
|
||||
or
|
||||
// the workflow's caller runs in the context of the default branch
|
||||
e.getName() = "workflow_call" and
|
||||
event.getName() = "workflow_call" and
|
||||
exists(ExternalJob caller |
|
||||
caller.getCallee() = j.getLocation().getFile().getRelativePath() and
|
||||
caller.getCallee() = job.getLocation().getFile().getRelativePath() and
|
||||
runsOnDefaultBranch(caller.getATriggerEvent())
|
||||
)
|
||||
) and
|
||||
// the job executes checked-out code
|
||||
// (The cache specific token can be leaked even for non-privileged workflows)
|
||||
source.getAFollowingStep() = s and
|
||||
s instanceof PoisonableStep and
|
||||
source.getAFollowingStep() = step and
|
||||
step instanceof PoisonableStep and
|
||||
// excluding privileged workflows since they can be exploited in easier circumstances
|
||||
not j.isPrivileged()
|
||||
select s, source, s, "Potential cache poisoning in the context of the default branch " + message
|
||||
not job.isPrivileged()
|
||||
select step, source, step,
|
||||
"Potential cache poisoning in the context of the default branch " + message
|
||||
|
||||
@@ -18,16 +18,18 @@ import codeql.actions.security.ControlChecks
|
||||
|
||||
query predicate edges(Step a, Step b) { a.getNextStep() = b }
|
||||
|
||||
from LocalJob j, MutableRefCheckoutStep checkout, PoisonableStep s, ControlCheck check
|
||||
from
|
||||
LocalJob job, MutableRefCheckoutStep checkout, PoisonableStep step, ControlCheck check,
|
||||
Event event
|
||||
where
|
||||
j.getAStep() = checkout and
|
||||
job.getAStep() = checkout and
|
||||
// the checked-out code may lead to arbitrary code execution
|
||||
checkout.getAFollowingStep() = s and
|
||||
checkout.getAFollowingStep() = step and
|
||||
// the checkout occurs in a privileged context
|
||||
inPrivilegedContext(checkout) and
|
||||
inPrivilegedContext(checkout, event) and
|
||||
// the mutable checkout step is protected by an Insufficient access check
|
||||
check.protects(checkout, j.getATriggerEvent(), "untrusted-checkout") and
|
||||
not check.protects(checkout, j.getATriggerEvent(), "untrusted-checkout-toctou")
|
||||
select s, checkout, s,
|
||||
check.protects(checkout, event, "untrusted-checkout") and
|
||||
not check.protects(checkout, event, "untrusted-checkout-toctou")
|
||||
select step, checkout, step,
|
||||
"Insufficient protection against execution of untrusted code on a privileged workflow on check $@.",
|
||||
check, check.toString()
|
||||
|
||||
@@ -16,16 +16,17 @@ import codeql.actions.security.UntrustedCheckoutQuery
|
||||
import codeql.actions.security.PoisonableSteps
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from LocalJob j, MutableRefCheckoutStep checkout, ControlCheck check
|
||||
from LocalJob job, MutableRefCheckoutStep checkout, ControlCheck check, Event event
|
||||
where
|
||||
j.getAStep() = checkout and
|
||||
job.getAStep() = checkout and
|
||||
// there are no evidences that the checked-out gets executed
|
||||
not checkout.getAFollowingStep() instanceof PoisonableStep and
|
||||
// the checkout occurs in a privileged context
|
||||
inPrivilegedContext(checkout) and
|
||||
inPrivilegedContext(checkout, event) and
|
||||
event = job.getATriggerEvent() and
|
||||
// the mutable checkout step is protected by an Insufficient access check
|
||||
check.protects(checkout, j.getATriggerEvent(), "untrusted-checkout") and
|
||||
not check.protects(checkout, j.getATriggerEvent(), "untrusted-checkout-toctou")
|
||||
check.protects(checkout, event, "untrusted-checkout") and
|
||||
not check.protects(checkout, event, "untrusted-checkout-toctou")
|
||||
select checkout,
|
||||
"Insufficient protection against execution of untrusted code on a privileged workflow on step $@.",
|
||||
check, check.toString()
|
||||
|
||||
@@ -16,10 +16,13 @@ import codeql.actions.security.ArtifactPoisoningQuery
|
||||
import ArtifactPoisoningFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from ArtifactPoisoningFlow::PathNode source, ArtifactPoisoningFlow::PathNode sink
|
||||
from ArtifactPoisoningFlow::PathNode source, ArtifactPoisoningFlow::PathNode sink, Event event
|
||||
where
|
||||
ArtifactPoisoningFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr())
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, "artifact-poisoning")
|
||||
)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential artifact poisoning in $@, which may be controlled by an external user.", sink,
|
||||
sink.getNode().toString()
|
||||
|
||||
@@ -16,8 +16,9 @@ import actions
|
||||
import codeql.actions.security.PoisonableSteps
|
||||
import codeql.actions.security.UseOfKnownVulnerableActionQuery
|
||||
|
||||
from UsesStep download, KnownVulnerableAction vulnerable_action
|
||||
from UsesStep download, KnownVulnerableAction vulnerable_action, Event event
|
||||
where
|
||||
event = download.getEnclosingJob().getATriggerEvent() and
|
||||
vulnerable_action.getVulnerableAction() = download.getCallee() and
|
||||
download.getCallee() = "actions/download-artifact" and
|
||||
(
|
||||
@@ -28,7 +29,7 @@ where
|
||||
// exists a poisonable upload artifact in the same workflow
|
||||
exists(UsesStep checkout, PoisonableStep poison, UsesStep upload |
|
||||
download.getEnclosingWorkflow().getAJob().(LocalJob).getAStep() = checkout and
|
||||
download.getEnclosingJob().isPrivilegedExternallyTriggerable() and
|
||||
download.getEnclosingJob().isPrivilegedExternallyTriggerable(event) and
|
||||
checkout.getCallee() = "actions/checkout" and
|
||||
checkout.getAFollowingStep() = poison and
|
||||
poison.getAFollowingStep() = upload and
|
||||
|
||||
@@ -25,8 +25,7 @@ where
|
||||
// the checkout is followed by a known poisonable step
|
||||
checkout.getAFollowingStep() = step and
|
||||
// the checkout occurs in a privileged context
|
||||
inPrivilegedContext(checkout) and
|
||||
event = checkout.getEnclosingJob().getATriggerEvent() and
|
||||
inPrivilegedContext(step, event) and
|
||||
(
|
||||
// issue_comment: check for date comparison checks and actor/access control checks
|
||||
event.getName() = "issue_comment" and
|
||||
@@ -36,12 +35,13 @@ where
|
||||
check instanceof AssociationCheck or
|
||||
check instanceof PermissionCheck
|
||||
) and
|
||||
check.dominates(checkout) and
|
||||
date_check.dominates(checkout)
|
||||
check.dominates(step) and
|
||||
date_check.dominates(step)
|
||||
)
|
||||
or
|
||||
// not issue_comment triggered workflows
|
||||
not event.getName() = "issue_comment" and
|
||||
not exists(ControlCheck check | check.protects(checkout, event, "untrusted-checkout"))
|
||||
not exists(ControlCheck check | check.protects(step, event, "untrusted-checkout"))
|
||||
)
|
||||
select step, checkout, step, "Execution of untrusted code on a privileged workflow."
|
||||
select step, checkout, step, "Execution of untrusted code on a privileged workflow. $@", event,
|
||||
event.getLocation().getFile().toString()
|
||||
|
||||
@@ -23,8 +23,7 @@ where
|
||||
// the checkout is NOT followed by a known poisonable step
|
||||
not checkout.getAFollowingStep() instanceof PoisonableStep and
|
||||
// the checkout occurs in a privileged context
|
||||
inPrivilegedContext(checkout) and
|
||||
event = checkout.getEnclosingJob().getATriggerEvent() and
|
||||
inPrivilegedContext(checkout, event) and
|
||||
(
|
||||
// issue_comment: check for date comparison checks and actor/access control checks
|
||||
event.getName() = "issue_comment" and
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
|
||||
import actions
|
||||
import codeql.actions.security.UntrustedCheckoutQuery
|
||||
import codeql.actions.security.PoisonableSteps
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from PRHeadCheckoutStep checkout
|
||||
where
|
||||
|
||||
@@ -438,7 +438,6 @@ subpaths
|
||||
| .github/workflows/composite-action-caller-3.yml:12:19:12:50 | github.event.comment.body | .github/actions/action5/action.yml:4:3:4:7 | input taint | .github/actions/action5/action.yml:9:3:14:46 | output Job outputs node [result] | .github/workflows/composite-action-caller-3.yml:9:9:13:6 | Uses Step: foo [result] |
|
||||
| .github/workflows/composite-action-caller-4.yml:14:19:14:56 | github.event.pull_request.title | .github/reusable_workflows/TestOrg/TestRepo/.github/actions/clone-repo/action.yaml:4:3:4:7 | input title | .github/reusable_workflows/TestOrg/TestRepo/.github/actions/clone-repo/action.yaml:14:3:16:45 | output Job outputs node [result] | .github/workflows/composite-action-caller-4.yml:10:9:17:6 | Uses Step: clone [result] |
|
||||
#select
|
||||
| .github/actions/action1/action.yml:7:19:7:55 | github.event.pull_request.body | .github/actions/action1/action.yml:7:19:7:55 | github.event.pull_request.body | .github/actions/action1/action.yml:7:19:7:55 | github.event.pull_request.body | Potential code injection in $@, which may be controlled by an external user. | .github/actions/action1/action.yml:7:19:7:55 | github.event.pull_request.body | ${{ github.event.pull_request.body }} |
|
||||
| .github/actions/action3/action.yml:9:19:9:55 | github.event.pull_request.body | .github/actions/action3/action.yml:9:19:9:55 | github.event.pull_request.body | .github/actions/action3/action.yml:9:19:9:55 | github.event.pull_request.body | Potential code injection in $@, which may be controlled by an external user. | .github/actions/action3/action.yml:9:19:9:55 | github.event.pull_request.body | ${{ github.event.pull_request.body }} |
|
||||
| .github/actions/action4/action.yml:7:19:7:55 | github.event.pull_request.body | .github/actions/action4/action.yml:7:19:7:55 | github.event.pull_request.body | .github/actions/action4/action.yml:7:19:7:55 | github.event.pull_request.body | Potential code injection in $@, which may be controlled by an external user. | .github/actions/action4/action.yml:7:19:7:55 | github.event.pull_request.body | ${{ github.event.pull_request.body }} |
|
||||
| .github/workflows/changed-files.yml:20:24:20:76 | steps.changed-files1.outputs.all_changed_files | .github/workflows/changed-files.yml:15:9:18:6 | Uses Step: changed-files1 | .github/workflows/changed-files.yml:20:24:20:76 | steps.changed-files1.outputs.all_changed_files | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/changed-files.yml:20:24:20:76 | steps.changed-files1.outputs.all_changed_files | ${{ steps.changed-files1.outputs.all_changed_files }} |
|
||||
|
||||
@@ -246,37 +246,42 @@ edges
|
||||
| .github/workflows/untrusted_checkout.yml:16:9:20:6 | Uses Step | .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step |
|
||||
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step |
|
||||
#select
|
||||
| .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/poc2.yml:52:9:58:24 | Run Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test5.yml:32:9:34:2 | Run Step | .github/workflows/test5.yml:28:9:32:6 | Uses Step | .github/workflows/test5.yml:32:9:34:2 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test5.yml:58:9:60:2 | Run Step | .github/workflows/test5.yml:54:9:58:6 | Uses Step | .github/workflows/test5.yml:58:9:60:2 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test5.yml:68:9:68:43 | Run Step | .github/workflows/test5.yml:64:9:68:6 | Uses Step | .github/workflows/test5.yml:68:9:68:43 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test7.yml:33:9:36:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test7.yml:36:9:39:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test7.yml:49:9:58:20 | Run Step: benchmark-pr | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:58:20 | Run Step: benchmark-pr | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test10.yml:25:9:30:2 | Run Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/test11.yml:90:7:93:54 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout4.yml:61:7:67:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:61:7:67:4 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout4.yml:67:7:73:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:67:7:73:4 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout4.yml:73:7:79:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:73:7:79:4 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | .github/workflows/untrusted_checkout.yml:10:9:13:6 | Uses Step | .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | .github/workflows/untrusted_checkout.yml:13:9:16:6 | Uses Step | .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | Execution of untrusted code on a privileged workflow. |
|
||||
| .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/reusable_workflows/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | .github/workflows/reusable_caller1.yaml |
|
||||
| .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | .github/workflows/actor_trusted_checkout.yml:9:7:14:4 | Uses Step | .github/workflows/actor_trusted_checkout.yml:15:7:19:4 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/actor_trusted_checkout.yml:2:3:2:21 | pull_request_target | .github/workflows/actor_trusted_checkout.yml |
|
||||
| .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | .github/workflows/auto_ci.yml |
|
||||
| .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:48:9:52:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | .github/workflows/auto_ci.yml |
|
||||
| .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | .github/workflows/auto_ci.yml |
|
||||
| .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | .github/workflows/auto_ci.yml |
|
||||
| .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | .github/workflows/dependabot3.yml |
|
||||
| .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | .github/workflows/gitcheckout.yml |
|
||||
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:3:3:3:8 | issues | .github/workflows/level0.yml |
|
||||
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:5:3:5:15 | issue_comment | .github/workflows/level0.yml |
|
||||
| .github/workflows/level0.yml:107:9:112:2 | Run Step | .github/workflows/level0.yml:99:9:103:6 | Uses Step | .github/workflows/level0.yml:107:9:112:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | .github/workflows/level0.yml |
|
||||
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:3:3:3:8 | issues | .github/workflows/level0.yml |
|
||||
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:5:3:5:15 | issue_comment | .github/workflows/level0.yml |
|
||||
| .github/workflows/level0.yml:133:9:135:23 | Run Step | .github/workflows/level0.yml:125:9:129:6 | Uses Step | .github/workflows/level0.yml:133:9:135:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/level0.yml:7:3:7:21 | pull_request_target | .github/workflows/level0.yml |
|
||||
| .github/workflows/poc2.yml:42:9:47:6 | Uses Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:42:9:47:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | .github/workflows/poc2.yml |
|
||||
| .github/workflows/poc2.yml:52:9:58:24 | Run Step | .github/workflows/poc2.yml:37:9:42:6 | Uses Step | .github/workflows/poc2.yml:52:9:58:24 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/poc2.yml:4:3:4:15 | issue_comment | .github/workflows/poc2.yml |
|
||||
| .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | .github/workflows/pr-workflow.yml:216:9:222:6 | Uses Step | .github/workflows/pr-workflow.yml:222:9:227:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | .github/workflows/pr-workflow.yml:250:9:256:6 | Uses Step | .github/workflows/pr-workflow.yml:256:9:261:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | .github/workflows/pr-workflow.yml:284:9:290:6 | Uses Step | .github/workflows/pr-workflow.yml:290:9:295:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:391:9:395:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:395:9:404:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:404:9:414:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:414:9:423:6 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | .github/workflows/pr-workflow.yml:386:9:391:6 | Uses Step | .github/workflows/pr-workflow.yml:423:9:432:2 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/pr-workflow-fork.yaml:7:3:7:21 | pull_request_target | .github/workflows/pr-workflow-fork.yaml |
|
||||
| .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | .github/workflows/reusable_local.yml:23:9:26:6 | Uses Step | .github/workflows/reusable_local.yml:26:9:29:7 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/reusable_caller3.yaml:4:3:4:21 | pull_request_target | .github/workflows/reusable_caller3.yaml |
|
||||
| .github/workflows/test5.yml:32:9:34:2 | Run Step | .github/workflows/test5.yml:28:9:32:6 | Uses Step | .github/workflows/test5.yml:32:9:34:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test5.yml:4:3:4:15 | issue_comment | .github/workflows/test5.yml |
|
||||
| .github/workflows/test5.yml:58:9:60:2 | Run Step | .github/workflows/test5.yml:54:9:58:6 | Uses Step | .github/workflows/test5.yml:58:9:60:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test5.yml:4:3:4:15 | issue_comment | .github/workflows/test5.yml |
|
||||
| .github/workflows/test5.yml:68:9:68:43 | Run Step | .github/workflows/test5.yml:64:9:68:6 | Uses Step | .github/workflows/test5.yml:68:9:68:43 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test5.yml:4:3:4:15 | issue_comment | .github/workflows/test5.yml |
|
||||
| .github/workflows/test7.yml:33:9:36:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:33:9:36:6 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test7.yml:4:3:4:15 | issue_comment | .github/workflows/test7.yml |
|
||||
| .github/workflows/test7.yml:36:9:39:6 | Run Step | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:36:9:39:6 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test7.yml:4:3:4:15 | issue_comment | .github/workflows/test7.yml |
|
||||
| .github/workflows/test7.yml:49:9:58:20 | Run Step: benchmark-pr | .github/workflows/test7.yml:19:9:24:6 | Uses Step | .github/workflows/test7.yml:49:9:58:20 | Run Step: benchmark-pr | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test7.yml:4:3:4:15 | issue_comment | .github/workflows/test7.yml |
|
||||
| .github/workflows/test10.yml:25:9:30:2 | Run Step | .github/workflows/test10.yml:20:9:25:6 | Uses Step | .github/workflows/test10.yml:25:9:30:2 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test10.yml:8:3:8:21 | pull_request_target | .github/workflows/test10.yml |
|
||||
| .github/workflows/test11.yml:90:7:93:54 | Uses Step | .github/workflows/test11.yml:84:7:90:4 | Uses Step | .github/workflows/test11.yml:90:7:93:54 | Uses Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/test11.yml:5:3:5:15 | issue_comment | .github/workflows/test11.yml |
|
||||
| .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | .github/actions/dangerous-git-checkout/action.yml:6:7:11:4 | Uses Step | .github/workflows/untrusted_checkout3.yml:13:9:13:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout3.yml:4:3:4:14 | workflow_run | .github/workflows/untrusted_checkout3.yml |
|
||||
| .github/workflows/untrusted_checkout4.yml:61:7:67:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:61:7:67:4 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout4.yml:4:3:4:15 | issue_comment | .github/workflows/untrusted_checkout4.yml |
|
||||
| .github/workflows/untrusted_checkout4.yml:67:7:73:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:67:7:73:4 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout4.yml:4:3:4:15 | issue_comment | .github/workflows/untrusted_checkout4.yml |
|
||||
| .github/workflows/untrusted_checkout4.yml:73:7:79:4 | Run Step | .github/workflows/untrusted_checkout4.yml:55:7:61:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:73:7:79:4 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout4.yml:4:3:4:15 | issue_comment | .github/workflows/untrusted_checkout4.yml |
|
||||
| .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | .github/workflows/untrusted_checkout.yml:10:9:13:6 | Uses Step | .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | .github/workflows/untrusted_checkout.yml |
|
||||
| .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | .github/workflows/untrusted_checkout.yml:13:9:16:6 | Uses Step | .github/workflows/untrusted_checkout.yml:20:9:22:23 | Run Step | Execution of untrusted code on a privileged workflow. $@ | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | .github/workflows/untrusted_checkout.yml |
|
||||
|
||||
Reference in New Issue
Block a user