mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #12748 from JarLob/yi
JS: Add more sources, more unit tests, fixes to the GitHub Actions injection query
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved the queries for injection vulnerabilities in GitHub Actions workflows (`js/actions/command-injection` and `js/actions/pull-request-target`) and the associated library `semmle.javascript.Actions`. These now support steps defined in composite actions, in addition to steps defined in Actions workflow files. It supports more potentially untrusted input values. Additionally to the shell injections it now also detects injections in `actions/github-script`. It also detects simple injections from user controlled `${{ env.name }}`. Additionally to the `yml` extension now it also supports workflows with the `yaml` extension.
|
||||
@@ -10,16 +10,70 @@ import javascript
|
||||
* See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions.
|
||||
*/
|
||||
module Actions {
|
||||
/** A YAML node in a GitHub Actions workflow file. */
|
||||
/** A YAML node in a GitHub Actions workflow or a custom composite action file. */
|
||||
private class Node extends YamlNode {
|
||||
Node() {
|
||||
this.getLocation()
|
||||
.getFile()
|
||||
.getRelativePath()
|
||||
.regexpMatch("(^|.*/)\\.github/workflows/.*\\.yml$")
|
||||
exists(File f |
|
||||
f = this.getLocation().getFile() and
|
||||
(
|
||||
f.getRelativePath().regexpMatch("(^|.*/)\\.github/workflows/.*\\.ya?ml$")
|
||||
or
|
||||
f.getBaseName() = ["action.yml", "action.yaml"]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom composite action. This is a mapping at the top level of an Actions YAML action file.
|
||||
* See https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions.
|
||||
*/
|
||||
class CompositeAction extends Node, YamlDocument, YamlMapping {
|
||||
CompositeAction() {
|
||||
this.getFile().getBaseName() = ["action.yml", "action.yaml"] and
|
||||
this.lookup("runs").(YamlMapping).lookup("using").(YamlScalar).getValue() = "composite"
|
||||
}
|
||||
|
||||
/** Gets the `runs` mapping. */
|
||||
Runs getRuns() { result = this.lookup("runs") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `runs` mapping in a custom composite action YAML.
|
||||
* See https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs
|
||||
*/
|
||||
class Runs extends StepsContainer {
|
||||
CompositeAction action;
|
||||
|
||||
Runs() { action.lookup("runs") = this }
|
||||
|
||||
/** Gets the action that this `runs` mapping is in. */
|
||||
CompositeAction getAction() { result = action }
|
||||
|
||||
/** Gets the `using` mapping. */
|
||||
Using getUsing() { result = this.lookup("using") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The parent class of the class that can contain `steps` mappings. (`Job` or `Runs` currently.)
|
||||
*/
|
||||
abstract class StepsContainer extends YamlNode, YamlMapping {
|
||||
/** Gets the sequence of `steps` within this YAML node. */
|
||||
YamlSequence getSteps() { result = this.lookup("steps") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `using` mapping in a custom composite action YAML.
|
||||
*/
|
||||
class Using extends YamlNode, YamlScalar {
|
||||
Runs runs;
|
||||
|
||||
Using() { runs.lookup("using") = this }
|
||||
|
||||
/** Gets the `runs` mapping that this `using` mapping is in. */
|
||||
Runs getRuns() { result = runs }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -28,6 +82,9 @@ module Actions {
|
||||
/** Gets the `jobs` mapping from job IDs to job definitions in this workflow. */
|
||||
YamlMapping getJobs() { result = this.lookup("jobs") }
|
||||
|
||||
/** Gets the 'global' `env` mapping in this workflow. */
|
||||
WorkflowEnv getEnv() { result = this.lookup("env") }
|
||||
|
||||
/** Gets the name of the workflow. */
|
||||
string getName() { result = this.lookup("name").(YamlString).getValue() }
|
||||
|
||||
@@ -54,11 +111,44 @@ module Actions {
|
||||
Workflow getWorkflow() { result = workflow }
|
||||
}
|
||||
|
||||
/** A common class for `env` in workflow, job or step. */
|
||||
abstract class Env extends YamlNode, YamlMapping { }
|
||||
|
||||
/** A workflow level `env` mapping. */
|
||||
class WorkflowEnv extends Env {
|
||||
Workflow workflow;
|
||||
|
||||
WorkflowEnv() { workflow.lookup("env") = this }
|
||||
|
||||
/** Gets the workflow this field belongs to. */
|
||||
Workflow getWorkflow() { result = workflow }
|
||||
}
|
||||
|
||||
/** A job level `env` mapping. */
|
||||
class JobEnv extends Env {
|
||||
Job job;
|
||||
|
||||
JobEnv() { job.lookup("env") = this }
|
||||
|
||||
/** Gets the job this field belongs to. */
|
||||
Job getJob() { result = job }
|
||||
}
|
||||
|
||||
/** A step level `env` mapping. */
|
||||
class StepEnv extends Env {
|
||||
Step step;
|
||||
|
||||
StepEnv() { step.lookup("env") = this }
|
||||
|
||||
/** Gets the step this field belongs to. */
|
||||
Step getStep() { result = step }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
class Job extends StepsContainer {
|
||||
string jobId;
|
||||
Workflow workflow;
|
||||
|
||||
@@ -85,8 +175,8 @@ module Actions {
|
||||
/** 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 `env` mapping in this job. */
|
||||
JobEnv getEnv() { result = this.lookup("env") }
|
||||
|
||||
/** Gets the workflow this job belongs to. */
|
||||
Workflow getWorkflow() { result = workflow }
|
||||
@@ -130,15 +220,18 @@ module Actions {
|
||||
*/
|
||||
class Step extends YamlNode, YamlMapping {
|
||||
int index;
|
||||
Job job;
|
||||
StepsContainer parent;
|
||||
|
||||
Step() { this = job.getSteps().getElement(index) }
|
||||
Step() { this = parent.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 `job` this step belongs to, if the step belongs to a `job` in a workflow. Has no result if the step belongs to `runs` in a custom composite action. */
|
||||
Job getJob() { result = parent }
|
||||
|
||||
/** Gets the `runs` this step belongs to, if the step belongs to a `runs` in a custom composite action. Has no result if the step belongs to a `job` in a workflow. */
|
||||
Runs getRuns() { result = parent }
|
||||
|
||||
/** Gets the value of the `uses` field in this step, if any. */
|
||||
Uses getUses() { result.getStep() = this }
|
||||
@@ -149,6 +242,9 @@ module Actions {
|
||||
/** Gets the value of the `if` field in this step, if any. */
|
||||
StepIf getIf() { result.getStep() = this }
|
||||
|
||||
/** Gets the value of the `env` field in this step, if any. */
|
||||
StepEnv getEnv() { result = this.lookup("env") }
|
||||
|
||||
/** Gets the ID of this step, if any. */
|
||||
string getId() { result = this.lookup("id").(YamlString).getValue() }
|
||||
}
|
||||
@@ -244,6 +340,25 @@ module Actions {
|
||||
With getWith() { result = with }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 node) {
|
||||
// We use `regexpFind` to obtain *all* matches of `${{...}}`,
|
||||
// not just the last (greedy match) or first (reluctant match).
|
||||
result =
|
||||
node.getValue()
|
||||
.regexpFind("\\$\\{\\{\\s*[A-Za-z0-9_\\[\\]\\*\\(\\)\\.\\-]+\\s*\\}\\}", _, _)
|
||||
.regexpCapture("\\$\\{\\{\\s*([A-Za-z0-9_\\[\\]\\*\\((\\)\\.\\-]+)\\s*\\}\\}", 1)
|
||||
}
|
||||
|
||||
/** Extracts the 'name' part from env.name */
|
||||
bindingset[name]
|
||||
string getEnvName(string name) { result = name.regexpCapture("env\\.([A-Za-z0-9_]+)", 1) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -255,20 +370,5 @@ module Actions {
|
||||
|
||||
/** 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.
|
||||
* 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() {
|
||||
// We use `regexpFind` to obtain *all* matches of `${{...}}`,
|
||||
// not just the last (greedy match) or first (reluctant match).
|
||||
result =
|
||||
this.getValue()
|
||||
.regexpFind("\\$\\{\\{\\s*[A-Za-z0-9_\\.\\-]+\\s*\\}\\}", _, _)
|
||||
.regexpCapture("\\$\\{\\{\\s*([A-Za-z0-9_\\.\\-]+)\\s*\\}\\}", 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
code injection in contexts like <i>run:</i> or <i>script:</i>.
|
||||
</p>
|
||||
<p>
|
||||
Code injection in GitHub Actions may allow an attacker to
|
||||
exfiltrate the temporary GitHub repository authorization token.
|
||||
Code injection in GitHub Actions may allow an attacker to
|
||||
exfiltrate any secrets used in the workflow and
|
||||
the temporary GitHub repository authorization token.
|
||||
The token might have write access to the repository, allowing an attacker
|
||||
to use the token to make changes to the repository.
|
||||
to use the token to make changes to the repository.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
@@ -19,7 +20,8 @@
|
||||
<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.
|
||||
to an intermediate environment variable and then use the environment variable
|
||||
using the native syntax of the shell/script interpreter (that is, not <i>${{ env.VAR }}</i>).
|
||||
</p>
|
||||
<p>
|
||||
It is also recommended to limit the permissions of any tokens used
|
||||
@@ -33,6 +35,12 @@
|
||||
</p>
|
||||
<sample src="examples/comment_issue_bad.yml" />
|
||||
|
||||
<p>
|
||||
The following example uses an environment variable, but
|
||||
<b>still allows the injection</b> because of the use of expression syntax:
|
||||
</p>
|
||||
<sample src="examples/comment_issue_bad_env.yml" />
|
||||
|
||||
<p>
|
||||
The following example uses shell syntax to read
|
||||
the environment variable and will prevent the attack:
|
||||
|
||||
@@ -15,6 +15,44 @@
|
||||
import javascript
|
||||
import semmle.javascript.Actions
|
||||
|
||||
/**
|
||||
* A `script:` field within an Actions `with:` specific to `actions/github-script` action.
|
||||
*
|
||||
* For example:
|
||||
* ```
|
||||
* uses: actions/github-script@v3
|
||||
* with:
|
||||
* script: console.log('${{ github.event.pull_request.head.sha }}')
|
||||
* ```
|
||||
*/
|
||||
class GitHubScript extends YamlNode, YamlString {
|
||||
GitHubScriptWith with;
|
||||
|
||||
GitHubScript() { with.lookup("script") = this }
|
||||
|
||||
/** Gets the `with` field this field belongs to. */
|
||||
GitHubScriptWith getWith() { result = with }
|
||||
}
|
||||
|
||||
/**
|
||||
* A step that uses `actions/github-script` action.
|
||||
*/
|
||||
class GitHubScriptStep extends Actions::Step {
|
||||
GitHubScriptStep() { this.getUses().getGitHubRepository() = "actions/github-script" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `with:` field sibling to `uses: actions/github-script`.
|
||||
*/
|
||||
class GitHubScriptWith extends YamlNode, YamlMapping {
|
||||
GitHubScriptStep step;
|
||||
|
||||
GitHubScriptWith() { step.lookup("with") = this }
|
||||
|
||||
/** Gets the step this field belongs to. */
|
||||
GitHubScriptStep getStep() { result = step }
|
||||
}
|
||||
|
||||
bindingset[context]
|
||||
private predicate isExternalUserControlledIssue(string context) {
|
||||
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*issue\\s*\\.\\s*title\\b") or
|
||||
@@ -30,7 +68,10 @@ private predicate isExternalUserControlledPullRequest(string context) {
|
||||
"\\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"
|
||||
]
|
||||
|
|
||||
context.regexpMatch(reg)
|
||||
@@ -39,8 +80,7 @@ private predicate isExternalUserControlledPullRequest(string context) {
|
||||
|
||||
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")
|
||||
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*review\\s*\\.\\s*body\\b")
|
||||
}
|
||||
|
||||
bindingset[context]
|
||||
@@ -51,7 +91,8 @@ private predicate isExternalUserControlledComment(string context) {
|
||||
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")
|
||||
.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")
|
||||
}
|
||||
|
||||
bindingset[context]
|
||||
@@ -59,13 +100,16 @@ private predicate isExternalUserControlledCommit(string context) {
|
||||
exists(string reg |
|
||||
reg =
|
||||
[
|
||||
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*message\\b",
|
||||
"\\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*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*author\\s*\\.\\s*email\\b",
|
||||
"\\bgithub\\s*\\.\\s*event\\s*\\.\\s*commits(?:\\[[0-9]\\]|\\s*\\.\\s*\\*)+\\s*\\.\\s*author\\s*\\.\\s*name\\b",
|
||||
"\\bgithub\\s*\\.\\s*head_ref\\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",
|
||||
]
|
||||
|
|
||||
context.regexpMatch(reg)
|
||||
@@ -78,32 +122,149 @@ private predicate isExternalUserControlledDiscussion(string context) {
|
||||
context.regexpMatch("\\bgithub\\s*\\.\\s*event\\s*\\.\\s*discussion\\s*\\.\\s*body\\b")
|
||||
}
|
||||
|
||||
from Actions::Run run, string context, Actions::On on
|
||||
where
|
||||
run.getASimpleReferenceExpression() = 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)
|
||||
or
|
||||
(exists(on.getNode("discussion")) or exists(on.getNode("discussion_comment"))) and
|
||||
isExternalUserControlledDiscussion(context)
|
||||
bindingset[context]
|
||||
private predicate isExternalUserControlledWorkflowRun(string context) {
|
||||
exists(string reg |
|
||||
reg =
|
||||
[
|
||||
"\\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",
|
||||
]
|
||||
|
|
||||
context.regexpMatch(reg)
|
||||
)
|
||||
select run,
|
||||
"Potential injection from the " + context +
|
||||
" context, which may be controlled by an external user."
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if environment name in the `injection` (in a form of `env.name`)
|
||||
* is tainted by the `context` (in a form of `github.event.xxx.xxx`).
|
||||
*/
|
||||
bindingset[injection]
|
||||
predicate isEnvInterpolationTainted(string injection, string context) {
|
||||
exists(Actions::Env env, string envName, YamlString envValue |
|
||||
envValue = env.lookup(envName) and
|
||||
Actions::getEnvName(injection) = envName and
|
||||
Actions::getASimpleReferenceExpression(envValue) = context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `run` contains any expression interpolation `${{ e }}`.
|
||||
* Sets `context` to the initial untrusted value assignment in case of `${{ env... }}` interpolation
|
||||
*/
|
||||
predicate isRunInjectable(Actions::Run run, string injection, string context) {
|
||||
Actions::getASimpleReferenceExpression(run) = injection and
|
||||
(
|
||||
injection = context
|
||||
or
|
||||
isEnvInterpolationTainted(injection, context)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `actions/github-script` contains any expression interpolation `${{ e }}`.
|
||||
* Sets `context` to the initial untrusted value assignment in case of `${{ env... }}` interpolation
|
||||
*/
|
||||
predicate isScriptInjectable(GitHubScript script, string injection, string context) {
|
||||
Actions::getASimpleReferenceExpression(script) = injection and
|
||||
(
|
||||
injection = context
|
||||
or
|
||||
isEnvInterpolationTainted(injection, context)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the composite action contains untrusted expression interpolation `${{ e }}`.
|
||||
*/
|
||||
YamlNode getInjectableCompositeActionNode(Actions::Runs runs, string injection, string context) {
|
||||
exists(Actions::Run run |
|
||||
isRunInjectable(run, injection, context) and
|
||||
result = run and
|
||||
run.getStep().getRuns() = runs
|
||||
)
|
||||
or
|
||||
exists(GitHubScript script |
|
||||
isScriptInjectable(script, injection, context) and
|
||||
result = script and
|
||||
script.getWith().getStep().getRuns() = runs
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the workflow contains untrusted expression interpolation `${{ e }}`.
|
||||
*/
|
||||
YamlNode getInjectableWorkflowNode(Actions::On on, string injection, string context) {
|
||||
exists(Actions::Run run |
|
||||
isRunInjectable(run, injection, context) and
|
||||
result = run and
|
||||
run.getStep().getJob().getWorkflow().getOn() = on
|
||||
)
|
||||
or
|
||||
exists(GitHubScript script |
|
||||
isScriptInjectable(script, injection, context) and
|
||||
result = script and
|
||||
script.getWith().getStep().getJob().getWorkflow().getOn() = on
|
||||
)
|
||||
}
|
||||
|
||||
from YamlNode node, string injection, string context
|
||||
where
|
||||
exists(Actions::CompositeAction action, Actions::Runs runs |
|
||||
action.getRuns() = runs and
|
||||
node = getInjectableCompositeActionNode(runs, injection, context) and
|
||||
(
|
||||
isExternalUserControlledIssue(context) or
|
||||
isExternalUserControlledPullRequest(context) or
|
||||
isExternalUserControlledReview(context) or
|
||||
isExternalUserControlledComment(context) or
|
||||
isExternalUserControlledGollum(context) or
|
||||
isExternalUserControlledCommit(context) or
|
||||
isExternalUserControlledDiscussion(context) or
|
||||
isExternalUserControlledWorkflowRun(context)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Actions::On on |
|
||||
node = getInjectableWorkflowNode(on, injection, context) 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")) and
|
||||
(isExternalUserControlledReview(context) or isExternalUserControlledPullRequest(context))
|
||||
or
|
||||
exists(on.getNode("pull_request_review_comment")) and
|
||||
(isExternalUserControlledComment(context) or isExternalUserControlledPullRequest(context))
|
||||
or
|
||||
exists(on.getNode("issue_comment")) and
|
||||
(isExternalUserControlledComment(context) or isExternalUserControlledIssue(context))
|
||||
or
|
||||
exists(on.getNode("gollum")) and
|
||||
isExternalUserControlledGollum(context)
|
||||
or
|
||||
exists(on.getNode("push")) and
|
||||
isExternalUserControlledCommit(context)
|
||||
or
|
||||
exists(on.getNode("discussion")) and
|
||||
isExternalUserControlledDiscussion(context)
|
||||
or
|
||||
exists(on.getNode("discussion_comment")) and
|
||||
(isExternalUserControlledDiscussion(context) or isExternalUserControlledComment(context))
|
||||
or
|
||||
exists(on.getNode("workflow_run")) and
|
||||
isExternalUserControlledWorkflowRun(context)
|
||||
)
|
||||
)
|
||||
select node,
|
||||
"Potential injection from the ${{ " + injection +
|
||||
" }}, which may be controlled by an external user."
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
on: issue_comment
|
||||
|
||||
jobs:
|
||||
echo-body:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- env:
|
||||
BODY: ${{ github.event.issue.body }}
|
||||
run: |
|
||||
echo '${{ env.BODY }}'
|
||||
@@ -17,7 +17,7 @@ import javascript
|
||||
import semmle.javascript.Actions
|
||||
|
||||
/**
|
||||
* An action step that doesn't contain `actor` or `label` check in `if:` or
|
||||
* An action step that doesn't contain `actor` check in `if:` or
|
||||
* the check requires manual analysis.
|
||||
*/
|
||||
class ProbableStep extends Actions::Step {
|
||||
@@ -29,25 +29,13 @@ class ProbableStep extends Actions::Step {
|
||||
// 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*==", _, _))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An action job that doesn't contain `actor` or `label` check in `if:` or
|
||||
* An action job that doesn't contain `actor` check in `if:` or
|
||||
* the check requires manual analysis.
|
||||
*/
|
||||
class ProbableJob extends Actions::Job {
|
||||
@@ -59,46 +47,18 @@ class ProbableJob extends Actions::Job {
|
||||
// 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*==", _, _))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An action step that doesn't contain `actor` or `label` check in `if:` or
|
||||
* The `on: pull_request_target`.
|
||||
*/
|
||||
class ProbablePullRequestTarget extends Actions::On, YamlMappingLikeNode {
|
||||
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(YamlMappingLikeNode prt, YamlMappingLikeNode types |
|
||||
types = prt.getNode("types") and
|
||||
prtNode = prt and
|
||||
(
|
||||
not types.getElementCount() = 1 or
|
||||
not exists(types.getNode("labeled"))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
// The `on:` is triggered on `pull_request_target`
|
||||
exists(this.getNode("pull_request_target"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
| .github/workflows/pull_request_target_if_job.yml:9:7:12:2 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on 'pull_request_target'. |
|
||||
| .github/workflows/pull_request_target_if_job.yml:16:7:19:2 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on 'pull_request_target'. |
|
||||
| .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:9:7:14:4 | uses: a ... kout@v2 | Potential unsafe checkout of untrusted pull request on 'pull_request_target'. |
|
||||
| .github/workflows/pull_request_target_if_step.yml:14:7:19:4 | 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_label_only.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_label_only_mapping.yml:11:7:13: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'. |
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
console.log('test')
|
||||
@@ -10,5 +10,19 @@ jobs:
|
||||
echo-chamber2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo '${{ github.event.comment.body }}'
|
||||
- run: echo '${{ github.event.comment.body }}'
|
||||
- run: echo '${{ github.event.issue.body }}'
|
||||
- run: echo '${{ github.event.issue.title }}'
|
||||
|
||||
echo-chamber3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v3
|
||||
with:
|
||||
script: console.log('${{ github.event.comment.body }}')
|
||||
- uses: actions/github-script@v3
|
||||
with:
|
||||
script: console.log('${{ github.event.issue.body }}')
|
||||
- uses: actions/github-script@v3
|
||||
with:
|
||||
script: console.log('${{ github.event.issue.title }}')
|
||||
@@ -0,0 +1,8 @@
|
||||
on: discussion
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.discussion.title }}'
|
||||
- run: echo '${{ github.event.discussion.body }}'
|
||||
@@ -0,0 +1,9 @@
|
||||
on: discussion_comment
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.discussion.title }}'
|
||||
- run: echo '${{ github.event.discussion.body }}'
|
||||
- run: echo '${{ github.event.comment.body }}'
|
||||
11
javascript/ql/test/query-tests/Security/CWE-094/ExpressionInjection/.github/workflows/gollum.yml
vendored
Normal file
11
javascript/ql/test/query-tests/Security/CWE-094/ExpressionInjection/.github/workflows/gollum.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
on: gollum
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.pages[1].title }}'
|
||||
- run: echo '${{ github.event.pages[11].title }}'
|
||||
- run: echo '${{ github.event.pages[0].page_name }}'
|
||||
- run: echo '${{ github.event.pages[2222].page_name }}'
|
||||
- run: echo '${{ toJSON(github.event.pages.*.title) }}' # safe
|
||||
@@ -0,0 +1,20 @@
|
||||
on: issues
|
||||
|
||||
env:
|
||||
global_env: ${{ github.event.issue.title }}
|
||||
test: test
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
env:
|
||||
job_env: ${{ github.event.issue.title }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.issue.title }}'
|
||||
- run: echo '${{ github.event.issue.body }}'
|
||||
- run: echo '${{ env.global_env }}'
|
||||
- run: echo '${{ env.test }}'
|
||||
- run: echo '${{ env.job_env }}'
|
||||
- run: echo '${{ env.step_env }}'
|
||||
env:
|
||||
step_env: ${{ github.event.issue.title }}
|
||||
@@ -0,0 +1,14 @@
|
||||
on: pull_request_review
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.pull_request.title }}'
|
||||
- run: echo '${{ github.event.pull_request.body }}'
|
||||
- run: echo '${{ github.event.pull_request.head.label }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.default_branch }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.description }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.homepage }}'
|
||||
- run: echo '${{ github.event.pull_request.head.ref }}'
|
||||
- run: echo '${{ github.event.review.body }}'
|
||||
@@ -0,0 +1,14 @@
|
||||
on: pull_request_review_comment
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.pull_request.title }}'
|
||||
- run: echo '${{ github.event.pull_request.body }}'
|
||||
- run: echo '${{ github.event.pull_request.head.label }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.default_branch }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.description }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.homepage }}'
|
||||
- run: echo '${{ github.event.pull_request.head.ref }}'
|
||||
- run: echo '${{ github.event.comment.body }}'
|
||||
@@ -0,0 +1,16 @@
|
||||
on: pull_request_target
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.issue.title }}' # not defined
|
||||
- run: echo '${{ github.event.issue.body }}' # not defined
|
||||
- run: echo '${{ github.event.pull_request.title }}'
|
||||
- run: echo '${{ github.event.pull_request.body }}'
|
||||
- run: echo '${{ github.event.pull_request.head.label }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.default_branch }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.description }}'
|
||||
- run: echo '${{ github.event.pull_request.head.repo.homepage }}'
|
||||
- run: echo '${{ github.event.pull_request.head.ref }}'
|
||||
- run: echo '${{ github.head_ref }}'
|
||||
16
javascript/ql/test/query-tests/Security/CWE-094/ExpressionInjection/.github/workflows/push.yml
vendored
Normal file
16
javascript/ql/test/query-tests/Security/CWE-094/ExpressionInjection/.github/workflows/push.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.commits[11].message }}'
|
||||
- run: echo '${{ github.event.commits[11].author.email }}'
|
||||
- run: echo '${{ github.event.commits[11].author.name }}'
|
||||
- run: echo '${{ github.event.head_commit.message }}'
|
||||
- run: echo '${{ github.event.head_commit.author.email }}'
|
||||
- run: echo '${{ github.event.head_commit.author.name }}'
|
||||
- run: echo '${{ github.event.head_commit.committer.email }}'
|
||||
- run: echo '${{ github.event.head_commit.committer.name }}'
|
||||
- run: echo '${{ github.event.commits[11].committer.email }}'
|
||||
- run: echo '${{ github.event.commits[11].committer.name }}'
|
||||
@@ -0,0 +1,16 @@
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [test]
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.workflow_run.display_title }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_commit.message }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_commit.author.email }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_commit.author.name }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_commit.committer.email }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_commit.committer.name }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_branch }}'
|
||||
- run: echo '${{ github.event.workflow_run.head_repository.description }}'
|
||||
@@ -1,3 +1,65 @@
|
||||
| .github/workflows/comment_issue.yml:7:12:8:48 | \| | Potential injection from the github.event.comment.body context, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:13:12:14:47 | \| | Potential injection from the github.event.comment.body context, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue_newline.yml:9:14:10:50 | \| | Potential injection from the github.event.comment.body context, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:7:12:8:48 | \| | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:13:12:13:50 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:14:12:14:48 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.issue.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:15:12:15:49 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.issue.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:22:17:22:63 | console ... dy }}') | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:25:17:25:61 | console ... dy }}') | Potential injection from the ${{ github.event.issue.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue.yml:28:17:28:62 | console ... le }}') | Potential injection from the ${{ github.event.issue.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/comment_issue_newline.yml:9:14:10:50 | \| | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/discussion.yml:7:12:7:54 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.discussion.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/discussion.yml:8:12:8:53 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.discussion.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/discussion_comment.yml:7:12:7:54 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.discussion.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/discussion_comment.yml:8:12:8:53 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.discussion.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/discussion_comment.yml:9:12:9:50 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/gollum.yml:7:12:7:52 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.pages[1].title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/gollum.yml:8:12:8:53 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.pages[11].title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/gollum.yml:9:12:9:56 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.pages[0].page_name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/gollum.yml:10:12:10:59 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.pages[2222].page_name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/issues.yaml:13:12:13:49 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.issue.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/issues.yaml:14:12:14:48 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.issue.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/issues.yaml:15:12:15:39 | echo '$ ... env }}' | Potential injection from the ${{ env.global_env }}, which may be controlled by an external user. |
|
||||
| .github/workflows/issues.yaml:17:12:17:36 | echo '$ ... env }}' | Potential injection from the ${{ env.job_env }}, which may be controlled by an external user. |
|
||||
| .github/workflows/issues.yaml:18:12:18:37 | echo '$ ... env }}' | Potential injection from the ${{ env.step_env }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:7:12:7:56 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.pull_request.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:8:12:8:55 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.pull_request.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:9:12:9:61 | echo '$ ... bel }}' | Potential injection from the ${{ github.event.pull_request.head.label }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:10:12:10:75 | echo '$ ... nch }}' | Potential injection from the ${{ github.event.pull_request.head.repo.default_branch }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:11:12:11:72 | echo '$ ... ion }}' | Potential injection from the ${{ github.event.pull_request.head.repo.description }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:12:12:12:69 | echo '$ ... age }}' | Potential injection from the ${{ github.event.pull_request.head.repo.homepage }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:13:12:13:59 | echo '$ ... ref }}' | Potential injection from the ${{ github.event.pull_request.head.ref }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review.yml:14:12:14:49 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.review.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:7:12:7:56 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.pull_request.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:8:12:8:55 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.pull_request.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:9:12:9:61 | echo '$ ... bel }}' | Potential injection from the ${{ github.event.pull_request.head.label }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:10:12:10:75 | echo '$ ... nch }}' | Potential injection from the ${{ github.event.pull_request.head.repo.default_branch }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:11:12:11:72 | echo '$ ... ion }}' | Potential injection from the ${{ github.event.pull_request.head.repo.description }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:12:12:12:69 | echo '$ ... age }}' | Potential injection from the ${{ github.event.pull_request.head.repo.homepage }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:13:12:13:59 | echo '$ ... ref }}' | Potential injection from the ${{ github.event.pull_request.head.ref }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_review_comment.yml:14:12:14:50 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:9:12:9:56 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.pull_request.title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:10:12:10:55 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.pull_request.body }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:11:12:11:61 | echo '$ ... bel }}' | Potential injection from the ${{ github.event.pull_request.head.label }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:12:12:12:75 | echo '$ ... nch }}' | Potential injection from the ${{ github.event.pull_request.head.repo.default_branch }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:13:12:13:72 | echo '$ ... ion }}' | Potential injection from the ${{ github.event.pull_request.head.repo.description }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:14:12:14:69 | echo '$ ... age }}' | Potential injection from the ${{ github.event.pull_request.head.repo.homepage }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:15:12:15:59 | echo '$ ... ref }}' | Potential injection from the ${{ github.event.pull_request.head.ref }}, which may be controlled by an external user. |
|
||||
| .github/workflows/pull_request_target.yml:16:12:16:40 | echo '$ ... ref }}' | Potential injection from the ${{ github.head_ref }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:7:12:7:57 | echo '$ ... age }}' | Potential injection from the ${{ github.event.commits[11].message }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:8:12:8:62 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.commits[11].author.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:9:12:9:61 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.commits[11].author.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:10:12:10:57 | echo '$ ... age }}' | Potential injection from the ${{ github.event.head_commit.message }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:11:12:11:62 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.head_commit.author.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:12:12:12:61 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.head_commit.author.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:13:12:13:65 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.head_commit.committer.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:14:12:14:64 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.head_commit.committer.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:15:12:15:65 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.commits[11].committer.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/push.yml:16:12:16:64 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.commits[11].committer.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:9:12:9:64 | echo '$ ... tle }}' | Potential injection from the ${{ github.event.workflow_run.display_title }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:10:12:10:70 | echo '$ ... age }}' | Potential injection from the ${{ github.event.workflow_run.head_commit.message }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:11:12:11:75 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.workflow_run.head_commit.author.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:12:12:12:74 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.workflow_run.head_commit.author.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:13:12:13:78 | echo '$ ... ail }}' | Potential injection from the ${{ github.event.workflow_run.head_commit.committer.email }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:14:12:14:77 | echo '$ ... ame }}' | Potential injection from the ${{ github.event.workflow_run.head_commit.committer.name }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:15:12:15:62 | echo '$ ... nch }}' | Potential injection from the ${{ github.event.workflow_run.head_branch }}, which may be controlled by an external user. |
|
||||
| .github/workflows/workflow_run.yml:16:12:16:78 | echo '$ ... ion }}' | Potential injection from the ${{ github.event.workflow_run.head_repository.description }}, which may be controlled by an external user. |
|
||||
| action1/action.yml:14:12:14:50 | echo '$ ... ody }}' | Potential injection from the ${{ github.event.comment.body }}, which may be controlled by an external user. |
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name: 'test'
|
||||
description: 'test'
|
||||
branding:
|
||||
icon: 'test'
|
||||
color: 'test'
|
||||
inputs:
|
||||
test:
|
||||
description: test
|
||||
required: false
|
||||
default: 'test'
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- run: echo '${{ github.event.comment.body }}'
|
||||
@@ -0,0 +1,17 @@
|
||||
name: 'Hello World'
|
||||
description: 'Greet someone and record the time'
|
||||
inputs:
|
||||
who-to-greet: # id of input
|
||||
description: 'Who to greet'
|
||||
required: true
|
||||
default: 'World'
|
||||
outputs:
|
||||
time: # id of output
|
||||
description: 'The time we greeted you'
|
||||
runs:
|
||||
using: 'docker'
|
||||
steps: # this is actually invalid, used to test we correctly identify composite actions
|
||||
- run: echo '${{ github.event.comment.body }}'
|
||||
image: 'Dockerfile'
|
||||
args:
|
||||
- ${{ inputs.who-to-greet }}
|
||||
@@ -1 +0,0 @@
|
||||
console.log('test')
|
||||
Reference in New Issue
Block a user