Merge pull request #12978 from asgerf/js/github-actions-sources

JS: Add sources and sinks related to GitHub Actions
This commit is contained in:
Asger F
2023-05-10 09:55:24 +02:00
committed by GitHub
11 changed files with 220 additions and 0 deletions

View File

@@ -67,6 +67,7 @@ import semmle.javascript.YAML
import semmle.javascript.dataflow.DataFlow
import semmle.javascript.dataflow.TaintTracking
import semmle.javascript.dataflow.TypeInference
import semmle.javascript.frameworks.ActionsLib
import semmle.javascript.frameworks.Angular2
import semmle.javascript.frameworks.AngularJS
import semmle.javascript.frameworks.Anser

View File

@@ -0,0 +1,82 @@
/**
* Contains models for `@actions/core` related libraries.
*/
private import javascript
private import semmle.javascript.security.dataflow.IndirectCommandInjectionCustomizations
private API::Node payload() {
result = API::moduleImport("@actions/github").getMember("context").getMember("payload")
}
private API::Node workflowRun() { result = payload().getMember("workflow_run") }
private API::Node commitObj() {
result = workflowRun().getMember("head_commit")
or
result = payload().getMember("commits").getAMember()
}
private API::Node pullRequest() {
result = payload().getMember("pull_request")
or
result = commitObj().getMember("pull_requests").getAMember()
}
private API::Node taintSource() {
result = pullRequest().getMember("head").getMember(["ref", "label"])
or
result =
[pullRequest(), payload().getMember(["discussion", "issue"])].getMember(["title", "body"])
or
result = payload().getMember(["review", "review_comment", "comment"]).getMember("body")
or
result = workflowRun().getMember(["head_branch", "display_title"])
or
result = workflowRun().getMember("head_repository").getMember("description")
or
result = commitObj().getMember("message")
or
result = commitObj().getMember(["author", "committer"]).getMember(["name", "email"])
}
/**
* A source of taint originating from the context.
*/
private class GitHubActionsContextSource extends RemoteFlowSource {
GitHubActionsContextSource() { this = taintSource().asSource() }
override string getSourceType() { result = "GitHub Actions context" }
}
/**
* A source of taint originating from user input.
*
* At the momemnt this is only treated as a taint source for the indirect-command injection
* query.
*/
private class GitHubActionsInputSource extends IndirectCommandInjection::Source {
GitHubActionsInputSource() {
this =
API::moduleImport("@actions/core")
.getMember(["getInput", "getMultilineInput"])
.getReturn()
.asSource()
}
override string describe() { result = "GitHub Actions user input" }
}
private class ExecActionsCall extends SystemCommandExecution, DataFlow::CallNode {
ExecActionsCall() {
this = API::moduleImport("@actions/exec").getMember(["exec", "getExecOutput"]).getACall()
}
override DataFlow::Node getACommandArgument() { result = this.getArgument(0) }
override DataFlow::Node getArgumentList() { result = this.getArgument(1) }
override DataFlow::Node getOptionsArg() { result = this.getArgument(2) }
override predicate isSync() { none() }
}

View File

@@ -49,6 +49,38 @@ module IndirectCommandInjection {
override string describe() { result = "environment variable" }
}
/** Gets a data flow node referring to `process.env`. */
private DataFlow::SourceNode envObject(DataFlow::TypeTracker t) {
t.start() and
result = NodeJSLib::process().getAPropertyRead("env")
or
exists(DataFlow::TypeTracker t2 | result = envObject(t2).track(t2, t))
}
/** Gets a data flow node referring to `process.env`. */
private DataFlow::SourceNode envObject() { result = envObject(DataFlow::TypeTracker::end()) }
/**
* Gets the name of an environment variable that is assumed to be safe.
*/
private string getASafeEnvironmentVariable() {
result =
[
"GITHUB_ACTION", "GITHUB_ACTION_PATH", "GITHUB_ACTION_REPOSITORY", "GITHUB_ACTIONS",
"GITHUB_ACTOR", "GITHUB_API_URL", "GITHUB_BASE_REF", "GITHUB_ENV", "GITHUB_EVENT_NAME",
"GITHUB_EVENT_PATH", "GITHUB_GRAPHQL_URL", "GITHUB_JOB", "GITHUB_PATH", "GITHUB_REF",
"GITHUB_REPOSITORY", "GITHUB_REPOSITORY_OWNER", "GITHUB_RUN_ID", "GITHUB_RUN_NUMBER",
"GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKFLOW", "GITHUB_WORKSPACE"
]
}
/** Sanitizer that blocks flow through safe environment variables. */
private class SafeEnvVariableSanitizer extends Sanitizer {
SafeEnvVariableSanitizer() {
this = envObject().getAPropertyRead(getASafeEnvironmentVariable())
}
}
/**
* An object containing parsed command-line arguments, considered as a flow source for command injection.
*/