Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag up functionality that may not exist in default setup workflows #1678

Merged
merged 9 commits into from
May 31, 2023
2 changes: 1 addition & 1 deletion lib/actions-util.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/actions-util.js.map

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions queries/codeql-pack.lock.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
lockVersion: 1.0.0
dependencies:
codeql-javascript:
version: 0.6.1
codeql/regex:
version: 0.0.12
codeql/tutorial:
version: 0.0.9
codeql/util:
version: 0.0.9
codeql/yaml:
version: 0.0.1
compiled: false
4 changes: 2 additions & 2 deletions queries/qlpack.yml → queries/codeql-pack.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: codeql-action-custom-queries-javascript
version: 0.0.0
libraryPathDependencies: codeql-javascript

dependencies:
codeql/javascript-all: 0.6.1
henrymercer marked this conversation as resolved.
Show resolved Hide resolved
52 changes: 52 additions & 0 deletions queries/default-setup-environment-variables.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @name Some environment variables may not exist in default setup workflows
* @id javascript/codeql-action/default-setup-env-vars
* @kind problem
* @severity warning
*/

import javascript

bindingset[envVar]
predicate isSafeForDefaultSetup(string envVar) {
// Ignore internal Code Scanning environment variables
envVar.matches("CODE_SCANNING_%") or
envVar.matches("CODEQL_%") or
envVar.matches("CODESCANNING_%") or
envVar.matches("LGTM_%") or
// We flag up usage of potentially unsafe parts of the GitHub event in `default-setup-event-context.ql`.
envVar = "GITHUB_EVENT_PATH" or
// The following environment variables are known to be safe for use with default setup
envVar =
[
"GITHUB_ACTION_REF", "GITHUB_ACTION_REPOSITORY", "GITHUB_ACTOR", "GITHUB_API_URL",
"GITHUB_BASE_REF", "GITHUB_EVENT_NAME", "GITHUB_JOB", "GITHUB_RUN_ATTEMPT", "GITHUB_RUN_ID",
"GITHUB_SHA", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_TOKEN", "GITHUB_WORKFLOW",
"GITHUB_WORKSPACE", "GOFLAGS", "JAVA_TOOL_OPTIONS", "RUNNER_ARCH", "RUNNER_NAME", "RUNNER_OS",
"RUNNER_TEMP", "RUNNER_TOOL_CACHE"
]
}

predicate envVarRead(DataFlow::Node node, string envVar) {
node =
any(DataFlow::PropRead read |
read = NodeJSLib::process().getAPropertyRead("env").getAPropertyRead() and
envVar = read.getPropertyName()
) or
node =
any(DataFlow::CallNode call |
call.getCalleeName().matches("get%EnvParam") and
envVar = call.getArgument(0).getStringValue()
)
}

from DataFlow::Node read, string envVar
where
envVarRead(read, envVar) and
not isSafeForDefaultSetup(envVar)
select read,
"The environment variable " + envVar +
" may not exist in default setup workflows. If all uses are safe, add it to the list of " +
"environment variables that are known to be safe in " +
"'queries/default-setup-environment-variables.ql'. If this use is safe but others are not, " +
"dismiss this alert as a false positive."
58 changes: 58 additions & 0 deletions queries/default-setup-event-context.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* @name Some context properties may not exist in default setup workflows
* @id javascript/codeql-action/default-setup-context-properties
* @kind path-problem
* @severity warning
*/

import javascript
import DataFlow::PathGraph

class NotParsedLabel extends DataFlow::FlowLabel {
NotParsedLabel() { this = "not-parsed" }
}

class ParsedLabel extends DataFlow::FlowLabel {
ParsedLabel() { this = "parsed" }
}

class EventContextAccessConfiguration extends DataFlow::Configuration {
EventContextAccessConfiguration() { this = "EventContextAccessConfiguration" }

override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
source = NodeJSLib::process().getAPropertyRead("env").getAPropertyRead("GITHUB_EVENT_PATH") and
lbl instanceof NotParsedLabel
}

override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
sink instanceof DataFlow::PropRead and
lbl instanceof ParsedLabel and
not exists(DataFlow::PropRead n | sink = n.getBase()) and
not sink.asExpr().getFile().getBaseName().matches("%.test.ts")
}

override predicate isAdditionalFlowStep(
DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
) {
src = trg.(FileSystemReadAccess).getAPathArgument() and inlbl = outlbl
or
exists(JsonParserCall c |
src = c.getInput() and
trg = c.getOutput() and
inlbl instanceof NotParsedLabel and
outlbl instanceof ParsedLabel
)
or
(
TaintTracking::sharedTaintStep(src, trg) or
DataFlow::SharedFlowStep::step(src, trg) or
DataFlow::SharedFlowStep::step(src, trg, _, _)
) and
inlbl = outlbl
}
}

from EventContextAccessConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"This event context property may not exist in default setup workflows."
16 changes: 9 additions & 7 deletions queries/inconsistent-action-input.ql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* must be defined in an identical way to avoid confusion for the user.
* This also makes writing queries like required-action-input.ql easier.
* @kind problem
* @problem.severity error
* @severity error
* @id javascript/codeql-action/inconsistent-action-input
*/

Expand All @@ -15,7 +15,9 @@ import javascript
*/
class ActionDeclaration extends File {
ActionDeclaration() {
getRelativePath().matches("%/action.yml")
getRelativePath().matches("%/action.yml") and
// Ignore internal Actions
not getRelativePath().matches(".github/actions/%")
}

/**
Expand All @@ -25,19 +27,19 @@ class ActionDeclaration extends File {
result = getRelativePath().regexpCapture("(.*)/action.yml", 1)
}

YAMLDocument getRootNode() {
YamlDocument getRootNode() {
result.getFile() = this
}

YAMLValue getInput(string inputName) {
result = getRootNode().(YAMLMapping).lookup("inputs").(YAMLMapping).lookup(inputName)
YamlValue getInput(string inputName) {
result = getRootNode().(YamlMapping).lookup("inputs").(YamlMapping).lookup(inputName)
}
}

predicate areNotEquivalent(YAMLValue x, YAMLValue y) {
predicate areNotEquivalent(YamlValue x, YamlValue y) {
x.getTag() != y.getTag()
or
x.(YAMLScalar).getValue() != y.(YAMLScalar).getValue()
x.(YamlScalar).getValue() != y.(YamlScalar).getValue()
or
x.getNumChild() != y.getNumChild()
or
Expand Down
2 changes: 1 addition & 1 deletion src/actions-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ export async function isAnalyzingDefaultBranch(): Promise<boolean> {
let defaultBranch = event?.repository?.default_branch;

if (process.env.GITHUB_EVENT_NAME === "schedule") {
defaultBranch = removeRefsHeadsPrefix(getRequiredEnvParam("GITHUB_REF"));
defaultBranch = removeRefsHeadsPrefix(getRefFromEnv());
}

return currentRef === defaultBranch;
Expand Down