Merge pull request #5350 from JarLob/actions

github actions queries
This commit is contained in:
Erik Krogh Kristensen
2021-03-18 14:46:25 +01:00
committed by GitHub
26 changed files with 952 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Using user-controlled input in GitHub Actions may lead to
code injection in contexts like <i>run:</i> or <i>script:</i>.
</p>
</overview>
<recommendation>
<p>
The best practice to avoid code injection vulnerabilities
in GitHub workflows is to set the untrusted input value of the expression
to an intermediate environment variable.
</p>
</recommendation>
<example>
<p>
The following example lets a user inject an arbitrary shell command:
</p>
<sample src="examples/comment_issue_bad.yml" />
<p>
The following example uses shell syntax to read
the environment variable and will prevent the attack:
</p>
<sample src="examples/comment_issue_good.yml" />
</example>
<references>
<li>GitHub Security Lab Research: <a href="https://securitylab.github.com/research/github-actions-untrusted-input">Keeping your GitHub Actions and workflows secure: Untrusted input</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,93 @@
/**
* @name Expression injection in Actions
* @description Using user-controlled GitHub Actions contexts like `run:` or `script:` may allow a malicious
* user to inject code into the GitHub action.
* @kind problem
* @problem.severity error
* @precision high
* @id js/actions/injection
* @tags actions
* security
* external/cwe/cwe-094
*/
import javascript
import experimental.semmle.javascript.Actions
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")
}
bindingset[context]
private predicate isExternalUserControlledPullRequest(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*title\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*body\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*label\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*repo\\s*\\.\\s*default_branch\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pull_request\\s*\\.\\s*head\\s*\\.\\s*ref\\b")
}
bindingset[context]
private predicate isExternalUserControlledReview(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*review\\s*\\.\\s*body\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*review_comment\\s*\\.\\s*body\\b")
}
bindingset[context]
private predicate isExternalUserControlledComment(string context) {
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*comment\\s*\\.\\s*body\\b")
}
bindingset[context]
private predicate isExternalUserControlledGollum(string context) {
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*pages(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*page_name\\b")
}
bindingset[context]
private predicate isExternalUserControlledCommit(string context) {
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*message\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*message\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*author\\s*\\.\\s*email\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*head_commit\\s*\\.\\s*author\\s*\\.\\s*name\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*author\\s*\\.\\s*email\\b") or
context
.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*author\\s*\\.\\s*name\\b") or
context.regexpMatch("\\bgithub\\s*\\.\\s*head_ref\\b")
}
from Actions::Run run, string context, Actions::On on
where
run.getAReferencedExpression() = context and
run.getStep().getJob().getWorkflow().getOn() = on and
(
exists(on.getNode("issues")) and
isExternalUserControlledIssue(context)
or
exists(on.getNode("pull_request_target")) and
isExternalUserControlledPullRequest(context)
or
(exists(on.getNode("pull_request_review_comment")) or exists(on.getNode("pull_request_review"))) and
isExternalUserControlledReview(context)
or
(exists(on.getNode("issue_comment")) or exists(on.getNode("pull_request_target"))) and
isExternalUserControlledComment(context)
or
exists(on.getNode("gollum")) and
isExternalUserControlledGollum(context)
or
exists(on.getNode("pull_request_target")) and
isExternalUserControlledCommit(context)
)
select run,
"Potential injection from the " + context +
" context, which may be controlled by an external user."

View File

@@ -0,0 +1,64 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Combining <i>pull_request_target</i> workflow trigger with an explicit checkout
of an untrusted pull request is a dangerous practice
that may lead to repository compromise.
</p>
</overview>
<recommendation>
<p>
The best practice is to handle the potentially untrusted pull request
via the <i>pull_request</i> trigger so that it is isolated in
an unprivileged environment. The workflow processing the pull request
should then store any results like code coverage or failed/passed tests
in artifacts and exit. The following workflow then starts on <i>workflow_run</i>
where it is granted write permission to the target repository and access to
repository secrets, so that it can download the artifacts and make
any necessary modifications to the repository or interact with third party services
that require repository secrets (e.g. API tokens).
</p>
</recommendation>
<example>
<p>
The following example allows unauthorized repository modification
and secrets exfiltration:
</p>
<sample src="examples/pull_request_target_bad.yml" />
<p>
The following example uses two workflows to handle potentially untrusted
pull request in a secure manner. The receive_pr.yml is triggered first:
</p>
<sample src="examples/receive_pr.yml" />
<p>The comment_pr.yml is triggered after receive_pr.yml completes:</p>
<sample src="examples/comment_pr.yml" />
</example>
<references>
<li>GitHub Security Lab Research: <a href="https://securitylab.github.com/research/github-actions-preventing-pwn-requests">Keeping your GitHub Actions and workflows secure: Preventing pwn requests</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,122 @@
/**
* @name Checkout of untrusted code in trusted context
* @description Workflows triggered on `pull_request_target` have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.
* @kind problem
* @problem.severity warning
* @precision low
* @id js/actions/pull_request_target
* @tags actions
* security
* external/cwe/cwe-094
*/
import javascript
import experimental.semmle.javascript.Actions
/**
* Action step that doesn't contain `actor` or `label` check in `if:` or
* the check requires manual analysis.
*/
class ProbableStep extends Actions::Step {
// some simplistic checks to eleminate likely false positives:
ProbableStep() {
// no if at all
not exists(this.getIf().getValue())
or
// needs manual analysis if there is OR
this.getIf().getValue().matches("%||%")
or
// labels can be assigned by owners only
not exists(
this.getIf()
.getValue()
.regexpFind("\\bcontains\\s*\\(\\s*github\\s*\\.\\s*event\\s*\\.\\s*(?:issue|pull_request)\\s*\\.\\s*labels\\b",
_, _)
) and
not exists(
this.getIf()
.getValue()
.regexpFind("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*label\\s*\\.\\s*name\\s*==", _, _)
) and
// actor check means only the user is able to run it
not exists(this.getIf().getValue().regexpFind("\\bgithub\\s*\\.\\s*actor\\s*==", _, _))
}
}
/**
* Action job that doesn't contain `actor` or `label` check in `if:` or
* the check requires manual analysis.
*/
class ProbableJob extends Actions::Job {
// some simplistic checks to eleminate likely false positives:
ProbableJob() {
// no if at all
not exists(this.getIf().getValue())
or
// needs manual analysis if there is OR
this.getIf().getValue().matches("%||%")
or
// labels can be assigned by owners only
not exists(
this.getIf()
.getValue()
.regexpFind("\\bcontains\\s*\\(\\s*github\\s*\\.\\s*event\\s*\\.\\s*(?:issue|pull_request)\\s*\\.\\s*labels\\b",
_, _)
) and
not exists(
this.getIf()
.getValue()
.regexpFind("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*label\\s*\\.\\s*name\\s*==", _, _)
) and
// actor check means only the user is able to run it
not exists(this.getIf().getValue().regexpFind("\\bgithub\\s*\\.\\s*actor\\s*==", _, _))
}
}
/**
* Action step that doesn't contain `actor` or `label` check in `if:` or
*/
class ProbablePullRequestTarget extends Actions::On, Actions::MappingOrSequenceOrScalar {
ProbablePullRequestTarget() {
exists(YAMLNode prtNode |
// The `on:` is triggered on `pull_request_target`
this.getNode("pull_request_target") = prtNode and
(
// and either doesn't contain `types` filter
not exists(prtNode.getAChild())
or
// or has the filter, that is something else than just [labeled]
exists(Actions::MappingOrSequenceOrScalar prt, Actions::MappingOrSequenceOrScalar types |
types = prt.getNode("types") and
prtNode = prt and
(
not types.getElementCount() = 1 or
not exists(types.getNode("labeled"))
)
)
)
)
}
}
from
Actions::Ref ref, Actions::Uses uses, Actions::Step step, Actions::Job job,
ProbablePullRequestTarget pullRequestTarget
where
pullRequestTarget.getWorkflow() = job.getWorkflow() and
uses.getStep() = step and
ref.getWith().getStep() = step and
step.getJob() = job and
uses.getGitHubRepository() = "actions/checkout" and
(
ref.getValue().matches("%github.event.pull_request.head.ref%") or
ref.getValue().matches("%github.event.pull_request.head.sha%") or
ref.getValue().matches("%github.event.pull_request.number%") or
ref.getValue().matches("%github.event.number%") or
ref.getValue().matches("%github.head_ref%")
) and
step instanceof ProbableStep and
job instanceof ProbableJob
select step, "Potential unsafe checkout of untrusted pull request on `pull_request_target`"

View File

@@ -0,0 +1,8 @@
on: issue_comment
jobs:
echo-body:
runs-on: ubuntu-latest
steps:
- run: |
echo '${{ github.event.comment.body }}'

View File

@@ -0,0 +1,10 @@
on: issue_comment
jobs:
echo-body:
runs-on: ubuntu-latest
steps:
- env:
BODY: ${{ github.event.issue.body }}
run: |
echo '$BODY'

View File

@@ -0,0 +1,52 @@
name: Comment on the pull request
# read-write repo token
# access to secrets
on:
workflow_run:
workflows: ["Receive PR"]
types:
- completed
jobs:
upload:
runs-on: ubuntu-latest
if: >
${{ github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success' }}
steps:
- name: 'Download artifact'
uses: actions/github-script@v3.1.0
with:
script: |
var artifacts = await github.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr"
})[0];
var download = await github.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
- run: unzip pr.zip
- name: 'Comment on PR'
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
var fs = require('fs');
var issue_number = Number(fs.readFileSync('./NR'));
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
body: 'Everything is OK. Thank you for the PR!'
});

View File

@@ -0,0 +1,25 @@
on:
pull_request_target
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
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!

View File

@@ -0,0 +1,26 @@
name: Receive PR
# read-only repo token
# no access to secrets
on:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# imitation of a build process
- name: Build
run: /bin/bash ./build.sh
- name: Save PR number
run: |
mkdir -p ./pr
echo ${{ github.event.number }} > ./pr/NR
- uses: actions/upload-artifact@v2
with:
name: pr
path: pr/

View File

@@ -0,0 +1,316 @@
/**
* Libraries for modelling GitHub Actions workflow files written in YAML.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions.
*/
import javascript
/**
* Libraries for modelling GitHub Actions workflow files written in YAML.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions.
*/
module Actions {
/** A YAML node in a GitHub Actions workflow file. */
private class Node extends YAMLNode {
Node() {
this.getLocation()
.getFile()
.getRelativePath()
.matches(["experimental/Security/CWE-094/.github/workflows/%", ".github/workflows/%"])
}
}
/**
* Actions are quite flexible in parsing YAML.
*
* For example:
* ```
* on: pull_request
* ```
* and
* ```
* on: [pull_request]
* ```
* and
* ```
* on:
* pull_request:
* ```
*
* are equivalent.
*/
class MappingOrSequenceOrScalar extends YAMLNode {
MappingOrSequenceOrScalar() {
this instanceof YAMLMapping
or
this instanceof YAMLSequence
or
this instanceof YAMLScalar
}
YAMLNode getNode(string name) {
exists(YAMLMapping mapping |
mapping = this and
result = mapping.lookup(name)
)
or
exists(YAMLSequence sequence, YAMLNode node |
sequence = this and
sequence.getAChildNode() = node and
node.eval().toString() = name and
result = node
)
or
exists(YAMLScalar scalar |
scalar = this and
scalar.getValue() = name and
result = scalar
)
}
int getElementCount() {
exists(YAMLMapping mapping |
mapping = this and
result = mapping.getNumChild() / 2
)
or
exists(YAMLSequence sequence |
sequence = this and
result = sequence.getNumChild()
)
or
exists(YAMLScalar scalar |
scalar = this and
result = 1
)
}
}
/**
* An Actions workflow. This is a mapping at the top level of an Actions YAML workflow file.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions.
*/
class Workflow extends Node, YAMLDocument, YAMLMapping {
/** Gets the `jobs` mapping from job IDs to job definitions in this workflow. */
YAMLMapping getJobs() { result = this.lookup("jobs") }
/** Gets the name of the workflow file. */
string getFileName() { result = this.getFile().getBaseName() }
/** Gets the `on:` in this workflow. */
On getOn() { result = this.lookup("on") }
/** Gets the job within this workflow with the given job ID. */
Job getJob(string jobId) { result.getWorkflow() = this and result.getId() = jobId }
}
/**
* An Actions On trigger within a workflow.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#on.
*/
class On extends YAMLNode, MappingOrSequenceOrScalar {
Workflow workflow;
On() { workflow.lookup("on") = this }
Workflow getWorkflow() { result = workflow }
}
/**
* An Actions job within a workflow.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobs.
*/
class Job extends YAMLNode, YAMLMapping {
string jobId;
Workflow workflow;
Job() { this = workflow.getJobs().lookup(jobId) }
/**
* Gets the ID of this job, as a string.
* This is the job's key within the `jobs` mapping.
*/
string getId() { result = jobId }
/**
* Gets the ID of this job, as a YAML scalar node.
* This is the job's key within the `jobs` mapping.
*/
YAMLString getIdNode() { workflow.getJobs().maps(result, this) }
/** Gets the human-readable name of this job, if any, as a string. */
string getName() { result = this.getNameNode().getValue() }
/** Gets the human-readable name of this job, if any, as a YAML scalar node. */
YAMLString getNameNode() { result = this.lookup("name") }
/** Gets the step at the given index within this job. */
Step getStep(int index) { result.getJob() = this and result.getIndex() = index }
/** Gets the sequence of `steps` within this job. */
YAMLSequence getSteps() { result = this.lookup("steps") }
/** Gets the workflow this job belongs to. */
Workflow getWorkflow() { result = workflow }
/** Gets the value of the `if` field in this job, if any. */
JobIf getIf() { result.getJob() = this }
}
/**
* An `if` within a job.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idif.
*/
class JobIf extends YAMLNode, YAMLScalar {
Job job;
JobIf() { job.lookup("if") = this }
/** Gets the step this field belongs to. */
Job getJob() { result = job }
}
/**
* A step within an Actions job.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idsteps.
*/
class Step extends YAMLNode, YAMLMapping {
int index;
Job job;
Step() { this = job.getSteps().getElement(index) }
/** Gets the 0-based position of this step within the sequence of `steps`. */
int getIndex() { result = index }
/** Gets the job this step belongs to. */
Job getJob() { result = job }
/** Gets the value of the `uses` field in this step, if any. */
Uses getUses() { result.getStep() = this }
/** Gets the value of the `run` field in this step, if any. */
Run getRun() { result.getStep() = this }
/** Gets the value of the `if` field in this step, if any. */
StepIf getIf() { result.getStep() = this }
}
/**
* An `if` within a step.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsif.
*/
class StepIf extends YAMLNode, YAMLScalar {
Step step;
StepIf() { step.lookup("if") = this }
/** Gets the step this field belongs to. */
Step getStep() { result = step }
}
/**
* A `uses` field within an Actions job step, which references an action as a reusable unit of code.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsuses.
*
* For example:
* ```
* uses: actions/checkout@v2
* ```
* TODO: Does not currently handle local repository references, e.g. `.github/actions/action-name`.
*/
class Uses extends YAMLNode, YAMLScalar {
Step step;
/** The owner of the repository where the Action comes from, e.g. `actions` in `actions/checkout@v2`. */
string repositoryOwner;
/** The name of the repository where the Action comes from, e.g. `checkout` in `actions/checkout@v2`. */
string repositoryName;
/** The version reference used when checking out the Action, e.g. `v2` in `actions/checkout@v2`. */
string version;
Uses() {
step.lookup("uses") = this and
// Simple regular expression to split up an Action reference `owner/repo@version` into its components.
exists(string regexp | regexp = "([^/]+)/([^/@]+)@(.+)" |
repositoryOwner = this.getValue().regexpCapture(regexp, 1) and
repositoryName = this.getValue().regexpCapture(regexp, 2) and
version = this.getValue().regexpCapture(regexp, 3)
)
}
/** Gets the step this field belongs to. */
Step getStep() { result = step }
/** Gets the owner and name of the repository where the Action comes from, e.g. `actions/checkout` in `actions/checkout@v2`. */
string getGitHubRepository() { result = repositoryOwner + "/" + repositoryName }
/** Gets the version reference used when checking out the Action, e.g. `v2` in `actions/checkout@v2`. */
string getVersion() { result = version }
}
/**
* A `with` field within an Actions job step, which references an action as a reusable unit of code.
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepswith.
*
* For example:
* ```
* with:
* arg1: 1
* arg2: abc
* ```
*/
class With extends YAMLNode, YAMLMapping {
Step step;
With() { step.lookup("with") = this }
/** Gets the step this field belongs to. */
Step getStep() { result = step }
}
/**
* A `ref:` field within an Actions `with:` specific to `actions/checkout` action.
*
* For example:
* ```
* uses: actions/checkout@v2
* with:
* ref: ${{ github.event.pull_request.head.sha }}
* ```
*/
class Ref extends YAMLNode, YAMLString {
With with;
Ref() { with.lookup("ref") = this }
With getWith() { result = with }
}
/**
* A `run` field within an Actions job step, which runs command-line programs using an operating system shell.
* See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsrun.
*/
class Run extends YAMLNode, YAMLString {
Step step;
Run() { step.lookup("run") = this }
/** Gets the step that executes this `run` command. */
Step getStep() { result = step }
/**
* Holds if `${{ e }}` is a GitHub Actions expression evaluated within this `run` command.
* See https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions.
*/
string getAReferencedExpression() {
// We use `regexpFind` to obtain *all* matches of `${{...}}`,
// not just the last (greedy match) or first (reluctant match).
// TODO: This only handles expression strings that refer to contexts.
// It does not handle operators within the expression.
result =
this.getValue()
.regexpFind("\\$\\{\\{\\s*[A-Za-z0-9_\\.\\-]+\\s*\\}\\}", _, _)
.regexpCapture("\\$\\{\\{\\s*([A-Za-z0-9_\\.\\-]+)\\s*\\}\\}", 1)
}
}
}

View File

@@ -0,0 +1,8 @@
on: issue_comment
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- run: |
echo '${{ github.event.comment.body }}'

View File

@@ -0,0 +1,38 @@
on:
pull_request_target:
jobs:
job1:
if: contains(github.event.issue.labels.*.name, 'ok')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
job2:
if: github.event.label.name == 'ok'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
job3:
if: github.actor == 'ok'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
job4:
if: github.actor == 'ok' || true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
job5:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,31 @@
on:
pull_request_target:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
if: contains(github.event.issue.labels.*.name, 'ok')
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/checkout@v2
if: github.event.label.name == 'ok'
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/checkout@v2
if: github.actor == 'ok'
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/checkout@v2
if: github.actor == 'ok' || true
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,12 @@
on:
pull_request_target:
types: [labeled]
push:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,13 @@
on:
pull_request_target:
types:
labeled:
push:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,15 @@
on:
pull_request_target:
types:
labeled:
opened:
closed:
push:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,12 @@
on:
pull_request_target:
types: [labeled, opened]
push:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,10 @@
on:
pull_request_target:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1,10 @@
on:
pull_request_target:
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: master

View File

@@ -0,0 +1,11 @@
on: pull_request_target
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
- run: make

View File

@@ -0,0 +1,9 @@
on: [pull_request_target, push]
jobs:
echo-chamber:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}

View File

@@ -0,0 +1 @@
| .github/workflows/comment_issue.yml:7:12:8:47 | \| | Potential injection from the github.event.comment.body context, which may be controlled by an external user. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE-094/ExpressionInjection.ql

View File

@@ -0,0 +1,9 @@
| .github/workflows/pull_request_target_if_job.yml:30:7:33:2 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_if_job.yml:36:7:38:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_if_step.yml:24:7:29:4 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_if_step.yml:29:7:31:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_labels_mapping.yml:13:7:15:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_labels_sequence.yml:10:7:12:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_mapping.yml:8:7:10:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_run.yml:7:7:11:4 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |
| .github/workflows/pull_request_target_sequence.yml:7:7:9:54 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on `pull_request_target` |

View File

@@ -0,0 +1 @@
experimental/Security/CWE-094/UntrustedCheckout.ql

View File

@@ -0,0 +1 @@
console.log('test')