From 6a99845ecf46a81ae2a27d26c0ff76afb79e2994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Thu, 10 Oct 2024 22:22:56 +0200 Subject: [PATCH 1/6] Remove old code to handle redirections to GITHUB_ENV Redirections to GITHUB_ENV are better handled now by the Bash module ---- --- .../actions/dataflow/internal/DataFlowPrivate.qll | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll b/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll index 3226e41ba2f..4e4f580f070 100644 --- a/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll +++ b/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll @@ -266,21 +266,6 @@ predicate envCtxLocalStep(Node nodeFrom, Node nodeTo) { madSource(nodeFrom, _, "env." + astTo.getFieldName()) or astTo.getTarget() = astFrom - or - // e.g: - // - run: echo ISSUE_KEY=$(echo "${{ github.event.pull_request.title }}") >> $GITHUB_ENV - // - run: echo ${{ env.ISSUE_KEY }} - exists(Run run, string script, Expression expr, string line, string key, string value | - run.getScript() = script and - run.getAnScriptExpr() = expr and - line = script.splitAt("\n") and - key = line.regexpCapture("echo\\s+([^=]+)\\s*=(.*)>>\\s*\\$GITHUB_ENV", 1) and - value = line.regexpCapture("echo\\s+([^=]+)\\s*=(.*)>>\\s*\\$GITHUB_ENV", 2) and - value.indexOf(expr.getRawExpression()) > 0 and - key = astTo.getFieldName() and - expr = astFrom and - expr.getEnclosingWorkflow() = run.getEnclosingWorkflow() - ) ) ) } From d4a24dfdd15d66486194380f33f1cc15af581365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 11 Oct 2024 12:19:22 +0200 Subject: [PATCH 2/6] Refactor FlowSteps --- ql/lib/codeql/actions/dataflow/FlowSteps.qll | 326 +++--------------- ql/lib/codeql/actions/dataflow/TaintSteps.qll | 101 ++++++ .../dataflow/internal/DataFlowPrivate.qll | 6 +- .../internal/TaintTrackingPrivate.qll | 2 +- 4 files changed, 161 insertions(+), 274 deletions(-) create mode 100644 ql/lib/codeql/actions/dataflow/TaintSteps.qll diff --git a/ql/lib/codeql/actions/dataflow/FlowSteps.qll b/ql/lib/codeql/actions/dataflow/FlowSteps.qll index f43d1bdcd87..b0d98d2e659 100644 --- a/ql/lib/codeql/actions/dataflow/FlowSteps.qll +++ b/ql/lib/codeql/actions/dataflow/FlowSteps.qll @@ -3,120 +3,8 @@ */ private import actions -private import codeql.util.Unit private import codeql.actions.DataFlow private import codeql.actions.dataflow.FlowSources -private import codeql.actions.dataflow.ExternalFlow -private import codeql.actions.security.ArtifactPoisoningQuery -private import codeql.actions.security.OutputClobberingQuery -private import codeql.actions.security.UntrustedCheckoutQuery - -/** - * A unit class for adding additional taint steps. - * - * Extend this class to add additional taint steps that should apply to all - * taint configurations. - */ -class AdditionalTaintStep extends Unit { - /** - * Holds if the step from `node1` to `node2` should be considered a taint - * step for all configurations. - */ - abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); -} - -/** - * Holds if and environment variable is used, directly or indirectly, in a Run's step expression. - * Where the expression is a string captured from the Run's script. - */ -bindingset[var_name, expr] -predicate envToRunExpr(string var_name, Run run, string expr) { - // e.g. echo "FOO=$BODY" >> $GITHUB_ENV - // e.g. echo "FOO=${BODY}" >> $GITHUB_ENV - expr.matches("%$" + ["", "{", "ENV{"] + var_name + "%") - or - // e.g. echo "FOO=$(echo $BODY)" >> $GITHUB_ENV - expr.matches("$(echo %") and expr.indexOf(var_name) > 0 - or - // e.g. - // FOO=$(echo $BODY) - // echo "FOO=$FOO" >> $GITHUB_ENV - exists(string line, string var2_name, string var2_value | run.getScript().splitAt("\n") = line | - var2_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and - var2_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and - var2_value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") and - ( - expr.matches("%$" + ["", "{", "ENV{"] + var2_name + "%") - or - expr.matches("$(echo %") and expr.indexOf(var2_name) > 0 - ) - ) -} - -/** - * Holds if an environment variable is used, directly or indirectly, as an argument to a dangerous command - * in a Run step. - * Where the command is a string captured from the Run's script. - */ -bindingset[var_name] -predicate envToArgInjSink(string var_name, Run run, string command) { - exists(string argument, string line, string regexp, int command_group, int argument_group | - run.getScript().splitAt("\n") = line and - argumentInjectionSinksDataModel(regexp, command_group, argument_group) and - argument = line.regexpCapture(regexp, argument_group) and - command = line.regexpCapture(regexp, command_group) and - envToRunExpr(var_name, run, argument) and - exists(run.getInScopeEnvVarExpr(var_name)) - ) -} - -/** - * Holds if an env var is passed to a Run step and this Run step, writes its value to a special workflow file. - * - file is the name of the special workflow file: GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH - * - var_name is the name of the env var - * - run is the Run step - * - key is the name assigned in the special workflow file. - * e.g. FOO for `echo "FOO=$BODY" >> $GITHUB_ENV` - * e.g. FOO for `echo "FOO=$(echo $BODY)" >> $GITHUB_OUTPUT` - * e.g. path (special name) for `echo "$BODY" >> $GITHUB_PATH` - */ -bindingset[var_name] -predicate envToSpecialFile(string file, string var_name, Run run, string key) { - exists(string value | - ( - file = "GITHUB_ENV" and - run.getAWriteToGitHubEnv(key, value) - or - file = "GITHUB_OUTPUT" and - run.getAWriteToGitHubOutput(key, value) - or - file = "GITHUB_PATH" and - run.getAWriteToGitHubPath(value) and - key = "path" - ) and - envToRunExpr(var_name, run, value) - ) -} - -/** - * Holds if a Run step declares an environment variable, uses it in its script to set another env var. - * e.g. - * env: - * BODY: ${{ github.event.comment.body }} - * run: | - * echo "foo=$(echo $BODY)" >> $GITHUB_ENV - */ -predicate envToRunStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(Run run, string var_name | - run.getInScopeEnvVarExpr(var_name) = pred.asExpr() and - succ.asExpr() = run.getScriptScalar() and - ( - envToSpecialFile(["GITHUB_ENV", "GITHUB_OUTPUT", "GITHUB_PATH"], var_name, run, _) or - envToArgInjSink(var_name, run, _) or - exists(OutputClobberingSink n | n.asExpr() = run.getScriptScalar()) - ) - ) -} /** * Holds if a Run step declares an environment variable, uses it in its script and sets an output in its script. @@ -132,37 +20,61 @@ predicate envToRunStep(DataFlow::Node pred, DataFlow::Node succ) { * echo "::set-output name=step-output::$BODY" */ predicate envToOutputStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { - exists(Run run, string var_name, string key | - run.getInScopeEnvVarExpr(var_name) = pred.asExpr() and + exists(Run run, string var, string field | + run.getInScopeEnvVarExpr(var) = pred.asExpr() and succ.asExpr() = run and - envToSpecialFile("GITHUB_OUTPUT", var_name, run, key) and - c = any(DataFlow::FieldContent ct | ct.getName() = key) + Bash::envReachingGitHubFileWrite(run, var, "GITHUB_OUTPUT", field) and + c = any(DataFlow::FieldContent ct | ct.getName() = field) ) } predicate envToEnvStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { - exists(Run run, string var_name, string key, string value | - run.getAWriteToGitHubEnv(key, value) and - c = any(DataFlow::FieldContent ct | ct.getName() = key) and - pred.asExpr() = run.getInScopeEnvVarExpr(var_name) and + exists( + Run run, string var, string field //string key, string value | + | + run.getInScopeEnvVarExpr(var) = pred.asExpr() and // we store the taint on the enclosing job since the may not exist an implicit env attribute succ.asExpr() = run.getEnclosingJob() and - Bash::isBashParameterExpansion(value, var_name, _, _) + Bash::envReachingGitHubFileWrite(run, var, "GITHUB_ENV", field) and + c = any(DataFlow::FieldContent ct | ct.getName() = field) //and ) } -predicate controlledCWD(Step artifact) { - artifact instanceof UntrustedArtifactDownloadStep or - // This shoould be: - // artifact instanceof PRHeadCheckoutStep - // but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error - // so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround - // instead of using ActionsMutableRefCheckout and ActionsSHACheckout - artifact.(Uses).getCallee() = "actions/checkout" or - artifact instanceof GitMutableRefCheckout or - artifact instanceof GitSHACheckout or - artifact instanceof GhMutableRefCheckout or - artifact instanceof GhSHACheckout +/** + * A command whose output gets assigned to an environment variable or step output. + * - run: | + * echo "foo=$(cmd)" >> "$GITHUB_OUTPUT" + * - run: | + * foo=$(> "$GITHUB_OUTPUT" + */ +predicate commandToOutputStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { + exists(CommandSource source, Run run, string key, string cmd | + source.getCommand() = cmd and + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_OUTPUT", key) and + c = any(DataFlow::FieldContent ct | ct.getName() = key) and + pred.asExpr() = run.getScriptScalar() and + succ.asExpr() = run + ) +} + +/** + * A command whose output gets assigned to an environment variable or step output. + * - run: | + * echo "foo=$(cmd)" >> "$GITHUB_ENV" + * - run: | + * foo=$(> "$GITHUB_ENV" + */ +predicate commandToEnvStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { + exists(CommandSource source, Run run, string key, string cmd | + source.getCommand() = cmd and + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_ENV", key) and + c = any(DataFlow::FieldContent ct | ct.getName() = key) and + pred.asExpr() = run.getScriptScalar() and + // we store the taint on the enclosing job since there may not be an implicit env attribute + succ.asExpr() = run.getEnclosingJob() + ) } /** @@ -173,28 +85,12 @@ predicate controlledCWD(Step artifact) { * foo=$(> "$GITHUB_ENV" */ -predicate artifactToEnvStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { - exists(Run run, string key, string value, Step artifact | - controlledCWD(artifact) and - ( - // A file is read and its content is assigned to an env var - // - run: | - // foo=$(> "$GITHUB_ENV" - exists(string var_name, string file_read | - run.getAnAssignment(var_name, file_read) and - Bash::outputsPartialFileContent(run, file_read) and - envToRunExpr(var_name, run, value) and - run.getAWriteToGitHubEnv(key, value) - ) - or - // A file is read and its content is assigned to an output - // - run: echo "foo=$(> "$GITHUB_ENV" - run.getAWriteToGitHubEnv(key, value) and - Bash::outputsPartialFileContent(run, value) - ) and +predicate fileToEnvStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) { + exists(FileSource source, Run run, string key, string cmd | + source.asExpr().(Step).getAFollowingStep() = run and + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_ENV", key) and + Bash::outputsPartialFileContent(run, cmd) and c = any(DataFlow::FieldContent ct | ct.getName() = key) and - artifact.getAFollowingStep() = run and pred.asExpr() = run.getScriptScalar() and // we store the taint on the enclosing job since there may not be an implicit env attribute succ.asExpr() = run.getEnclosingJob() ) } - -/** - * A download artifact step followed by a step that may use downloaded artifacts. - */ -predicate artifactDownloadToRunStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(Step artifact, Run run | - controlledCWD(artifact) and - pred.asExpr() = artifact and - succ.asExpr() = run.getScriptScalar() and - artifact.getAFollowingStep() = run - ) -} - -// -/** - * A download artifact step followed by a uses step . - */ -predicate artifactDownloadToUsesStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(Step artifact, Uses uses | - controlledCWD(artifact) and - pred.asExpr() = artifact and - succ.asExpr() = uses and - artifact.getAFollowingStep() = uses - ) -} - -/** - * A read of the _files field of the dorny/paths-filter action. - */ -predicate dornyPathsFilterTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(StepsExpression o | - pred instanceof DornyPathsFilterSource and - o.getStepId() = pred.asExpr().(UsesStep).getId() and - o.getFieldName().matches("%_files") and - succ.asExpr() = o - ) -} - -/** - * A read of user-controlled field of the tj-actions/changed-files action. - */ -predicate tjActionsChangedFilesTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(StepsExpression o | - pred instanceof TJActionsChangedFilesSource and - o.getTarget() = pred.asExpr() and - o.getStepId() = pred.asExpr().(UsesStep).getId() and - o.getFieldName() = - [ - "added_files", "copied_files", "deleted_files", "modified_files", "renamed_files", - "all_old_new_renamed_files", "type_changed_files", "unmerged_files", "unknown_files", - "all_changed_and_modified_files", "all_changed_files", "other_changed_files", - "all_modified_files", "other_modified_files", "other_deleted_files", "modified_keys", - "changed_keys" - ] and - succ.asExpr() = o - ) -} - -/** - * A read of user-controlled field of the tj-actions/verify-changed-files action. - */ -predicate tjActionsVerifyChangedFilesTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(StepsExpression o | - pred instanceof TJActionsVerifyChangedFilesSource and - o.getTarget() = pred.asExpr() and - o.getStepId() = pred.asExpr().(UsesStep).getId() and - o.getFieldName() = "changed_files" and - succ.asExpr() = o - ) -} - -/** - * A read of user-controlled field of the xt0rted/slash-command-action action. - */ -predicate xt0rtedSlashCommandActionTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(StepsExpression o | - pred instanceof Xt0rtedSlashCommandSource and - o.getTarget() = pred.asExpr() and - o.getStepId() = pred.asExpr().(UsesStep).getId() and - o.getFieldName() = "command-arguments" and - succ.asExpr() = o - ) -} - -class TaintSteps extends AdditionalTaintStep { - override predicate step(DataFlow::Node node1, DataFlow::Node node2) { - envToRunStep(node1, node2) or - artifactDownloadToRunStep(node1, node2) or - artifactDownloadToUsesStep(node1, node2) or - // 3rd party actions - dornyPathsFilterTaintStep(node1, node2) or - tjActionsChangedFilesTaintStep(node1, node2) or - tjActionsVerifyChangedFilesTaintStep(node1, node2) or - xt0rtedSlashCommandActionTaintStep(node1, node2) - } -} diff --git a/ql/lib/codeql/actions/dataflow/TaintSteps.qll b/ql/lib/codeql/actions/dataflow/TaintSteps.qll new file mode 100644 index 00000000000..de64a0dd6f4 --- /dev/null +++ b/ql/lib/codeql/actions/dataflow/TaintSteps.qll @@ -0,0 +1,101 @@ +/** + * Provides classes representing various flow steps for taint tracking. + */ + +private import actions +private import codeql.util.Unit +private import codeql.actions.DataFlow +private import codeql.actions.dataflow.FlowSources + +/** + * A unit class for adding additional taint steps. + * + * Extend this class to add additional taint steps that should apply to all + * taint configurations. + */ +class AdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for all configurations. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); +} + +/** + * A download artifact step followed by a step that may use downloaded artifacts. + */ +predicate fileDownloadToRunStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(FileSource source, Run run | + pred = source and + source.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) +} + +/** + * A read of the _files field of the dorny/paths-filter action. + */ +predicate dornyPathsFilterTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(StepsExpression o | + pred instanceof DornyPathsFilterSource and + o.getStepId() = pred.asExpr().(UsesStep).getId() and + o.getFieldName().matches("%_files") and + succ.asExpr() = o + ) +} + +/** + * A read of user-controlled field of the tj-actions/changed-files action. + */ +predicate tjActionsChangedFilesTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(StepsExpression o | + pred instanceof TJActionsChangedFilesSource and + o.getTarget() = pred.asExpr() and + o.getStepId() = pred.asExpr().(UsesStep).getId() and + o.getFieldName() = + [ + "added_files", "copied_files", "deleted_files", "modified_files", "renamed_files", + "all_old_new_renamed_files", "type_changed_files", "unmerged_files", "unknown_files", + "all_changed_and_modified_files", "all_changed_files", "other_changed_files", + "all_modified_files", "other_modified_files", "other_deleted_files", "modified_keys", + "changed_keys" + ] and + succ.asExpr() = o + ) +} + +/** + * A read of user-controlled field of the tj-actions/verify-changed-files action. + */ +predicate tjActionsVerifyChangedFilesTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(StepsExpression o | + pred instanceof TJActionsVerifyChangedFilesSource and + o.getTarget() = pred.asExpr() and + o.getStepId() = pred.asExpr().(UsesStep).getId() and + o.getFieldName() = "changed_files" and + succ.asExpr() = o + ) +} + +/** + * A read of user-controlled field of the xt0rted/slash-command-action action. + */ +predicate xt0rtedSlashCommandActionTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(StepsExpression o | + pred instanceof Xt0rtedSlashCommandSource and + o.getTarget() = pred.asExpr() and + o.getStepId() = pred.asExpr().(UsesStep).getId() and + o.getFieldName() = "command-arguments" and + succ.asExpr() = o + ) +} + +class TaintSteps extends AdditionalTaintStep { + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { + dornyPathsFilterTaintStep(node1, node2) or + tjActionsChangedFilesTaintStep(node1, node2) or + tjActionsVerifyChangedFilesTaintStep(node1, node2) or + xt0rtedSlashCommandActionTaintStep(node1, node2) + } +} diff --git a/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll b/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll index 4e4f580f070..d7c3dad9ee7 100644 --- a/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll +++ b/ql/lib/codeql/actions/dataflow/internal/DataFlowPrivate.qll @@ -351,8 +351,10 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { madStoreStep(node1, node2, c) or envToOutputStoreStep(node1, node2, c) or envToEnvStoreStep(node1, node2, c) or - artifactToOutputStoreStep(node1, node2, c) or - artifactToEnvStoreStep(node1, node2, c) + fileToOutputStoreStep(node1, node2, c) or + fileToEnvStoreStep(node1, node2, c) or + commandToOutputStoreStep(node1, node2, c) or + commandToEnvStoreStep(node1, node2, c) } /** diff --git a/ql/lib/codeql/actions/dataflow/internal/TaintTrackingPrivate.qll b/ql/lib/codeql/actions/dataflow/internal/TaintTrackingPrivate.qll index b8647339d24..2dde5203576 100644 --- a/ql/lib/codeql/actions/dataflow/internal/TaintTrackingPrivate.qll +++ b/ql/lib/codeql/actions/dataflow/internal/TaintTrackingPrivate.qll @@ -5,7 +5,7 @@ private import DataFlowPrivate private import codeql.actions.DataFlow -private import codeql.actions.dataflow.FlowSteps +private import codeql.actions.dataflow.TaintSteps private import codeql.actions.Ast /** From d558ff80c3a63fa113a0befa2d09334c48d8e64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 11 Oct 2024 12:20:03 +0200 Subject: [PATCH 3/6] New Command sources for git and GITHUB_EVENT_PATH --- ql/lib/codeql/actions/config/Config.qll | 10 ++ .../actions/config/ConfigExtensions.qll | 5 + .../codeql/actions/dataflow/FlowSources.qll | 109 +++++++++++++++++- ql/lib/ext/config/untrusted_git_commands.yml | 32 +++++ 4 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 ql/lib/ext/config/untrusted_git_commands.yml diff --git a/ql/lib/codeql/actions/config/Config.qll b/ql/lib/codeql/actions/config/Config.qll index e298865c468..e3bf239565e 100644 --- a/ql/lib/codeql/actions/config/Config.qll +++ b/ql/lib/codeql/actions/config/Config.qll @@ -128,3 +128,13 @@ predicate vulnerableActionsDataModel( ) { Extensions::vulnerableActionsDataModel(action, vulnerable_version, vulnerable_sha, fixed_version) } + +/** + * MaD models for untrusted git commands + * Fields: + * - cmd_regex: Regular expression for matching untrusted git commands + * - flag: Flag for the command + */ +predicate untrustedGitCommandsDataModel(string cmd_regex, string flag) { + Extensions::untrustedGitCommandsDataModel(cmd_regex, flag) +} diff --git a/ql/lib/codeql/actions/config/ConfigExtensions.qll b/ql/lib/codeql/actions/config/ConfigExtensions.qll index cc1b5553f5f..a32e9c445f2 100644 --- a/ql/lib/codeql/actions/config/ConfigExtensions.qll +++ b/ql/lib/codeql/actions/config/ConfigExtensions.qll @@ -57,3 +57,8 @@ extensible predicate argumentInjectionSinksDataModel( extensible predicate vulnerableActionsDataModel( string action, string vulnerable_version, string vulnerable_sha, string fixed_version ); + +/** + * Holds for git commands that may introduce untrusted data when called on an attacker controlled branch. + */ +extensible predicate untrustedGitCommandsDataModel(string cmd_regex, string flag); diff --git a/ql/lib/codeql/actions/dataflow/FlowSources.qll b/ql/lib/codeql/actions/dataflow/FlowSources.qll index 4682e7b1abf..f1fb2073ed0 100644 --- a/ql/lib/codeql/actions/dataflow/FlowSources.qll +++ b/ql/lib/codeql/actions/dataflow/FlowSources.qll @@ -64,6 +64,88 @@ class GitHubEventCtxSource extends RemoteFlowSource { override string getSourceType() { result = flag } } +abstract class CommandSource extends RemoteFlowSource { + abstract string getCommand(); + + abstract Run getEnclosingRun(); +} + +class GitCommandSource extends RemoteFlowSource, CommandSource { + Run run; + string cmd; + string flag; + + GitCommandSource() { + exists(Step checkout, string cmd_regex | + // This shoould be: + // source instanceof PRHeadCheckoutStep + // but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error + // so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround + // instead of using ActionsMutableRefCheckout and ActionsSHACheckout + ( + exists(Uses uses | + checkout = uses and + uses.getCallee() = "actions/checkout" and + exists(uses.getArgument("ref")) + ) + or + checkout instanceof GitMutableRefCheckout + or + checkout instanceof GitSHACheckout + or + checkout instanceof GhMutableRefCheckout + or + checkout instanceof GhSHACheckout + ) and + this.asExpr() = run.getScriptScalar() and + checkout.getAFollowingStep() = run and + run.getACommand() = cmd and + cmd.indexOf("git") = 0 and + untrustedGitCommandsDataModel(cmd_regex, flag) and + cmd.regexpMatch(cmd_regex) + ) + } + + override string getSourceType() { result = flag } + + override string getCommand() { result = cmd } + + override Run getEnclosingRun() { result = run } +} + +class GitHubEventPathSource extends RemoteFlowSource, CommandSource { + string cmd; + string flag; + string access_path; + Run run; + + // Examples + // COMMENT_AUTHOR=$(jq -r .comment.user.login "$GITHUB_EVENT_PATH") + // CURRENT_COMMENT=$(jq -r .comment.body "$GITHUB_EVENT_PATH") + // PR_HEAD=$(jq --raw-output .pull_request.head.ref ${GITHUB_EVENT_PATH}) + // PR_NUMBER=$(jq --raw-output .pull_request.number ${GITHUB_EVENT_PATH}) + // PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH}) + // BODY=$(jq -r '.issue.body' "$GITHUB_EVENT_PATH" | sed -n '3p') + GitHubEventPathSource() { + this.asExpr() = run.getScriptScalar() and + run.getACommand() = cmd and + cmd.matches("jq%") and + cmd.matches("%GITHUB_EVENT_PATH%") and + exists(string regexp | + untrustedEventPropertiesDataModel(regexp, flag) and + not flag = "json" and + access_path = "github.event" + cmd.regexpCapture(".*\\s+([^\\s]+)\\s+.*", 1) and + normalizeExpr(access_path).regexpMatch("(?i)\\s*" + wrapRegexp(regexp) + ".*") + ) + } + + override string getSourceType() { result = flag } + + override string getCommand() { result = cmd } + + override Run getEnclosingRun() { result = run } +} + class GitHubEventJsonSource extends RemoteFlowSource { string flag; @@ -104,10 +186,12 @@ class MaDSource extends RemoteFlowSource { override string getSourceType() { result = sourceType } } +abstract class FileSource extends RemoteFlowSource { } + /** * A downloaded artifact. */ -class ArtifactSource extends RemoteFlowSource { +class ArtifactSource extends RemoteFlowSource, FileSource { ArtifactSource() { this.asExpr() instanceof UntrustedArtifactDownloadStep } override string getSourceType() { result = "artifact" } @@ -116,8 +200,27 @@ class ArtifactSource extends RemoteFlowSource { /** * A file from an untrusted checkout. */ -private class CheckoutSource extends RemoteFlowSource { - CheckoutSource() { this.asExpr() instanceof PRHeadCheckoutStep } +private class CheckoutSource extends RemoteFlowSource, FileSource { + CheckoutSource() { + // This shoould be: + // source instanceof PRHeadCheckoutStep + // but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error + // so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround + // instead of using ActionsMutableRefCheckout and ActionsSHACheckout + exists(Uses u | + this.asExpr() = u and + u.getCallee() = "actions/checkout" and + exists(u.getArgument("ref")) + ) + or + this.asExpr() instanceof GitMutableRefCheckout + or + this.asExpr() instanceof GitSHACheckout + or + this.asExpr() instanceof GhMutableRefCheckout + or + this.asExpr() instanceof GhSHACheckout + } override string getSourceType() { result = "artifact" } } diff --git a/ql/lib/ext/config/untrusted_git_commands.yml b/ql/lib/ext/config/untrusted_git_commands.yml new file mode 100644 index 00000000000..0d6c9e3bfa0 --- /dev/null +++ b/ql/lib/ext/config/untrusted_git_commands.yml @@ -0,0 +1,32 @@ +extensions: + - addsTo: + pack: github/actions-all + extensible: untrustedGitCommandsDataModel + data: + # FILES=$(git diff-tree --no-commit-id --name-only HEAD -r) + - [".*git\\b.*\\bdiff-tree\\b.*", "filename,multiline"] + # CHANGES=$(git --no-pager diff --name-only $NAME | grep -v -f .droneignore); + # CHANGES=$(git diff --name-only) + - [".*git\\b.*\\bdiff\\b.*", "filename,multiline"] + # COMMIT_MESSAGE=$(git log --format=%s -n 1) + - [".*git\\b.*\\blog\\b.*%s.*", "text,online"] + # COMMIT_MESSAGE=$(git log --format=%B -n 1) + - [".*git\\b.*\\blog\\b.*%B.*", "text,multiline"] + # COMMIT_MESSAGE=$(git log --format=oneline) + - [".*git\\b.*\\blog\\b.*oneline.*", "text,oneline"] + # COMMIT_MESSAGE=$(git show -s --format=%B) + # COMMIT_MESSAGE=$(git show -s --format=%s) + - [".*git\\b.*\\bshow\\b.*-s.*%s.*", "text,oneline"] + - [".*git\\b.*\\bshow\\b.*-s.*%B.*", "text,multiline"] + # AUTHOR=$(git log -1 --pretty=format:'%an') + - [".*git\\b.*\\blog\\b.*%an.*", "username,oneline"] + # AUTHOR=$(git show -s --pretty=%an) + - [".*git\\b.*\\bshow\\b.*%an.*", "username,oneline"] + # EMAIL=$(git log -1 --pretty=format:'%ae') + - [".*git\\b.*\\blog\\b.*%ae.*", "email,oneline"] + # EMAIL=$(git show -s --pretty=%ae) + - [".*git\\b.*\\bshow\\b.*%ae.*", "email,oneline"] + # BRANCH=$(git branch --show-current) + - [".*git\\b.*\\bbranch\\b.*\\b--show-current\\b.*", "branch,oneline"] + # BRANCH=$(git rev-parse --abbrev-ref HEAD) + - [".*git\\b.*\\brev-parse\\b.*\\b--abbrev-ref\\b.*", "branch,oneline"] From ee25f3565335dd4ee4e62188721adebb76a97b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 11 Oct 2024 12:20:26 +0200 Subject: [PATCH 4/6] Refactor of Bash functions --- ql/lib/codeql/actions/Ast.qll | 16 + ql/lib/codeql/actions/Bash.qll | 364 ++++++++++++++++++ ql/lib/codeql/actions/Helper.qll | 239 +----------- ql/lib/codeql/actions/ast/internal/Ast.qll | 16 + .../security/ArgumentInjectionQuery.qll | 58 ++- .../security/ArtifactPoisoningQuery.qll | 18 + .../actions/security/CodeInjectionQuery.qll | 16 + .../security/EnvPathInjectionQuery.qll | 72 ++-- .../actions/security/EnvVarInjectionQuery.qll | 77 ++-- .../security/OutputClobberingQuery.qll | 134 ++++--- .../actions/security/PoisonableSteps.qll | 11 +- .../security/UntrustedCheckoutQuery.qll | 22 +- 12 files changed, 697 insertions(+), 346 deletions(-) create mode 100644 ql/lib/codeql/actions/Bash.qll diff --git a/ql/lib/codeql/actions/Ast.qll b/ql/lib/codeql/actions/Ast.qll index 759bcf3f786..cc29ceffe53 100644 --- a/ql/lib/codeql/actions/Ast.qll +++ b/ql/lib/codeql/actions/Ast.qll @@ -315,6 +315,22 @@ class Run extends Step instanceof RunImpl { } predicate getAWriteToGitHubPath(string value) { super.getAWriteToGitHubPath(value) } + + predicate getAnEnvReachingGitHubOutputWrite(string var, string output_field) { + super.getAnEnvReachingGitHubOutputWrite(var, output_field) + } + + predicate getACmdReachingGitHubOutputWrite(string cmd, string output_field) { + super.getACmdReachingGitHubOutputWrite(cmd, output_field) + } + + predicate getAnEnvReachingGitHubEnvWrite(string var, string output_field) { + super.getAnEnvReachingGitHubEnvWrite(var, output_field) + } + + predicate getACmdReachingGitHubEnvWrite(string cmd, string output_field) { + super.getACmdReachingGitHubEnvWrite(cmd, output_field) + } } abstract class SimpleReferenceExpression extends AstNode instanceof SimpleReferenceExpressionImpl { diff --git a/ql/lib/codeql/actions/Bash.qll b/ql/lib/codeql/actions/Bash.qll new file mode 100644 index 00000000000..5907b601a46 --- /dev/null +++ b/ql/lib/codeql/actions/Bash.qll @@ -0,0 +1,364 @@ +private import codeql.actions.Ast +private import codeql.Locations +import codeql.actions.config.Config +private import codeql.actions.security.ControlChecks + +module Bash { + string stmtSeparator() { result = ";" } + + string commandSeparator() { result = ["&&", "||"] } + + string pipeSeparator() { result = "|" } + + string splitSeparators() { + result = stmtSeparator() or result = commandSeparator() or result = pipeSeparator() + } + + string redirectionSeparator() { result = [">", ">>", "2>", "2>>", ">&", "2>&", "<", "<<<"] } + + string partialFileContentCommand() { result = ["cat", "jq", "yq", "tail", "head"] } + + /** Checks if expr is a bash command substitution */ + bindingset[expr] + predicate isCmdSubstitution(string expr, string cmd) { + exists(string regexp | + // $(cmd) + regexp = "\\$\\(([^)]+)\\)" and + cmd = expr.regexpCapture(regexp, 1) + or + // `cmd` + regexp = "`([^`]+)`" and + cmd = expr.regexpCapture(regexp, 1) + ) + } + + /** Checks if expr is a bash command substitution */ + bindingset[expr] + predicate containsCmdSubstitution(string expr, string cmd) { + exists(string regexp | + // $(cmd) + regexp = ".*\\$\\(([^)]+)\\).*" and + cmd = expr.regexpCapture(regexp, 1) + or + // `cmd` + regexp = ".*`([^`]+)`.*" and + cmd = expr.regexpCapture(regexp, 1) + ) + } + + /** Checks if expr is a bash parameter expansion */ + bindingset[expr] + predicate isParameterExpansion(string expr, string parameter, string operator, string params) { + exists(string regexp | + // $VAR + regexp = "\\$([a-zA-Z_][a-zA-Z0-9_]+)\\b" and + parameter = expr.regexpCapture(regexp, 1) and + operator = "" and + params = "" + or + // ${VAR} + regexp = "\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}" and + parameter = expr.regexpCapture(regexp, 1) and + operator = "" and + params = "" + or + // ${!VAR} + regexp = "\\$\\{([!#])([a-zA-Z_][a-zA-Z0-9_]*)\\}" and + parameter = expr.regexpCapture(regexp, 2) and + operator = expr.regexpCapture(regexp, 1) and + params = "" + or + // ${VAR}, ... + regexp = "\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)([#%/:^,\\-+]{1,2})?(.*?)\\}" and + parameter = expr.regexpCapture(regexp, 1) and + operator = expr.regexpCapture(regexp, 2) and + params = expr.regexpCapture(regexp, 3) + ) + } + + bindingset[expr] + predicate containsParameterExpansion(string expr, string parameter, string operator, string params) { + exists(string regexp | + // $VAR + regexp = ".*\\$([a-zA-Z_][a-zA-Z0-9_]+)\\b.*" and + parameter = expr.regexpCapture(regexp, 1) and + operator = "" and + params = "" + or + // ${VAR} + regexp = ".*\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}.*" and + parameter = expr.regexpCapture(regexp, 1) and + operator = "" and + params = "" + or + // ${!VAR} + regexp = ".*\\$\\{([!#])([a-zA-Z_][a-zA-Z0-9_]*)\\}.*" and + parameter = expr.regexpCapture(regexp, 2) and + operator = expr.regexpCapture(regexp, 1) and + params = "" + or + // ${VAR}, ... + regexp = ".*\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)([#%/:^,\\-+]{1,2})?(.*?)\\}.*" and + parameter = expr.regexpCapture(regexp, 1) and + operator = expr.regexpCapture(regexp, 2) and + params = expr.regexpCapture(regexp, 3) + ) + } + + bindingset[raw_content] + predicate extractVariableAndValue(string raw_content, string key, string value) { + exists(string regexp, string content | content = trimQuotes(raw_content) | + regexp = "(?msi).*^([a-zA-Z_][a-zA-Z0-9_]*)\\s*<<\\s*['\"]?(\\S+)['\"]?\\s*\n(.*?)\n\\2\\s*$" and + key = trimQuotes(content.regexpCapture(regexp, 1)) and + value = trimQuotes(content.regexpCapture(regexp, 3)) + or + exists(string line | + line = content.splitAt("\n") and + regexp = "(?i)^([a-zA-Z_][a-zA-Z0-9_\\-]*)\\s*=\\s*(.*)$" and + key = trimQuotes(line.regexpCapture(regexp, 1)) and + value = trimQuotes(line.regexpCapture(regexp, 2)) + ) + ) + } + + bindingset[script] + predicate singleLineFileWrite( + string script, string cmd, string file, string content, string filters + ) { + exists(string regexp | + regexp = + "(?i)(echo|printf|write-output)\\s*(.*?)\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)" and + cmd = script.regexpCapture(regexp, 1) and + file = trimQuotes(script.regexpCapture(regexp, 5)) and + filters = "" and + content = script.regexpCapture(regexp, 2) + ) + } + + bindingset[script] + predicate singleLineWorkflowCmd(string script, string cmd, string key, string value) { + exists(string regexp | + regexp = + "(?i)(echo|printf|write-output)\\s*(['|\"])?::(set-[a-z]+)\\s*name\\s*=\\s*(.*?)::(.*)" and + cmd = script.regexpCapture(regexp, 3) and + key = script.regexpCapture(regexp, 4) and + value = trimQuotes(script.regexpCapture(regexp, 5)) + or + regexp = "(?i)(echo|printf|write-output)\\s*(['|\"])?::(add-[a-z]+)\\s*::(.*)" and + cmd = script.regexpCapture(regexp, 3) and + key = "" and + value = trimQuotes(script.regexpCapture(regexp, 4)) + ) + } + + bindingset[script] + predicate heredocFileWrite(string script, string cmd, string file, string content, string filters) { + exists(string regexp | + regexp = + "(?msi).*^(cat)\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)\\s*<<\\s*['\"]?(\\S+)['\"]?\\s*\n(.*?)\n\\4\\s*$.*" and + cmd = script.regexpCapture(regexp, 1) and + file = trimQuotes(script.regexpCapture(regexp, 4)) and + content = script.regexpCapture(regexp, 6) and + filters = "" + or + regexp = + "(?msi).*^(cat)\\s*(<<|<)\\s*[-]?['\"]?(\\S+)['\"]?\\s*([^>]*)(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)\\s*\n(.*?)\n\\3\\s*$.*" and + cmd = script.regexpCapture(regexp, 1) and + file = trimQuotes(script.regexpCapture(regexp, 7)) and + filters = script.regexpCapture(regexp, 4) and + content = script.regexpCapture(regexp, 8) + ) + } + + bindingset[script] + predicate linesFileWrite(string script, string cmd, string file, string content, string filters) { + exists(string regexp, string var_name | + regexp = + "(?msi).*((echo|printf)\\s+['|\"]?(.*?<<(\\S+))['|\"]?\\s*>>\\s*(\\S+)\\s*[\r\n]+)" + + "(((.*?)\\s*>>\\s*\\S+\\s*[\r\n]+)+)" + + "((echo|printf)\\s+['|\"]?(EOF)['|\"]?\\s*>>\\s*\\S+\\s*[\r\n]*).*" and + var_name = trimQuotes(script.regexpCapture(regexp, 3)).regexpReplaceAll("<<\\s*(\\S+)", "") and + content = + var_name + "=$(" + + trimQuotes(script.regexpCapture(regexp, 6)) + .regexpReplaceAll(">>.*GITHUB_(ENV|OUTPUT)(})?", "") + .trim() + ")" and + cmd = "echo" and + file = trimQuotes(script.regexpCapture(regexp, 5)) and + filters = "" + ) + } + + bindingset[script] + predicate blockFileWrite(string script, string cmd, string file, string content, string filters) { + exists(string regexp, string first_line, string var_name | + regexp = + "(?msi).*^\\s*\\{\\s*[\r\n]" + + // + "(.*?)" + + // + "(\\s*\\}\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+))\\s*$.*" and + first_line = script.regexpCapture(regexp, 1).splitAt("\n", 0).trim() and + var_name = first_line.regexpCapture("echo\\s+('|\\\")?(.*)<<.*", 2) and + content = var_name + "=$(" + script.regexpCapture(regexp, 1).splitAt("\n").trim() + ")" and + not content.indexOf("EOF") > 0 and + file = trimQuotes(script.regexpCapture(regexp, 5)) and + cmd = "echo" and + filters = "" + ) + } + + bindingset[script] + predicate multiLineFileWrite( + string script, string cmd, string file, string content, string filters + ) { + heredocFileWrite(script, cmd, file, content, filters) + or + linesFileWrite(script, cmd, file, content, filters) + or + blockFileWrite(script, cmd, file, content, filters) + } + + bindingset[script, file_var] + predicate extractFileWrite(string script, string file_var, string content) { + // single line assignment + exists(string file_expr, string raw_content | + isParameterExpansion(file_expr, file_var, _, _) and + singleLineFileWrite(script.splitAt("\n"), _, file_expr, raw_content, _) and + content = trimQuotes(raw_content) + ) + or + // workflow command assignment + exists(string key, string value, string cmd | + ( + file_var = "GITHUB_ENV" and + cmd = "set-env" and + content = key + "=" + value + or + file_var = "GITHUB_OUTPUT" and + cmd = "set-output" and + content = key + "=" + value + or + file_var = "GITHUB_PATH" and + cmd = "add-path" and + content = value + ) and + singleLineWorkflowCmd(script.splitAt("\n"), cmd, key, value) + ) + or + // multiline assignment + exists(string file_expr, string raw_content | + multiLineFileWrite(script, _, file_expr, raw_content, _) and + isParameterExpansion(file_expr, file_var, _, _) and + content = trimQuotes(raw_content) + ) + } + + /** Writes the content of the file specified by `path` into a file pointed to by `file_var` */ + predicate fileToFileWrite(Run run, string file_var, string path) { + exists(string regexp, string stmt, string file_expr | + regexp = + "(?i)(cat)\\s*" + "((?:(?!<<|<<-)[^>\n])+)\\s*" + + "(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*" + "(\\S+)" and + stmt = run.getAStmt() and + file_expr = trimQuotes(stmt.regexpCapture(regexp, 5)) and + path = stmt.regexpCapture(regexp, 2) and + containsParameterExpansion(file_expr, file_var, _, _) + ) + } + + predicate fileToGitHubEnv(Run run, string path) { fileToFileWrite(run, "GITHUB_ENV", path) } + + predicate fileToGitHubOutput(Run run, string path) { fileToFileWrite(run, "GITHUB_OUTPUT", path) } + + predicate fileToGitHubPath(Run run, string path) { fileToFileWrite(run, "GITHUB_PATH", path) } + + bindingset[snippet] + predicate outputsPartialFileContent(Run run, string snippet) { + // e.g. + // echo FOO=`yq '.foo' foo.yml` >> $GITHUB_ENV + // echo "FOO=$(> $GITHUB_ENV + // yq '.foo' foo.yml >> $GITHUB_PATH + // cat foo.txt >> $GITHUB_PATH + exists(int i, string line, string cmd | + run.getStmt(i) = line and + line.indexOf(snippet.regexpReplaceAll("^\\$\\(", "").regexpReplaceAll("\\)$", "")) > -1 and + run.getCommand(i) = cmd and + cmd.indexOf(["<", Bash::partialFileContentCommand() + " "]) = 0 + ) + } + + /** + * Holds if the Run scripts contains an access to an environment variable called `var` + * which value may get appended to the GITHUB_XXX special file + */ + predicate envReachingGitHubFileWrite(Run run, string var, string file_var, string field) { + exists(string file_write_value | + ( + file_var = "GITHUB_ENV" and + run.getAWriteToGitHubEnv(field, file_write_value) + or + file_var = "GITHUB_OUTPUT" and + run.getAWriteToGitHubOutput(field, file_write_value) + or + file_var = "GITHUB_PATH" and + field = "PATH" and + run.getAWriteToGitHubPath(file_write_value) + ) and + envReachingRunExpr(run, var, file_write_value) + ) + } + + /** + * Holds if and environment variable is used, directly or indirectly, in a Run's step expression. + * Where the expression is a string captured from the Run's script. + */ + bindingset[expr] + predicate envReachingRunExpr(Run run, string var, string expr) { + exists(string var2, string value2 | + // VAR2=${VAR:-default} (var2=value2) + // echo "FIELD=${VAR2:-default}" >> $GITHUB_ENV (field, file_write_value) + run.getAnAssignment(var2, value2) and + containsParameterExpansion(value2, var, _, _) and + containsParameterExpansion(expr, var2, _, _) + ) + or + // var reaches the file write directly + // echo "FIELD=${VAR:-default}" >> $GITHUB_ENV (field, file_write_value) + containsParameterExpansion(expr, var, _, _) + } + + /** + * Holds if the Run scripts contains a command substitution (`cmd`) + * which output may get appended to the GITHUB_XXX special file + */ + predicate cmdReachingGitHubFileWrite(Run run, string cmd, string file_var, string field) { + exists(string file_write_value | + ( + file_var = "GITHUB_ENV" and + run.getAWriteToGitHubEnv(field, file_write_value) + or + file_var = "GITHUB_OUTPUT" and + run.getAWriteToGitHubOutput(field, file_write_value) + or + file_var = "GITHUB_PATH" and + field = "PATH" and + run.getAWriteToGitHubPath(file_write_value) + ) and + ( + // cmd output is assigned to a second variable (var2) and var2 reaches the file write + exists(string var2, string value2 | + // VAR2=$(cmd) + // echo "FIELD=${VAR2:-default}" >> $GITHUB_ENV (field, file_write_value) + run.getAnAssignment(var2, value2) and + containsCmdSubstitution(value2, cmd) and + containsParameterExpansion(file_write_value, var2, _, _) + ) + or + // var reaches the file write directly + // echo "FIELD=$(cmd)" >> $GITHUB_ENV (field, file_write_value) + containsCmdSubstitution(file_write_value, cmd) + ) + ) + } +} diff --git a/ql/lib/codeql/actions/Helper.qll b/ql/lib/codeql/actions/Helper.qll index 688d62acbe1..ae4405a185b 100644 --- a/ql/lib/codeql/actions/Helper.qll +++ b/ql/lib/codeql/actions/Helper.qll @@ -1,7 +1,8 @@ private import codeql.actions.Ast private import codeql.Locations -import codeql.actions.config.Config private import codeql.actions.security.ControlChecks +import codeql.actions.config.Config +import codeql.actions.Bash bindingset[expr] string normalizeExpr(string expr) { @@ -82,239 +83,3 @@ string normalizePath(string path) { */ bindingset[subpath, path] predicate isSubpath(string subpath, string path) { subpath.substring(0, path.length()) = path } - -module Bash { - string stmtSeparator() { result = ";" } - - string commandSeparator() { result = ["&&", "||"] } - - string pipeSeparator() { result = "|" } - - string splitSeparators() { - result = stmtSeparator() or result = commandSeparator() or result = pipeSeparator() - } - - string redirectionSeparator() { result = [">", ">>", "2>", "2>>", ">&", "2>&", "<", "<<<"] } - - string partialFileContentCommand() { result = ["cat", "jq", "yq", "tail", "head"] } - - /** Checks if expr is a bash parameter expansion */ - bindingset[expr] - predicate isBashParameterExpansion(string expr, string parameter, string operator, string params) { - exists(string regexp | - // $VAR - regexp = "\\$([a-zA-Z_][a-zA-Z0-9_]+)\\b" and - parameter = expr.regexpCapture(regexp, 1) and - operator = "" and - params = "" - or - // ${VAR} - regexp = "\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}" and - parameter = expr.regexpCapture(regexp, 1) and - operator = "" and - params = "" - or - // ${!VAR} - regexp = "\\$\\{([!#])([a-zA-Z_][a-zA-Z0-9_]*)\\}" and - parameter = expr.regexpCapture(regexp, 2) and - operator = expr.regexpCapture(regexp, 1) and - params = "" - or - // ${VAR}, ... - regexp = "\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)([#%/:^,\\-+]{1,2})?(.*?)\\}" and - parameter = expr.regexpCapture(regexp, 1) and - operator = expr.regexpCapture(regexp, 2) and - params = expr.regexpCapture(regexp, 3) - ) - } - - bindingset[raw_content] - predicate extractVariableAndValue(string raw_content, string key, string value) { - exists(string regexp, string content | content = trimQuotes(raw_content) | - regexp = "(?msi).*^([a-zA-Z_][a-zA-Z0-9_]*)\\s*<<\\s*['\"]?(\\S+)['\"]?\\s*\n(.*?)\n\\2\\s*$" and - key = trimQuotes(content.regexpCapture(regexp, 1)) and - value = trimQuotes(content.regexpCapture(regexp, 3)) - or - exists(string line | - line = content.splitAt("\n") and - regexp = "(?i)^([a-zA-Z_][a-zA-Z0-9_\\-]*)\\s*=\\s*(.*)$" and - key = trimQuotes(line.regexpCapture(regexp, 1)) and - value = trimQuotes(line.regexpCapture(regexp, 2)) - ) - ) - } - - bindingset[script] - predicate singleLineFileWrite( - string script, string cmd, string file, string content, string filters - ) { - exists(string regexp | - regexp = - "(?i)(echo|printf|write-output)\\s*(.*?)\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)" and - cmd = script.regexpCapture(regexp, 1) and - file = trimQuotes(script.regexpCapture(regexp, 5)) and - filters = "" and - content = script.regexpCapture(regexp, 2) - ) - } - - bindingset[script] - predicate singleLineWorkflowCmd(string script, string cmd, string key, string value) { - exists(string regexp | - regexp = - "(?i)(echo|printf|write-output)\\s*(['|\"])?::(set-[a-z]+)\\s*name\\s*=\\s*(.*?)::(.*)" and - cmd = script.regexpCapture(regexp, 3) and - key = script.regexpCapture(regexp, 4) and - value = trimQuotes(script.regexpCapture(regexp, 5)) - or - regexp = "(?i)(echo|printf|write-output)\\s*(['|\"])?::(add-[a-z]+)\\s*::(.*)" and - cmd = script.regexpCapture(regexp, 3) and - key = "" and - value = trimQuotes(script.regexpCapture(regexp, 4)) - ) - } - - bindingset[script] - predicate heredocFileWrite(string script, string cmd, string file, string content, string filters) { - exists(string regexp | - regexp = - "(?msi).*^(cat)\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)\\s*<<\\s*['\"]?(\\S+)['\"]?\\s*\n(.*?)\n\\4\\s*$.*" and - cmd = script.regexpCapture(regexp, 1) and - file = trimQuotes(script.regexpCapture(regexp, 4)) and - content = script.regexpCapture(regexp, 6) and - filters = "" - or - regexp = - "(?msi).*^(cat)\\s*(<<|<)\\s*[-]?['\"]?(\\S+)['\"]?\\s*([^>]*)(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+)\\s*\n(.*?)\n\\3\\s*$.*" and - cmd = script.regexpCapture(regexp, 1) and - file = trimQuotes(script.regexpCapture(regexp, 7)) and - filters = script.regexpCapture(regexp, 4) and - content = script.regexpCapture(regexp, 8) - ) - } - - bindingset[script] - predicate linesFileWrite(string script, string cmd, string file, string content, string filters) { - exists(string regexp | - regexp = - "(?msi).*((echo|printf)\\s+['|\"]?(.*?<<(\\S+))['|\"]?\\s*>>\\s*(\\S+)\\s*[\r\n]+)" + - "(((.*?)\\s*>>\\s*\\S+\\s*[\r\n]+)+)" + - "((echo|printf)\\s+['|\"]?(EOF)['|\"]?\\s*>>\\s*\\S+\\s*[\r\n]*).*" and - content = - trimQuotes(script.regexpCapture(regexp, 3)) + "\n" + - trimQuotes(script.regexpCapture(regexp, 6)) + "\n" + - trimQuotes(script.regexpCapture(regexp, 4)) and - cmd = "echo" and - file = trimQuotes(script.regexpCapture(regexp, 5)) and - filters = "" - ) - } - - bindingset[script] - predicate blockFileWrite(string script, string cmd, string file, string content, string filters) { - exists(string regexp | - regexp = - "(?msi).*^\\s*\\{\\s*[\r\n]" + - // - "(.*?)" + - // - "(\\s*\\}\\s*(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*(\\S+))\\s*$.*" and - content = - script - .regexpCapture(regexp, 1) - .regexpReplaceAll("(?m)^\\s*(echo|printf|write-output)\\s*['\"](.*?)['\"]", "$2") - .regexpReplaceAll("(?m)^\\s*(echo|printf|write-output)\\s*", "") and - file = trimQuotes(script.regexpCapture(regexp, 5)) and - cmd = "echo" and - filters = "" - ) - } - - bindingset[script] - predicate multiLineFileWrite( - string script, string cmd, string file, string content, string filters - ) { - heredocFileWrite(script, cmd, file, content, filters) - or - linesFileWrite(script, cmd, file, content, filters) - or - blockFileWrite(script, cmd, file, content, filters) - } - - bindingset[script, file_var] - predicate extractFileWrite(string script, string file_var, string content) { - // single line assignment - exists(string file_expr, string raw_content | - isBashParameterExpansion(file_expr, file_var, _, _) and - singleLineFileWrite(script.splitAt("\n"), _, file_expr, raw_content, _) and - content = trimQuotes(raw_content) - ) - or - // workflow command assignment - exists(string key, string value, string cmd | - ( - file_var = "GITHUB_ENV" and - cmd = "set-env" and - content = key + "=" + value - or - file_var = "GITHUB_OUTPUT" and - cmd = "set-output" and - content = key + "=" + value - or - file_var = "GITHUB_PATH" and - cmd = "add-path" and - content = value - ) and - singleLineWorkflowCmd(script.splitAt("\n"), cmd, key, value) - ) - or - // multiline assignment - exists(string file_expr, string raw_content | - multiLineFileWrite(script, _, file_expr, raw_content, _) and - isBashParameterExpansion(file_expr, file_var, _, _) and - content = trimQuotes(raw_content) - ) - } - - /** Writes the content of the file specified by `path` into a file pointed to by `file_var` */ - bindingset[script, file_var] - predicate fileToFileWrite(string script, string file_var, string path) { - exists(string regexp, string line, string file_expr | - isBashParameterExpansion(file_expr, file_var, _, _) and - regexp = - "(?i)(cat)\\s*" + "((?:(?!<<|<<-)[^>\n])+)\\s*" + - "(>>|>|\\s*\\|\\s*tee\\s*(-a|--append)?)\\s*" + "(\\S+)" and - line = script.splitAt("\n") and - path = line.regexpCapture(regexp, 2) and - file_expr = trimQuotes(line.regexpCapture(regexp, 5)) - ) - } - - predicate fileToGitHubEnv(Run run, string path) { - fileToFileWrite(run.getScript(), "GITHUB_ENV", path) - } - - predicate fileToGitHubOutput(Run run, string path) { - fileToFileWrite(run.getScript(), "GITHUB_OUTPUT", path) - } - - predicate fileToGitHubPath(Run run, string path) { - fileToFileWrite(run.getScript(), "GITHUB_PATH", path) - } - - bindingset[snippet] - predicate outputsPartialFileContent(Run run, string snippet) { - // e.g. - // echo FOO=`yq '.foo' foo.yml` >> $GITHUB_ENV - // echo "FOO=$(> $GITHUB_ENV - // yq '.foo' foo.yml >> $GITHUB_PATH - // cat foo.txt >> $GITHUB_PATH - // Bash::getACommand(snippet).indexOf(["<", Bash::partialFileContentCommand() + " "]) = 0 - exists(int i, string line, string cmd | - run.getStmt(i) = line and - line.matches("%" + snippet + "%") and - run.getCommand(i) = cmd and - cmd.indexOf(["<", Bash::partialFileContentCommand() + " "]) = 0 - ) - } -} diff --git a/ql/lib/codeql/actions/ast/internal/Ast.qll b/ql/lib/codeql/actions/ast/internal/Ast.qll index 30b57e361ab..a4b5778246a 100644 --- a/ql/lib/codeql/actions/ast/internal/Ast.qll +++ b/ql/lib/codeql/actions/ast/internal/Ast.qll @@ -1526,6 +1526,22 @@ class RunImpl extends StepImpl { predicate getAWriteToGitHubPath(string value) { Bash::extractFileWrite(this.getScript(), "GITHUB_PATH", value) } + + predicate getAnEnvReachingGitHubOutputWrite(string var, string output_field) { + Bash::envReachingGitHubFileWrite(this, var, "GITHUB_OUTPUT", output_field) + } + + predicate getACmdReachingGitHubOutputWrite(string cmd, string output_field) { + Bash::cmdReachingGitHubFileWrite(this, cmd, "GITHUB_OUTPUT", output_field) + } + + predicate getAnEnvReachingGitHubEnvWrite(string var, string output_field) { + Bash::envReachingGitHubFileWrite(this, var, "GITHUB_ENV", output_field) + } + + predicate getACmdReachingGitHubEnvWrite(string cmd, string output_field) { + Bash::cmdReachingGitHubFileWrite(this, cmd, "GITHUB_ENV", output_field) + } } /** diff --git a/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll b/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll index 6e1a5c0f229..18ff398ebab 100644 --- a/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll @@ -9,6 +9,23 @@ abstract class ArgumentInjectionSink extends DataFlow::Node { abstract string getCommand(); } +/** + * Holds if an environment variable is used, directly or indirectly, as an argument to a dangerous command + * in a Run step. + * Where the command is a string captured from the Run's script. + */ +bindingset[var] +predicate envToArgInjSink(string var, Run run, string command) { + exists(string argument, string cmd, string regexp, int command_group, int argument_group | + run.getACommand() = cmd and + argumentInjectionSinksDataModel(regexp, command_group, argument_group) and + command = cmd.regexpCapture(regexp, command_group) and + argument = cmd.regexpCapture(regexp, argument_group) and + Bash::envReachingRunExpr(run, var, argument) and + exists(run.getInScopeEnvVarExpr(var)) + ) +} + /** * Holds if a Run step declares an environment variable, uses it as the argument to a command vulnerable to argument injection. * e.g. @@ -21,10 +38,10 @@ class ArgumentInjectionFromEnvVarSink extends ArgumentInjectionSink { string command; ArgumentInjectionFromEnvVarSink() { - exists(Run run, string var_name | - envToArgInjSink(var_name, run, command) and + exists(Run run, string var | + envToArgInjSink(var, run, command) and run.getScriptScalar() = this.asExpr() and - exists(run.getInScopeEnvVarExpr(var_name)) + exists(run.getInScopeEnvVarExpr(var)) ) or exists( @@ -42,6 +59,33 @@ class ArgumentInjectionFromEnvVarSink extends ArgumentInjectionSink { override string getCommand() { result = command } } +/** + * Holds if a Run step executes a command that returns untrusted data which flows to an unsafe argument + * e.g. + * run: | + * BODY=$(git log --format=%s) + * sed "s/FOO/$BODY/g" > /tmp/foo + */ +class ArgumentInjectionFromCommandSink extends ArgumentInjectionSink { + string command; + + ArgumentInjectionFromCommandSink() { + exists( + CommandSource source, Run run, string cmd, string argument, string regexp, int argument_group, + int command_group + | + run = source.getEnclosingRun() and + this.asExpr() = run.getScriptScalar() and + cmd = run.getACommand() and + argumentInjectionSinksDataModel(regexp, command_group, argument_group) and + argument = cmd.regexpCapture(regexp, argument_group) and + command = cmd.regexpCapture(regexp, command_group) + ) + } + + override string getCommand() { result = command } +} + /** * Holds if a Run step declares an environment variable, uses it as the argument to a command vulnerable to argument injection. */ @@ -71,6 +115,14 @@ private module ArgumentInjectionConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { sink instanceof ArgumentInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Run run, string var | + run.getInScopeEnvVarExpr(var) = pred.asExpr() and + succ.asExpr() = run.getScriptScalar() and + envToArgInjSink(var, run, _) + ) + } } /** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */ diff --git a/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll b/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll index b7015590614..31a9edd03b3 100644 --- a/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll +++ b/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll @@ -274,6 +274,24 @@ private module ArtifactPoisoningConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof ArtifactSource } predicate isSink(DataFlow::Node sink) { sink instanceof ArtifactPoisoningSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(PoisonableStep step | + pred instanceof ArtifactSource and + pred.asExpr().(Step).getAFollowingStep() = step and + ( + succ.asExpr() = step.(Run).getScriptScalar() or + succ.asExpr() = step.(UsesStep) + ) + ) + or + exists(Run run | + pred instanceof ArtifactSource and + pred.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) + } } /** Tracks flow of unsafe artifacts that is used in an insecure way. */ diff --git a/ql/lib/codeql/actions/security/CodeInjectionQuery.qll b/ql/lib/codeql/actions/security/CodeInjectionQuery.qll index 8cd589fa9f8..ca72fe00d16 100644 --- a/ql/lib/codeql/actions/security/CodeInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/CodeInjectionQuery.qll @@ -19,6 +19,22 @@ private module CodeInjectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Uses step | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = step and + succ.asExpr() = step and + madSink(succ, "code-injection") + ) + or + exists(Run run | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) + } } /** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */ diff --git a/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll b/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll index a80032de320..1f53c938436 100644 --- a/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll @@ -14,6 +14,9 @@ abstract class EnvPathInjectionSink extends DataFlow::Node { } * e.g. * run: | * cat foo.txt >> $GITHUB_PATH + * echo "$(cat foo.txt)" >> $GITHUB_PATH + * FOO=$(cat foo.txt) + * echo "$FOO" >> $GITHUB_PATH */ class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink { EnvPathInjectionFromFileReadSink() { @@ -25,35 +28,34 @@ class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink { this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and ( - // e.g. - // cat test-results/.env >> $GITHUB_PATH - Bash::fileToGitHubPath(run, _) - or - exists(string value | - run.getAWriteToGitHubPath(value) and - ( - Bash::outputsPartialFileContent(run, value) - or - // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_PATH - exists(string var_name, string var_value | - run.getAnAssignment(var_name, var_value) and - Bash::outputsPartialFileContent(run, var_value) and - ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") - or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 - ) - ) - ) + exists(string cmd | + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_PATH", _) and + Bash::outputsPartialFileContent(run, cmd) ) + or + Bash::fileToGitHubPath(run, _) ) ) } } +/** + * Holds if a Run step executes a command that returns untrusted data which flows to GITHUB_ENV + * e.g. + * run: | + * COMMIT_MESSAGE=$(git log --format=%s) + * echo "${COMMIT_MESSAGE}" >> $GITHUB_PATH + */ +class EnvPathInjectionFromCommandSink extends EnvPathInjectionSink { + EnvPathInjectionFromCommandSink() { + exists(CommandSource source | + this.asExpr() = source.getEnclosingRun().getScriptScalar() and + Bash::cmdReachingGitHubFileWrite(source.getEnclosingRun(), source.getCommand(), "GITHUB_PATH", + _) + ) + } +} + /** * Holds if a Run step declares an environment variable, uses it to declare a PATH env var. * e.g. @@ -65,7 +67,7 @@ class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink { class EnvPathInjectionFromEnvVarSink extends EnvPathInjectionSink { EnvPathInjectionFromEnvVarSink() { exists(Run run, string var_name | - envToSpecialFile("GITHUB_PATH", var_name, run, _) and + Bash::envReachingGitHubFileWrite(run, var_name, "GITHUB_PATH", _) and exists(run.getInScopeEnvVarExpr(var_name)) and run.getScriptScalar() = this.asExpr() ) @@ -84,6 +86,28 @@ private module EnvPathInjectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof EnvPathInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Run run, string var | + run.getInScopeEnvVarExpr(var) = pred.asExpr() and + succ.asExpr() = run.getScriptScalar() and + Bash::envReachingGitHubFileWrite(run, var, ["GITHUB_ENV", "GITHUB_OUTPUT", "GITHUB_PATH"], _) + ) + or + exists(Uses step | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = step and + succ.asExpr() = step and + madSink(succ, "envpath-injection") + ) + or + exists(Run run | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) + } } /** Tracks flow of unsafe user input that is used to construct and evaluate the PATH environment variable. */ diff --git a/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll b/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll index 65c6938f0a4..dd6b8342185 100644 --- a/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll @@ -14,8 +14,12 @@ abstract class EnvVarInjectionSink extends DataFlow::Node { } * e.g. * run: | * cat test-results/.env >> $GITHUB_ENV + * * echo "sha=$(cat test-results/sha-number)" >> $GITHUB_ENV * echo "sha=$(> $GITHUB_ENV + * + * FOO=$(cat test-results/sha-number) + * echo "FOO=$FOO" >> $GITHUB_ENV */ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink { EnvVarInjectionFromFileReadSink() { @@ -27,37 +31,34 @@ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink { this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and ( - // e.g. - // cat test-results/.env >> $GITHUB_ENV - Bash::fileToGitHubEnv(run, _) - or - exists(string value | - run.getAWriteToGitHubEnv(_, value) and - ( - // e.g. - // echo "FOO=$(cat test-results/sha-number)" >> $GITHUB_ENV - Bash::outputsPartialFileContent(run, value) - or - // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_ENV - exists(string var_name, string var_value | - run.getAnAssignment(var_name, var_value) and - Bash::outputsPartialFileContent(run, var_value) and - ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") - or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 - ) - ) - ) + exists(string cmd | + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_ENV", _) and + Bash::outputsPartialFileContent(run, cmd) ) + or + Bash::fileToGitHubEnv(run, _) ) ) } } +/** + * Holds if a Run step executes a command that returns untrusted data which flows to GITHUB_ENV + * e.g. + * run: | + * COMMIT_MESSAGE=$(git log --format=%s) + * echo "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV + */ +class EnvVarInjectionFromCommandSink extends EnvVarInjectionSink { + EnvVarInjectionFromCommandSink() { + exists(CommandSource source | + this.asExpr() = source.getEnclosingRun().getScriptScalar() and + Bash::cmdReachingGitHubFileWrite(source.getEnclosingRun(), source.getCommand(), "GITHUB_ENV", + _) + ) + } +} + /** * Holds if a Run step declares an environment variable, uses it to declare env var. * e.g. @@ -69,9 +70,9 @@ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink { class EnvVarInjectionFromEnvVarSink extends EnvVarInjectionSink { EnvVarInjectionFromEnvVarSink() { exists(Run run, string var_name | - envToSpecialFile("GITHUB_ENV", var_name, run, _) and exists(run.getInScopeEnvVarExpr(var_name)) and - run.getScriptScalar() = this.asExpr() + run.getScriptScalar() = this.asExpr() and + Bash::envReachingGitHubFileWrite(run, var_name, "GITHUB_ENV", _) ) } } @@ -104,6 +105,28 @@ private module EnvVarInjectionConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { sink instanceof EnvVarInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Run run, string var | + run.getInScopeEnvVarExpr(var) = pred.asExpr() and + succ.asExpr() = run.getScriptScalar() and + Bash::envReachingGitHubFileWrite(run, var, ["GITHUB_ENV", "GITHUB_OUTPUT", "GITHUB_PATH"], _) + ) + or + exists(Uses step | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = step and + succ.asExpr() = step and + madSink(succ, "envvar-injection") + ) + or + exists(Run run | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) + } } /** Tracks flow of unsafe user input that is used to construct and evaluate an environment variable. */ diff --git a/ql/lib/codeql/actions/security/OutputClobberingQuery.qll b/ql/lib/codeql/actions/security/OutputClobberingQuery.qll index 8541286f6e1..4f9eeef7579 100644 --- a/ql/lib/codeql/actions/security/OutputClobberingQuery.qll +++ b/ql/lib/codeql/actions/security/OutputClobberingQuery.qll @@ -10,7 +10,7 @@ import codeql.actions.dataflow.FlowSources abstract class OutputClobberingSink extends DataFlow::Node { } /** - * Holds if a Run step declares an environment variable with contents from a local file. + * Holds if a Run step declares a step output variable with contents from a local file. * e.g. * run: | * cat test-results/.vars >> $GITHUB_OUTPUT @@ -21,58 +21,43 @@ class OutputClobberingFromFileReadSink extends OutputClobberingSink { OutputClobberingFromFileReadSink() { exists(Run run, Step step | ( - step instanceof UntrustedArtifactDownloadStep or + step instanceof UntrustedArtifactDownloadStep + or // This shoould be: // artifact instanceof PRHeadCheckoutStep // but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error // so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround // instead of using ActionsMutableRefCheckout and ActionsSHACheckout - step.(Uses).getCallee() = "actions/checkout" or - step instanceof GitMutableRefCheckout or - step instanceof GitSHACheckout or - step instanceof GhMutableRefCheckout or + exists(Uses uses | + step = uses and + uses.getCallee() = "actions/checkout" and + exists(uses.getArgument("ref")) + ) + or + step instanceof GitMutableRefCheckout + or + step instanceof GitSHACheckout + or + step instanceof GhMutableRefCheckout + or step instanceof GhSHACheckout ) and - this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and + this.asExpr() = run.getScriptScalar() and ( - // e.g. - // cat test-results/.vars >> $GITHUB_OUTPUT - Bash::fileToGitHubOutput(run, _) - or - exists(string key, string value | - run.getAWriteToGitHubOutput(key, value) and - // there is a different output variable in the same script - // TODO: key2/value2 should be declared before key/value - exists(string key2 | - run.getAWriteToGitHubOutput(key2, _) and - not key2 = key - ) and - ( - Bash::outputsPartialFileContent(run, value) - or - // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_OUTPUT - exists(string var_name, string var_value | - run.getAnAssignment(var_name, var_value) and - Bash::outputsPartialFileContent(run, var_value) and - ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") - or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 - ) - ) - ) + exists(string cmd | + Bash::cmdReachingGitHubFileWrite(run, cmd, "GITHUB_OUTPUT", _) and + Bash::outputsPartialFileContent(run, cmd) ) + or + Bash::fileToGitHubOutput(run, _) ) ) } } /** - * Holds if a Run step declares an environment variable, uses it to declare env var. + * Holds if a Run step declares an environment variable, uses it in a step variable output. * e.g. * env: * BODY: ${{ github.event.comment.body }} @@ -81,15 +66,15 @@ class OutputClobberingFromFileReadSink extends OutputClobberingSink { */ class OutputClobberingFromEnvVarSink extends OutputClobberingSink { OutputClobberingFromEnvVarSink() { - exists(Run run, string var_name, string key | - envToSpecialFile("GITHUB_OUTPUT", var_name, run, key) and + exists(Run run, string var, string field | + Bash::envReachingGitHubFileWrite(run, var, "GITHUB_OUTPUT", field) and // there is a different output variable in the same script // TODO: key2/value2 should be declared before key/value - exists(string key2 | - run.getAWriteToGitHubOutput(key2, _) and - not key2 = key + exists(string field2 | + run.getAWriteToGitHubOutput(field2, _) and + not field2 = field ) and - exists(run.getInScopeEnvVarExpr(var_name)) and + exists(run.getInScopeEnvVarExpr(var)) and run.getScriptScalar() = this.asExpr() ) } @@ -113,10 +98,9 @@ class OutputClobberingFromEnvVarSink extends OutputClobberingSink { */ class WorkflowCommandClobberingFromEnvVarSink extends OutputClobberingSink { WorkflowCommandClobberingFromEnvVarSink() { - exists(Run run, string output_line, string clobbering_line, string var_name | - run.getScript().splitAt("\n") = output_line and - Bash::singleLineWorkflowCmd(output_line, "set-output", _, _) and - run.getScript().splitAt("\n") = clobbering_line and + exists(Run run, string clobbering_line, string var_name | + Bash::singleLineWorkflowCmd(run.getACommand(), "set-output", _, _) and + run.getACommand() = clobbering_line and clobbering_line.regexpMatch(".*echo\\s+(-e\\s+)?(\"|')?\\$(\\{)?" + var_name + ".*") and exists(run.getInScopeEnvVarExpr(var_name)) and run.getScriptScalar() = this.asExpr() @@ -124,13 +108,36 @@ class WorkflowCommandClobberingFromEnvVarSink extends OutputClobberingSink { } } +/** + * - id: clob1 + * run: | + * # VULNERABLE + * PR="$(; @@ -93,6 +102,15 @@ private module ActionsSHACheckoutConfig implements DataFlow::ConfigSig { uses.getArgumentExpr("ref") = sink.asExpr() ) } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Run run | + pred instanceof FileSource and + pred.asExpr().(Step).getAFollowingStep() = run and + succ.asExpr() = run.getScriptScalar() and + Bash::outputsPartialFileContent(run, run.getACommand()) + ) + } } module ActionsSHACheckoutFlow = TaintTracking::Global; @@ -139,7 +157,7 @@ predicate containsHeadSHA(string s) { "\\bgithub\\.event\\.merge_group\\.head_sha\\b", "\\bgithub\\.event\\.merge_group\\.head_commit\\.id\\b", // heuristics - "\\bhead\\.sha\\b", "\\bhead_sha\\b", "\\bpr_head_sha\\b" + "\\bhead\\.sha\\b", "\\bhead_sha\\b", "\\bmerge_sha\\b", "\\bpr_head_sha\\b" ], _, _) ) } @@ -156,7 +174,7 @@ predicate containsHeadRef(string s) { "\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.head\\.ref\\b", "\\bgithub\\.event\\.merge_group\\.head_ref\\b", // heuristics - "\\bhead\\.ref\\b", "\\bhead_ref\\b", "\\bpr_head_ref\\b", + "\\bhead\\.ref\\b", "\\bhead_ref\\b", "\\bmerge_ref\\b", "\\bpr_head_ref\\b", // env vars "GITHUB_HEAD_REF", ], _, _) From 1e749ae6d5ddff29c0bd1bac751c75ab5bbdb2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 11 Oct 2024 12:20:39 +0200 Subject: [PATCH 5/6] Add new poisonable step --- ql/lib/ext/config/poisonable_steps.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/ql/lib/ext/config/poisonable_steps.yml b/ql/lib/ext/config/poisonable_steps.yml index 1543e2d8d45..aa5148d7cf6 100644 --- a/ql/lib/ext/config/poisonable_steps.yml +++ b/ql/lib/ext/config/poisonable_steps.yml @@ -52,6 +52,7 @@ extensions: - ["rails\\s+assets:precompile"] - ["rubocop"] - ["sed\\s+-f"] + - ["sonar-scanner"] - ["stylelint"] - ["terraform"] - ["tflint"] From 99e92af0342654cd86e600f03207b8aa005e7d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 11 Oct 2024 12:20:57 +0200 Subject: [PATCH 6/6] Update tests --- .../library-tests/poisonable_steps.expected | 2 + ql/test/library-tests/test.ql | 2 +- .../.github/workflows/calling_composite.yml | 0 .../.github/workflows/calling_workflow.yml | 0 .../.github/workflows/reusable_workflow.yml | 0 .../CompositeActionsSinks.expected | 0 .../CompositeActionsSinks.qlref | 0 .../CompositeActionsSources.expected | 0 .../CompositeActionsSources.qlref | 0 .../CompositeActionsSummaries.expected | 0 .../CompositeActionsSummaries.qlref | 0 .../ReusableWorkflowsSinks.expected | 0 .../ReusableWorkflowsSinks.qlref | 0 .../ReusableWorkflowsSources.expected | 0 .../ReusableWorkflowsSources.qlref | 0 .../ReusableWorkflowsSummaries.expected | 0 .../ReusableWorkflowsSummaries.qlref | 0 .../CWE-020 => Models}/action1/action.yml | 0 .../CWE-074/OutputClobberingHigh.expected | 16 +- .../CWE-077/.github/workflows/test13.yml | 23 +++ .../CWE-077/.github/workflows/test14.yml | 30 ++++ .../CWE-077/.github/workflows/test15.yml | 29 ++++ .../CWE-077/.github/workflows/test8.yml | 2 - .../CWE-077/EnvPathInjectionCritical.expected | 11 +- .../CWE-077/EnvPathInjectionMedium.expected | 11 +- .../CWE-077/EnvVarInjectionCritical.expected | 77 +++++---- .../CWE-077/EnvVarInjectionMedium.expected | 65 ++++---- .../.github/workflows/arg_injection.yml | 12 +- .../ArgumentInjectionCritical.expected | 49 +++--- .../CWE-088/ArgumentInjectionMedium.expected | 31 ++-- .../CWE-094/.github/workflows/test.yml | 15 +- .../CWE-094/.github/workflows/test1.yml | 4 +- .../CWE-094/.github/workflows/test14.yml | 51 ++++++ .../CWE-094/.github/workflows/test15.yml | 38 +++++ .../CWE-094/CodeInjectionCritical.expected | 146 +++++++++++------- .../CWE-094/CodeInjectionMedium.expected | 134 ++++++++++------ .../ArtifactPoisoningCritical.expected | 38 ++--- .../CWE-829/ArtifactPoisoningMedium.expected | 38 ++--- 38 files changed, 544 insertions(+), 280 deletions(-) rename ql/test/query-tests/{Security/CWE-020 => Models}/.github/workflows/calling_composite.yml (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/.github/workflows/calling_workflow.yml (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/.github/workflows/reusable_workflow.yml (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSinks.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSinks.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSources.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSources.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSummaries.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/CompositeActionsSummaries.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSinks.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSinks.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSources.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSources.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSummaries.expected (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/ReusableWorkflowsSummaries.qlref (100%) rename ql/test/query-tests/{Security/CWE-020 => Models}/action1/action.yml (100%) create mode 100644 ql/test/query-tests/Security/CWE-077/.github/workflows/test13.yml create mode 100644 ql/test/query-tests/Security/CWE-077/.github/workflows/test14.yml create mode 100644 ql/test/query-tests/Security/CWE-077/.github/workflows/test15.yml create mode 100644 ql/test/query-tests/Security/CWE-094/.github/workflows/test14.yml create mode 100644 ql/test/query-tests/Security/CWE-094/.github/workflows/test15.yml diff --git a/ql/test/library-tests/poisonable_steps.expected b/ql/test/library-tests/poisonable_steps.expected index a87ec0a341c..100eddb1400 100644 --- a/ql/test/library-tests/poisonable_steps.expected +++ b/ql/test/library-tests/poisonable_steps.expected @@ -1,3 +1,5 @@ +| .github/workflows/multiline2.yml:63:9:66:6 | Run Step | +| .github/workflows/multiline.yml:63:9:66:6 | Run Step | | .github/workflows/poisonable_steps.yml:8:9:13:6 | Uses Step | | .github/workflows/poisonable_steps.yml:13:9:14:6 | Run Step | | .github/workflows/poisonable_steps.yml:14:9:15:6 | Run Step | diff --git a/ql/test/library-tests/test.ql b/ql/test/library-tests/test.ql index 5880e06da7f..03f9e5b1840 100644 --- a/ql/test/library-tests/test.ql +++ b/ql/test/library-tests/test.ql @@ -150,6 +150,6 @@ query predicate isBashParameterExpansion(string parameter, string operator, stri "${parameter21%%pattern}", "${parameter22/pattern/string}", "${parameter23//pattern/string}", ] and - Bash::isBashParameterExpansion(test, parameter, operator, params) + Bash::isParameterExpansion(test, parameter, operator, params) ) } diff --git a/ql/test/query-tests/Security/CWE-020/.github/workflows/calling_composite.yml b/ql/test/query-tests/Models/.github/workflows/calling_composite.yml similarity index 100% rename from ql/test/query-tests/Security/CWE-020/.github/workflows/calling_composite.yml rename to ql/test/query-tests/Models/.github/workflows/calling_composite.yml diff --git a/ql/test/query-tests/Security/CWE-020/.github/workflows/calling_workflow.yml b/ql/test/query-tests/Models/.github/workflows/calling_workflow.yml similarity index 100% rename from ql/test/query-tests/Security/CWE-020/.github/workflows/calling_workflow.yml rename to ql/test/query-tests/Models/.github/workflows/calling_workflow.yml diff --git a/ql/test/query-tests/Security/CWE-020/.github/workflows/reusable_workflow.yml b/ql/test/query-tests/Models/.github/workflows/reusable_workflow.yml similarity index 100% rename from ql/test/query-tests/Security/CWE-020/.github/workflows/reusable_workflow.yml rename to ql/test/query-tests/Models/.github/workflows/reusable_workflow.yml diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSinks.expected b/ql/test/query-tests/Models/CompositeActionsSinks.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSinks.expected rename to ql/test/query-tests/Models/CompositeActionsSinks.expected diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSinks.qlref b/ql/test/query-tests/Models/CompositeActionsSinks.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSinks.qlref rename to ql/test/query-tests/Models/CompositeActionsSinks.qlref diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSources.expected b/ql/test/query-tests/Models/CompositeActionsSources.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSources.expected rename to ql/test/query-tests/Models/CompositeActionsSources.expected diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSources.qlref b/ql/test/query-tests/Models/CompositeActionsSources.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSources.qlref rename to ql/test/query-tests/Models/CompositeActionsSources.qlref diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSummaries.expected b/ql/test/query-tests/Models/CompositeActionsSummaries.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSummaries.expected rename to ql/test/query-tests/Models/CompositeActionsSummaries.expected diff --git a/ql/test/query-tests/Security/CWE-020/CompositeActionsSummaries.qlref b/ql/test/query-tests/Models/CompositeActionsSummaries.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/CompositeActionsSummaries.qlref rename to ql/test/query-tests/Models/CompositeActionsSummaries.qlref diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSinks.expected b/ql/test/query-tests/Models/ReusableWorkflowsSinks.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSinks.expected rename to ql/test/query-tests/Models/ReusableWorkflowsSinks.expected diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSinks.qlref b/ql/test/query-tests/Models/ReusableWorkflowsSinks.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSinks.qlref rename to ql/test/query-tests/Models/ReusableWorkflowsSinks.qlref diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSources.expected b/ql/test/query-tests/Models/ReusableWorkflowsSources.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSources.expected rename to ql/test/query-tests/Models/ReusableWorkflowsSources.expected diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSources.qlref b/ql/test/query-tests/Models/ReusableWorkflowsSources.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSources.qlref rename to ql/test/query-tests/Models/ReusableWorkflowsSources.qlref diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSummaries.expected b/ql/test/query-tests/Models/ReusableWorkflowsSummaries.expected similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSummaries.expected rename to ql/test/query-tests/Models/ReusableWorkflowsSummaries.expected diff --git a/ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSummaries.qlref b/ql/test/query-tests/Models/ReusableWorkflowsSummaries.qlref similarity index 100% rename from ql/test/query-tests/Security/CWE-020/ReusableWorkflowsSummaries.qlref rename to ql/test/query-tests/Models/ReusableWorkflowsSummaries.qlref diff --git a/ql/test/query-tests/Security/CWE-020/action1/action.yml b/ql/test/query-tests/Models/action1/action.yml similarity index 100% rename from ql/test/query-tests/Security/CWE-020/action1/action.yml rename to ql/test/query-tests/Models/action1/action.yml diff --git a/ql/test/query-tests/Security/CWE-074/OutputClobberingHigh.expected b/ql/test/query-tests/Security/CWE-074/OutputClobberingHigh.expected index b6cb2a32e47..715e2c4c90c 100644 --- a/ql/test/query-tests/Security/CWE-074/OutputClobberingHigh.expected +++ b/ql/test/query-tests/Security/CWE-074/OutputClobberingHigh.expected @@ -1,12 +1,12 @@ edges -| .github/workflows/output1.yml:9:18:9:49 | github.event.comment.body | .github/workflows/output1.yml:10:14:13:50 | # VULNERABLE\necho "OUTPUT_1=HARDCODED" >> $GITHUB_OUTPUT\necho "OUTPUT_2=$BODY" >> $GITHUB_OUTPUT\n | provenance | | -| .github/workflows/output1.yml:30:9:35:6 | Uses Step | .github/workflows/output1.yml:36:14:38:58 | echo "OUTPUT_1=HARDCODED" >> $GITHUB_OUTPUT\necho "OUTPUT_2=$(> $GITHUB_OUTPUT\n | provenance | | -| .github/workflows/output2.yml:9:18:9:49 | github.event.comment.body | .github/workflows/output2.yml:10:14:13:48 | # VULNERABLE\necho $BODY\necho "::set-output name=OUTPUT::SAFE"\n | provenance | | -| .github/workflows/output2.yml:16:18:16:49 | github.event.comment.body | .github/workflows/output2.yml:17:14:20:21 | # VULNERABLE\necho "::set-output name=OUTPUT::SAFE"\necho $BODY\n | provenance | | -| .github/workflows/output2.yml:36:9:41:6 | Uses Step | .github/workflows/output2.yml:42:14:46:48 | # VULNERABLE\nPR="$(> $GITHUB_OUTPUT\necho "OUTPUT_2=$BODY" >> $GITHUB_OUTPUT\n | provenance | Config | +| .github/workflows/output1.yml:30:9:35:6 | Uses Step | .github/workflows/output1.yml:36:14:38:58 | echo "OUTPUT_1=HARDCODED" >> $GITHUB_OUTPUT\necho "OUTPUT_2=$(> $GITHUB_OUTPUT\n | provenance | Config | +| .github/workflows/output2.yml:9:18:9:49 | github.event.comment.body | .github/workflows/output2.yml:10:14:13:48 | # VULNERABLE\necho $BODY\necho "::set-output name=OUTPUT::SAFE"\n | provenance | Config | +| .github/workflows/output2.yml:16:18:16:49 | github.event.comment.body | .github/workflows/output2.yml:17:14:20:21 | # VULNERABLE\necho "::set-output name=OUTPUT::SAFE"\necho $BODY\n | provenance | Config | +| .github/workflows/output2.yml:36:9:41:6 | Uses Step | .github/workflows/output2.yml:42:14:46:48 | # VULNERABLE\nPR="$(> $GITHUB_OUTPUT\necho "OUTPUT_2=$BODY" >> $GITHUB_OUTPUT\n | semmle.label | # VULNERABLE\necho "OUTPUT_1=HARDCODED" >> $GITHUB_OUTPUT\necho "OUTPUT_2=$BODY" >> $GITHUB_OUTPUT\n | diff --git a/ql/test/query-tests/Security/CWE-077/.github/workflows/test13.yml b/ql/test/query-tests/Security/CWE-077/.github/workflows/test13.yml new file mode 100644 index 00000000000..78d288fb982 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-077/.github/workflows/test13.yml @@ -0,0 +1,23 @@ +name: publish +on: + pull_request_target: + branches: + - main +jobs: + need-publish: + permissions: + actions: write + name: Need Publish + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + - name: Get commit message + run: | + COMMIT_MESSAGE=$(git log --format=%s) + echo "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV + - name: Get commit message + run: | + echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV diff --git a/ql/test/query-tests/Security/CWE-077/.github/workflows/test14.yml b/ql/test/query-tests/Security/CWE-077/.github/workflows/test14.yml new file mode 100644 index 00000000000..93854c5e889 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-077/.github/workflows/test14.yml @@ -0,0 +1,30 @@ +name: Pull Request Open + +on: + pull_request_target: + +jobs: + test1: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV" + - run: echo "${{ env.CHANGED-FILES }}" + test2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/) + echo "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV" + - run: echo "${{ env.CHANGED-FILES }}" + + + diff --git a/ql/test/query-tests/Security/CWE-077/.github/workflows/test15.yml b/ql/test/query-tests/Security/CWE-077/.github/workflows/test15.yml new file mode 100644 index 00000000000..89ecd8c0ec3 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-077/.github/workflows/test15.yml @@ -0,0 +1,29 @@ +name: Pull Request Open + +on: + pull_request_target: + +jobs: + test1: + runs-on: ubuntu-latest + steps: + - id: title + run: | + echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV" + - run: echo "$TITLE" + test2: + runs-on: ubuntu-latest + steps: + - id: title + run: | + PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH}) + echo "BODY=$PR_BODY" >> "$GITHUB_ENV" + - run: echo "$TITLE" + test3: + runs-on: ubuntu-latest + steps: + - run: | + echo "branch_name=$(jq --raw-output .pull_request.head.ref $GITHUB_EVENT_PATH)" >> $GITHUB_ENV + + + diff --git a/ql/test/query-tests/Security/CWE-077/.github/workflows/test8.yml b/ql/test/query-tests/Security/CWE-077/.github/workflows/test8.yml index 05bde57551d..806f8dc8e45 100644 --- a/ql/test/query-tests/Security/CWE-077/.github/workflows/test8.yml +++ b/ql/test/query-tests/Security/CWE-077/.github/workflows/test8.yml @@ -20,8 +20,6 @@ jobs: contents: write steps: - uses: actions/checkout@v4 - with: - ref: foo - name: Download and Extract Artifacts uses: dawidd6/action-download-artifact@v6 diff --git a/ql/test/query-tests/Security/CWE-077/EnvPathInjectionCritical.expected b/ql/test/query-tests/Security/CWE-077/EnvPathInjectionCritical.expected index 7fab238795c..851aa524154 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvPathInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvPathInjectionCritical.expected @@ -1,10 +1,9 @@ edges -| .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:16:21:16:58 | github.event.pull_request.title | .github/workflows/path1.yml:17:14:17:42 | echo $PATHINJ >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:19:21:19:58 | github.event.pull_request.title | .github/workflows/path1.yml:20:14:20:44 | echo ${PATHINJ} >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:25:14:25:50 | echo "$(cat foo/bar)" >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | | -| .github/workflows/path1.yml:28:21:28:58 | github.event.pull_request.title | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | | +| .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:16:21:16:58 | github.event.pull_request.title | .github/workflows/path1.yml:17:14:17:42 | echo $PATHINJ >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:19:21:19:58 | github.event.pull_request.title | .github/workflows/path1.yml:20:14:20:44 | echo ${PATHINJ} >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:25:14:25:50 | echo "$(cat foo/bar)" >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:28:21:28:58 | github.event.pull_request.title | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | Config | nodes | .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | semmle.label | github.event.pull_request.title | | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | semmle.label | echo $(echo "$PATHINJ") >> $GITHUB_PATH | diff --git a/ql/test/query-tests/Security/CWE-077/EnvPathInjectionMedium.expected b/ql/test/query-tests/Security/CWE-077/EnvPathInjectionMedium.expected index ea360bc56df..5be9f729ad6 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvPathInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvPathInjectionMedium.expected @@ -1,10 +1,9 @@ edges -| .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:16:21:16:58 | github.event.pull_request.title | .github/workflows/path1.yml:17:14:17:42 | echo $PATHINJ >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:19:21:19:58 | github.event.pull_request.title | .github/workflows/path1.yml:20:14:20:44 | echo ${PATHINJ} >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:25:14:25:50 | echo "$(cat foo/bar)" >> $GITHUB_PATH | provenance | | -| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | | -| .github/workflows/path1.yml:28:21:28:58 | github.event.pull_request.title | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | | +| .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:16:21:16:58 | github.event.pull_request.title | .github/workflows/path1.yml:17:14:17:42 | echo $PATHINJ >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:19:21:19:58 | github.event.pull_request.title | .github/workflows/path1.yml:20:14:20:44 | echo ${PATHINJ} >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:21:9:25:6 | Uses Step | .github/workflows/path1.yml:25:14:25:50 | echo "$(cat foo/bar)" >> $GITHUB_PATH | provenance | Config | +| .github/workflows/path1.yml:28:21:28:58 | github.event.pull_request.title | .github/workflows/path1.yml:29:14:29:40 | echo "::add-path::$PATHINJ" | provenance | Config | nodes | .github/workflows/path1.yml:13:21:13:58 | github.event.pull_request.title | semmle.label | github.event.pull_request.title | | .github/workflows/path1.yml:14:14:14:52 | echo $(echo "$PATHINJ") >> $GITHUB_PATH | semmle.label | echo $(echo "$PATHINJ") >> $GITHUB_PATH | diff --git a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected index 6ad5cf04304..aff785242f9 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected @@ -1,30 +1,29 @@ edges -| .github/workflows/test2.yml:12:9:41:6 | Uses Step | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test3.yml:13:7:20:4 | Uses Step | .github/workflows/test3.yml:20:12:23:77 | echo "PR_NUMBER=$(cat pr_number.txt \| jq -r .)" >> $GITHUB_ENV\necho "PR_HEAD_REPO=$(cat pr_head_repo.txt \| jq -Rr .)" >> $GITHUB_ENV\necho "PR_HEAD_REF=$(cat pr_head_ref.txt \| jq -Rr .)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test4.yml:12:14:13:48 | echo "PR_TITLE=$TITLE" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:15:19:15:56 | github.event.pull_request.title | .github/workflows/test4.yml:16:14:17:50 | echo "PR_TITLE=${TITLE}" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:19:19:19:56 | github.event.pull_request.title | .github/workflows/test4.yml:20:14:21:54 | echo PR_TITLE=$(echo $TITLE) >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:23:19:23:56 | github.event.pull_request.title | .github/workflows/test4.yml:24:14:27:36 | echo "PR_TITLE<> $GITHUB_ENV\necho "$TITLE" >> $GITHUB_ENV\necho "EOF" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:29:19:29:56 | github.event.pull_request.title | .github/workflows/test4.yml:30:14:33:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\necho "$TITLE" >> "${GITHUB_ENV}"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | | -| .github/workflows/test4.yml:35:19:35:56 | github.event.pull_request.title | .github/workflows/test4.yml:36:14:41:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test4.yml:43:19:43:56 | github.event.pull_request.title | .github/workflows/test4.yml:44:14:47:14 | cat <<-EOF >> "$GITHUB_ENV"\nFOO=$TITLE\nEOF\n | provenance | | -| .github/workflows/test4.yml:57:27:57:64 | github.event.pull_request.title | .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | provenance | | -| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P[0-9]+)') >> $GITHUB_ENV | provenance | | -| .github/workflows/test5.yml:10:9:30:6 | Uses Step | .github/workflows/test5.yml:33:14:36:62 | echo "PR_NUM=$(cat coverage/pr_num.txt)" >> $GITHUB_ENV\necho "BASE=$(cat coverage/base.txt)" >> $GITHUB_ENV\necho "HEAD=$(cat coverage/head.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test7.yml:9:9:16:6 | Uses Step | .github/workflows/test7.yml:16:9:24:35 | Uses Step | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test9.yml:19:9:27:6 | Uses Step | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test10.yml:20:9:26:6 | Uses Step | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | provenance | | -| .github/workflows/test11.yml:15:9:21:6 | Uses Step | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:55:9:61:6 | Uses Step | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:55:9:61:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | | +| .github/workflows/test2.yml:12:9:41:6 | Uses Step | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test3.yml:13:7:20:4 | Uses Step | .github/workflows/test3.yml:20:12:23:77 | echo "PR_NUMBER=$(cat pr_number.txt \| jq -r .)" >> $GITHUB_ENV\necho "PR_HEAD_REPO=$(cat pr_head_repo.txt \| jq -Rr .)" >> $GITHUB_ENV\necho "PR_HEAD_REF=$(cat pr_head_ref.txt \| jq -Rr .)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test4.yml:12:14:13:48 | echo "PR_TITLE=$TITLE" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:15:19:15:56 | github.event.pull_request.title | .github/workflows/test4.yml:16:14:17:50 | echo "PR_TITLE=${TITLE}" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:19:19:19:56 | github.event.pull_request.title | .github/workflows/test4.yml:20:14:21:54 | echo PR_TITLE=$(echo $TITLE) >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:23:19:23:56 | github.event.pull_request.title | .github/workflows/test4.yml:24:14:27:36 | echo "PR_TITLE<> $GITHUB_ENV\necho "$TITLE" >> $GITHUB_ENV\necho "EOF" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:29:19:29:56 | github.event.pull_request.title | .github/workflows/test4.yml:30:14:33:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\necho "$TITLE" >> "${GITHUB_ENV}"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | Config | +| .github/workflows/test4.yml:35:19:35:56 | github.event.pull_request.title | .github/workflows/test4.yml:36:14:41:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test4.yml:43:19:43:56 | github.event.pull_request.title | .github/workflows/test4.yml:44:14:47:14 | cat <<-EOF >> "$GITHUB_ENV"\nFOO=$TITLE\nEOF\n | provenance | Config | +| .github/workflows/test4.yml:57:27:57:64 | github.event.pull_request.title | .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P[0-9]+)') >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test5.yml:10:9:30:6 | Uses Step | .github/workflows/test5.yml:33:14:36:62 | echo "PR_NUM=$(cat coverage/pr_num.txt)" >> $GITHUB_ENV\necho "BASE=$(cat coverage/base.txt)" >> $GITHUB_ENV\necho "HEAD=$(cat coverage/head.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test7.yml:9:9:16:6 | Uses Step | .github/workflows/test7.yml:16:9:24:35 | Uses Step | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test9.yml:19:9:27:6 | Uses Step | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test10.yml:20:9:26:6 | Uses Step | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test11.yml:15:9:21:6 | Uses Step | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:55:9:61:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | Config | nodes | .github/workflows/test2.yml:12:9:41:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | semmle.label | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | @@ -58,10 +57,10 @@ nodes | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | semmle.label | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | | .github/workflows/test7.yml:9:9:16:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test7.yml:16:9:24:35 | Uses Step | semmle.label | Uses Step | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | semmle.label | Uses Step | -| .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | semmle.label | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | semmle.label | Uses Step | +| .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | semmle.label | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | | .github/workflows/test9.yml:19:9:27:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | | .github/workflows/test10.yml:20:9:26:6 | Uses Step | semmle.label | Uses Step | @@ -72,6 +71,12 @@ nodes | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | semmle.label | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | | .github/workflows/test12.yml:55:9:61:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | semmle.label | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | +| .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | semmle.label | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | +| .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | semmle.label | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | +| .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | semmle.label | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | semmle.label | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | semmle.label | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | subpaths #select | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | .github/workflows/test2.yml:12:9:41:6 | Uses Step | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | @@ -90,12 +95,18 @@ subpaths | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | | .github/workflows/test7.yml:16:9:24:35 | Uses Step | .github/workflows/test7.yml:9:9:16:6 | Uses Step | .github/workflows/test7.yml:16:9:24:35 | Uses Step | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test7.yml:16:9:24:35 | Uses Step | Uses Step | -| .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | .github/workflows/test9.yml:19:9:27:6 | Uses Step | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | .github/workflows/test10.yml:20:9:26:6 | Uses Step | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | cat foo/.github/java-config.env >> $GITHUB_ENV | | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | .github/workflows/test11.yml:15:9:21:6 | Uses Step | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | .github/workflows/test12.yml:55:9:61:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | +| .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | +| .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | +| .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | diff --git a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected index 82602ee8ed8..1ac092dd0d3 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected @@ -1,30 +1,29 @@ edges -| .github/workflows/test2.yml:12:9:41:6 | Uses Step | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test3.yml:13:7:20:4 | Uses Step | .github/workflows/test3.yml:20:12:23:77 | echo "PR_NUMBER=$(cat pr_number.txt \| jq -r .)" >> $GITHUB_ENV\necho "PR_HEAD_REPO=$(cat pr_head_repo.txt \| jq -Rr .)" >> $GITHUB_ENV\necho "PR_HEAD_REF=$(cat pr_head_ref.txt \| jq -Rr .)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test4.yml:12:14:13:48 | echo "PR_TITLE=$TITLE" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:15:19:15:56 | github.event.pull_request.title | .github/workflows/test4.yml:16:14:17:50 | echo "PR_TITLE=${TITLE}" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:19:19:19:56 | github.event.pull_request.title | .github/workflows/test4.yml:20:14:21:54 | echo PR_TITLE=$(echo $TITLE) >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:23:19:23:56 | github.event.pull_request.title | .github/workflows/test4.yml:24:14:27:36 | echo "PR_TITLE<> $GITHUB_ENV\necho "$TITLE" >> $GITHUB_ENV\necho "EOF" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test4.yml:29:19:29:56 | github.event.pull_request.title | .github/workflows/test4.yml:30:14:33:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\necho "$TITLE" >> "${GITHUB_ENV}"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | | -| .github/workflows/test4.yml:35:19:35:56 | github.event.pull_request.title | .github/workflows/test4.yml:36:14:41:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test4.yml:43:19:43:56 | github.event.pull_request.title | .github/workflows/test4.yml:44:14:47:14 | cat <<-EOF >> "$GITHUB_ENV"\nFOO=$TITLE\nEOF\n | provenance | | -| .github/workflows/test4.yml:57:27:57:64 | github.event.pull_request.title | .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | provenance | | -| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P[0-9]+)') >> $GITHUB_ENV | provenance | | -| .github/workflows/test5.yml:10:9:30:6 | Uses Step | .github/workflows/test5.yml:33:14:36:62 | echo "PR_NUM=$(cat coverage/pr_num.txt)" >> $GITHUB_ENV\necho "BASE=$(cat coverage/base.txt)" >> $GITHUB_ENV\necho "HEAD=$(cat coverage/head.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test7.yml:9:9:16:6 | Uses Step | .github/workflows/test7.yml:16:9:24:35 | Uses Step | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test9.yml:19:9:27:6 | Uses Step | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/test10.yml:20:9:26:6 | Uses Step | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | provenance | | -| .github/workflows/test11.yml:15:9:21:6 | Uses Step | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:55:9:61:6 | Uses Step | provenance | | -| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/test12.yml:55:9:61:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | | +| .github/workflows/test2.yml:12:9:41:6 | Uses Step | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test3.yml:13:7:20:4 | Uses Step | .github/workflows/test3.yml:20:12:23:77 | echo "PR_NUMBER=$(cat pr_number.txt \| jq -r .)" >> $GITHUB_ENV\necho "PR_HEAD_REPO=$(cat pr_head_repo.txt \| jq -Rr .)" >> $GITHUB_ENV\necho "PR_HEAD_REF=$(cat pr_head_ref.txt \| jq -Rr .)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test4.yml:12:14:13:48 | echo "PR_TITLE=$TITLE" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:15:19:15:56 | github.event.pull_request.title | .github/workflows/test4.yml:16:14:17:50 | echo "PR_TITLE=${TITLE}" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:19:19:19:56 | github.event.pull_request.title | .github/workflows/test4.yml:20:14:21:54 | echo PR_TITLE=$(echo $TITLE) >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:23:19:23:56 | github.event.pull_request.title | .github/workflows/test4.yml:24:14:27:36 | echo "PR_TITLE<> $GITHUB_ENV\necho "$TITLE" >> $GITHUB_ENV\necho "EOF" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test4.yml:29:19:29:56 | github.event.pull_request.title | .github/workflows/test4.yml:30:14:33:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\necho "$TITLE" >> "${GITHUB_ENV}"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | Config | +| .github/workflows/test4.yml:35:19:35:56 | github.event.pull_request.title | .github/workflows/test4.yml:36:14:41:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test4.yml:43:19:43:56 | github.event.pull_request.title | .github/workflows/test4.yml:44:14:47:14 | cat <<-EOF >> "$GITHUB_ENV"\nFOO=$TITLE\nEOF\n | provenance | Config | +| .github/workflows/test4.yml:57:27:57:64 | github.event.pull_request.title | .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P[0-9]+)') >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test5.yml:10:9:30:6 | Uses Step | .github/workflows/test5.yml:33:14:36:62 | echo "PR_NUM=$(cat coverage/pr_num.txt)" >> $GITHUB_ENV\necho "BASE=$(cat coverage/base.txt)" >> $GITHUB_ENV\necho "HEAD=$(cat coverage/head.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test7.yml:9:9:16:6 | Uses Step | .github/workflows/test7.yml:16:9:24:35 | Uses Step | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test9.yml:19:9:27:6 | Uses Step | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/test10.yml:20:9:26:6 | Uses Step | .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | provenance | Config | +| .github/workflows/test11.yml:15:9:21:6 | Uses Step | .github/workflows/test11.yml:23:14:28:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:38:9:46:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/test12.yml:55:9:61:6 | Uses Step | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | provenance | Config | nodes | .github/workflows/test2.yml:12:9:41:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test2.yml:41:14:43:52 | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | semmle.label | unzip pr.zip\necho "pr_number=$(cat NR)" >> $GITHUB_ENV\n | @@ -58,10 +57,10 @@ nodes | .github/workflows/test6.yml:22:14:24:52 | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | semmle.label | venv="$(echo $TITLE)')"\necho "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV\n | | .github/workflows/test7.yml:9:9:16:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test7.yml:16:9:24:35 | Uses Step | semmle.label | Uses Step | -| .github/workflows/test8.yml:26:9:32:6 | Uses Step | semmle.label | Uses Step | -| .github/workflows/test8.yml:33:14:35:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | semmle.label | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:37:14:38:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | -| .github/workflows/test8.yml:40:14:41:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:24:9:30:6 | Uses Step | semmle.label | Uses Step | +| .github/workflows/test8.yml:31:14:33:41 | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | semmle.label | foo=$(cat ./artifacts/parent-artifacts/event.txt)\necho "foo=$foo" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:35:14:36:82 | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(cat ./artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | +| .github/workflows/test8.yml:38:14:39:79 | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | semmle.label | echo "foo=$(< /artifacts/parent-artifacts/event.txt)" >> $GITHUB_ENV\n | | .github/workflows/test9.yml:19:9:27:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test9.yml:29:14:41:41 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_ENV\necho "ref=$ref" >> $GITHUB_ENV\n | | .github/workflows/test10.yml:20:9:26:6 | Uses Step | semmle.label | Uses Step | @@ -72,5 +71,11 @@ nodes | .github/workflows/test12.yml:48:14:53:29 | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | semmle.label | {\n echo 'RUNTIME_VERSIONS<> "$GITHUB_ENV"\n | | .github/workflows/test12.yml:55:9:61:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/test12.yml:63:14:68:29 | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | semmle.label | {\n echo 'PRERELEASE_REPORT<> "$GITHUB_ENV"\n | +| .github/workflows/test13.yml:18:14:20:65 | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | semmle.label | COMMIT_MESSAGE=$(git log --format=%s)\necho "COMMIT_MESSAGE=${COMMIT_MESSAGE}" >> $GITHUB_ENV\n | +| .github/workflows/test13.yml:22:14:23:70 | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | semmle.label | echo "COMMIT_MESSAGE=$(git log --format=%s)" >> $GITHUB_ENV\n | +| .github/workflows/test14.yml:14:14:15:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | semmle.label | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:24:14:26:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:11:14:12:98 | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | semmle.label | echo "BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:18:14:20:48 | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | semmle.label | PR_BODY=$(jq --raw-output .pull_request.body ${GITHUB_EVENT_PATH})\necho "BODY=$PR_BODY" >> "$GITHUB_ENV"\n | subpaths #select diff --git a/ql/test/query-tests/Security/CWE-088/.github/workflows/arg_injection.yml b/ql/test/query-tests/Security/CWE-088/.github/workflows/arg_injection.yml index 09e540a0f1b..59ea1564bdd 100644 --- a/ql/test/query-tests/Security/CWE-088/.github/workflows/arg_injection.yml +++ b/ql/test/query-tests/Security/CWE-088/.github/workflows/arg_injection.yml @@ -1,15 +1,18 @@ name: Argument injection on: - issues: - types: [opened, edited] + pull_request_target: jobs: test1: runs-on: ubuntu-latest env: - TITLE: ${{github.event.issue.title}} + TITLE: ${{github.event.pull_request.title}} steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} - run: echo "s/FOO/$TITLE/g" - run: sed "s/FOO/$TITLE/g" - run: echo "foo" | sed "s/FOO/$TITLE/g" > bar @@ -28,3 +31,6 @@ jobs: -e 's##${{ env.sot_repo }}#' \ -e 's##${TITLE}#' \ .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky + - run: | + BODY=$(git log --format=%s) + sed "s/FOO/$BODY/g" > /tmp/foo diff --git a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected index b5df9a2cbd3..326cb935f7c 100644 --- a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected @@ -1,27 +1,30 @@ edges -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | Config | nodes -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | semmle.label | github.event.issue.title | -| .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | semmle.label | sed "s/FOO/$TITLE/g" | -| .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | semmle.label | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | -| .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | semmle.label | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | -| .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | semmle.label | awk "BEGIN {$TITLE}" | -| .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | semmle.label | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | -| .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | semmle.label | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | -| .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | -| .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | semmle.label | github.event.pull_request.title | +| .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | semmle.label | sed "s/FOO/$TITLE/g" | +| .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | semmle.label | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | +| .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | semmle.label | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | +| .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | semmle.label | awk "BEGIN {$TITLE}" | +| .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | semmle.label | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | +| .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | semmle.label | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | +| .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | semmle.label | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | subpaths #select -| .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | sed | -| .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | sed | -| .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | sed | -| .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | awk | -| .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | sed | -| .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | sed | -| .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | sed | -| .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | sed | +| .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | sed | +| .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | sed | +| .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | sed | +| .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | awk | +| .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | sed | +| .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | sed | +| .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | sed | +| .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | sed | +| .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | git | +| .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | Potential argument injection in $@ command, which may be controlled by an external user. | .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | sed | diff --git a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionMedium.expected b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionMedium.expected index 73413f51a39..90e7101e5fd 100644 --- a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionMedium.expected @@ -1,19 +1,20 @@ edges -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | | -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | Config | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | provenance | Config | nodes -| .github/workflows/arg_injection.yml:11:15:11:43 | github.event.issue.title | semmle.label | github.event.issue.title | -| .github/workflows/arg_injection.yml:14:14:14:33 | sed "s/FOO/$TITLE/g" | semmle.label | sed "s/FOO/$TITLE/g" | -| .github/workflows/arg_injection.yml:15:14:15:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | semmle.label | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | -| .github/workflows/arg_injection.yml:16:14:16:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | semmle.label | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | -| .github/workflows/arg_injection.yml:17:14:17:33 | awk "BEGIN {$TITLE}" | semmle.label | awk "BEGIN {$TITLE}" | -| .github/workflows/arg_injection.yml:18:14:18:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | semmle.label | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | -| .github/workflows/arg_injection.yml:19:14:20:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | semmle.label | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | -| .github/workflows/arg_injection.yml:21:14:25:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | -| .github/workflows/arg_injection.yml:26:14:30:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:10:15:10:50 | github.event.pull_request.title | semmle.label | github.event.pull_request.title | +| .github/workflows/arg_injection.yml:17:14:17:33 | sed "s/FOO/$TITLE/g" | semmle.label | sed "s/FOO/$TITLE/g" | +| .github/workflows/arg_injection.yml:18:14:18:52 | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | semmle.label | echo "foo" \| sed "s/FOO/$TITLE/g" > bar | +| .github/workflows/arg_injection.yml:19:14:19:60 | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | semmle.label | echo $(echo "foo" \| sed "s/FOO/$TITLE/g" > bar) | +| .github/workflows/arg_injection.yml:20:14:20:33 | awk "BEGIN {$TITLE}" | semmle.label | awk "BEGIN {$TITLE}" | +| .github/workflows/arg_injection.yml:21:14:21:86 | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | semmle.label | sed -i "s/git_branch = .*/git_branch = \\"$GITHUB_HEAD_REF\\"/" config.json | +| .github/workflows/arg_injection.yml:22:14:23:84 | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | semmle.label | sed -i "s\|git_branch = .*\|git_branch = \\"$GITHUB_HEAD_REF\\"\|" config.json\n | +| .github/workflows/arg_injection.yml:24:14:28:111 | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##${TITLE}#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##TITLE#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:29:14:33:111 | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | semmle.label | sed -e 's##TITLE#' \\\n -e 's##${{ env.sot_repo }}#' \\\n -e 's##${TITLE}#' \\\n .github/workflows/common-copybara.bara.sky.template > .github/workflows/common-copybara.bara.sky\n | +| .github/workflows/arg_injection.yml:34:14:36:41 | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | semmle.label | BODY=$(git log --format=%s)\nsed "s/FOO/$BODY/g" > /tmp/foo\n | subpaths #select diff --git a/ql/test/query-tests/Security/CWE-094/.github/workflows/test.yml b/ql/test/query-tests/Security/CWE-094/.github/workflows/test.yml index 153ebc5b733..5aeb9aac7c5 100644 --- a/ql/test/query-tests/Security/CWE-094/.github/workflows/test.yml +++ b/ql/test/query-tests/Security/CWE-094/.github/workflows/test.yml @@ -1,26 +1,29 @@ -on: push +on: + pull_request_target: + +permissions: + actions: write jobs: job1: runs-on: ubuntu-latest - outputs: job_output: ${{ steps.step5.outputs.MSG5 }} steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} - id: step0 uses: mad9000/actions-find-and-replace-string@3 with: - source: ${{ github.event['head_commit']['message'] }} + source: ${{ github.event['pull_request']['body'] }} find: 'foo' replace: '' - id: step1 env: BODY: ${{ steps.step0.outputs.value}} - shell: powershell - run: | - Write-Output "::set-output name=MSG::$ENV{BODY}" + run: echo "::set-output name=MSG::${BODY}" - id: step2 env: MSG: ${{steps.step1.outputs.MSG}} diff --git a/ql/test/query-tests/Security/CWE-094/.github/workflows/test1.yml b/ql/test/query-tests/Security/CWE-094/.github/workflows/test1.yml index 3cab86f3171..d149df2bd7c 100644 --- a/ql/test/query-tests/Security/CWE-094/.github/workflows/test1.yml +++ b/ql/test/query-tests/Security/CWE-094/.github/workflows/test1.yml @@ -19,7 +19,9 @@ jobs: uses: actions/checkout@v4 - name: Extract Jira Key - run: echo ISSUE_KEY=$(echo "${{ github.event.pull_request.title }}") >> $GITHUB_ENV + env: + TITLE: ${{ github.event.pull_request.title }} + run: echo ISSUE_KEY=$(echo "$TITLE") >> $GITHUB_ENV - name: Sink run: echo ${{ env.ISSUE_KEY }} diff --git a/ql/test/query-tests/Security/CWE-094/.github/workflows/test14.yml b/ql/test/query-tests/Security/CWE-094/.github/workflows/test14.yml new file mode 100644 index 00000000000..6d925a82d37 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-094/.github/workflows/test14.yml @@ -0,0 +1,51 @@ +name: Pull Request Open + +on: + pull_request_target: + +jobs: + test1: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT" + - run: echo "${{ steps.changed-files.outputs.files }}" + test2: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/) + echo "files=${FILES}" >> "$GITHUB_OUTPUT" + - run: echo "${{ steps.changed-files.outputs.files }}" + test3: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV" + - run: echo "${{ env.CHANGED-FILES }}" + test4: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: changed-files + run: | + FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/) + echo "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV" + - run: echo "${{ env.CHANGED-FILES }}" + + + diff --git a/ql/test/query-tests/Security/CWE-094/.github/workflows/test15.yml b/ql/test/query-tests/Security/CWE-094/.github/workflows/test15.yml new file mode 100644 index 00000000000..a39967760e8 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-094/.github/workflows/test15.yml @@ -0,0 +1,38 @@ +name: Pull Request Open + +on: + pull_request_target: + +jobs: + test1: + runs-on: ubuntu-latest + steps: + - id: title + run: | + echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT" + - run: echo "${{ steps.title.outputs.title }}" + test2: + runs-on: ubuntu-latest + steps: + - id: title + run: | + PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH}) + echo "title=$PR_TITLE" >> "$GITHUB_OUTPUT" + - run: echo "${{ steps.title.outputs.title }}" + test3: + runs-on: ubuntu-latest + steps: + - id: title + run: | + echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV" + - run: echo "${{ env.TITLE }}" + test4: + runs-on: ubuntu-latest + steps: + - id: title + run: | + PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH}) + echo "TITLE=$PR_TITLE" >> "$GITHUB_ENV" + - run: echo "${{ env.TITLE }}" + + diff --git a/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected b/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected index 61c851a2cfa..4c9ea8fe8ca 100644 --- a/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected @@ -19,28 +19,28 @@ edges | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | provenance | | | .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | provenance | | | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] | provenance | | -| .github/workflows/artifactpoisoning1.yml:14:9:20:6 | Uses Step | .github/workflows/artifactpoisoning1.yml:22:14:22:55 | echo "::set-output name=id::$(> $GITHUB_OUTPUT\n | provenance | | +| .github/workflows/artifactpoisoning3.yml:20:9:41:6 | Uses Step | .github/workflows/artifactpoisoning3.yml:43:14:51:45 | unzip input.zip\necho current directory contents\nls -al\n\necho Reading PR number\ntmp=$(> $GITHUB_OUTPUT\n | provenance | Config | | .github/workflows/artifactpoisoning3.yml:41:9:53:6 | Run Step: prepare [pr] | .github/workflows/artifactpoisoning3.yml:53:20:53:50 | steps.prepare.outputs.pr | provenance | | | .github/workflows/artifactpoisoning3.yml:43:14:51:45 | unzip input.zip\necho current directory contents\nls -al\n\necho Reading PR number\ntmp=$(> $GITHUB_OUTPUT\n | .github/workflows/artifactpoisoning3.yml:41:9:53:6 | Run Step: prepare [pr] | provenance | | -| .github/workflows/artifactpoisoning4.yml:9:9:17:6 | Uses Step | .github/workflows/artifactpoisoning4.yml:19:14:19:58 | echo "::set-output name=id::$(> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | | +| .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | Config | | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | provenance | | -| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | provenance | | | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | provenance | | -| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | provenance | | -| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:49:20:49:56 | needs.job1.outputs['job_output'] | provenance | | -| .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | provenance | | -| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | provenance | | -| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | provenance | | -| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | provenance | | -| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | provenance | | -| .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | provenance | | -| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | provenance | | -| .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | provenance | | -| .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | provenance | | -| .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | provenance | | -| .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | provenance | | -| .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | provenance | | -| .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | provenance | | -| .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | provenance | | +| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | provenance | | +| .github/workflows/test14.yml:24:14:26:52 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | provenance | | +| .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | provenance | | +| .github/workflows/test14.yml:35:14:36:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | provenance | | +| .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | provenance | | +| .github/workflows/test14.yml:45:14:47:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | provenance | | +| .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | provenance | | +| .github/workflows/test15.yml:11:14:12:103 | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | provenance | | +| .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | provenance | | +| .github/workflows/test15.yml:18:14:20:53 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | provenance | | +| .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | .github/workflows/test15.yml:28:21:28:36 | env.TITLE | provenance | | +| .github/workflows/test15.yml:26:14:27:100 | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | provenance | | +| .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | .github/workflows/test15.yml:36:21:36:36 | env.TITLE | provenance | | +| .github/workflows/test15.yml:33:14:35:50 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | provenance | | +| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | provenance | | +| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | provenance | | +| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | provenance | | +| .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | provenance | | +| .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | provenance | | +| .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | provenance | | +| .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | provenance | | +| .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | provenance | | +| .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | provenance | | +| .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | provenance | | +| .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | provenance | | +| .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | provenance | | +| .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | provenance | | +| .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | provenance | | +| .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | semmle.label | needs.get-artifacts.outputs.pr_num | -| .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | semmle.label | needs.get-artifacts.outputs.ref | | .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | semmle.label | github.event.pull_request.title \|\| "foo" | | .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | semmle.label | github.event.changes.body.from | | .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | semmle.label | github.event.changes.title.from | | .github/workflows/test13.yml:12:21:12:61 | github.event.changes.head.ref.from | semmle.label | github.event.changes.head.ref.from | | .github/workflows/test13.yml:13:21:13:55 | toJson(github.event.changes) | semmle.label | toJson(github.event.changes) | -| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] | -| .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 | -| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] | -| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] | -| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] | -| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value | -| .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | semmle.label | Run Step: step2 [MSG2] | -| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG | -| .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | semmle.label | Run Step: step3 [MSG3] | -| .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | semmle.label | steps.step2.outputs.MSG2 | -| .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | semmle.label | Run Step: step4 [MSG4] | -| .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | semmle.label | steps.step3.outputs.MSG3 | -| .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | semmle.label | Run Step: step5 [MSG5] | -| .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | semmle.label | steps.step4.outputs.MSG4 | -| .github/workflows/test.yml:49:20:49:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] | +| .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | semmle.label | Run Step: changed-files [files] | +| .github/workflows/test14.yml:14:14:15:117 | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | semmle.label | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | semmle.label | steps.changed-files.outputs.files | +| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | semmle.label | Run Step: changed-files [files] | +| .github/workflows/test14.yml:24:14:26:52 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | semmle.label | steps.changed-files.outputs.files | +| .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | semmle.label | Job: test3 [CHANGED-FILES] | +| .github/workflows/test14.yml:35:14:36:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | semmle.label | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | semmle.label | env.CHANGED-FILES | +| .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | semmle.label | Job: test4 [CHANGED-FILES] | +| .github/workflows/test14.yml:45:14:47:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | semmle.label | env.CHANGED-FILES | +| .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | semmle.label | Run Step: title [title] | +| .github/workflows/test15.yml:11:14:12:103 | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | semmle.label | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | semmle.label | steps.title.outputs.title | +| .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | semmle.label | Run Step: title [title] | +| .github/workflows/test15.yml:18:14:20:53 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | semmle.label | steps.title.outputs.title | +| .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | semmle.label | Job: test3 [TITLE] | +| .github/workflows/test15.yml:26:14:27:100 | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | semmle.label | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:28:21:28:36 | env.TITLE | semmle.label | env.TITLE | +| .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | semmle.label | Job: test4 [TITLE] | +| .github/workflows/test15.yml:33:14:35:50 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | semmle.label | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:36:21:36:36 | env.TITLE | semmle.label | env.TITLE | +| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] | +| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 | +| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] | +| .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | semmle.label | github.event['pull_request']['body'] | +| .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] | +| .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value | +| .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | semmle.label | Run Step: step2 [MSG2] | +| .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG | +| .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | semmle.label | Run Step: step3 [MSG3] | +| .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | semmle.label | steps.step2.outputs.MSG2 | +| .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | semmle.label | Run Step: step4 [MSG4] | +| .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | semmle.label | steps.step3.outputs.MSG3 | +| .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | semmle.label | Run Step: step5 [MSG5] | +| .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | semmle.label | steps.step4.outputs.MSG4 | +| .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] | | .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/untrusted_checkout1.yml:11:9:14:6 | Run Step: artifact [pr_number] | semmle.label | Run Step: artifact [pr_number] | | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | ${{ steps.changed-files.outputs.files }} | +| .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | .github/workflows/test14.yml:24:14:26:52 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | ${{ steps.changed-files.outputs.files }} | +| .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | .github/workflows/test14.yml:35:14:36:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | ${{ env.CHANGED-FILES }} | +| .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | .github/workflows/test14.yml:45:14:47:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | ${{ env.CHANGED-FILES }} | +| .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | .github/workflows/test15.yml:11:14:12:103 | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | ${{ steps.title.outputs.title }} | +| .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | .github/workflows/test15.yml:18:14:20:53 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | ${{ steps.title.outputs.title }} | +| .github/workflows/test15.yml:28:21:28:36 | env.TITLE | .github/workflows/test15.yml:26:14:27:100 | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:28:21:28:36 | env.TITLE | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:28:21:28:36 | env.TITLE | ${{ env.TITLE }} | +| .github/workflows/test15.yml:36:21:36:36 | env.TITLE | .github/workflows/test15.yml:33:14:35:50 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:36:21:36:36 | env.TITLE | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test15.yml:36:21:36:36 | env.TITLE | ${{ env.TITLE }} | +| .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | ${{needs.job1.outputs['job_output']}} | | .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | ${{ steps.artifact.outputs.pr_number }} | | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | ${{ github.event.workflow_run.display_title }} | | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run.yml:10:19:10:70 | github.event.workflow_run.head_commit.message | ${{ github.event.workflow_run.head_commit.message }} | diff --git a/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected b/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected index db8e7b485d7..262912c58a5 100644 --- a/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected @@ -19,28 +19,28 @@ edges | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] | .github/workflows/argus_case_study.yml:27:33:27:77 | steps.remove_quotations.outputs.replaced | provenance | | | .github/workflows/argus_case_study.yml:17:25:17:53 | github.event.issue.title | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | provenance | | | .github/workflows/argus_case_study.yml:22:20:22:39 | env.ISSUE_TITLE | .github/workflows/argus_case_study.yml:15:9:24:6 | Uses Step: remove_quotations [replaced] | provenance | | -| .github/workflows/artifactpoisoning1.yml:14:9:20:6 | Uses Step | .github/workflows/artifactpoisoning1.yml:22:14:22:55 | echo "::set-output name=id::$(> $GITHUB_OUTPUT\n | provenance | | +| .github/workflows/artifactpoisoning3.yml:20:9:41:6 | Uses Step | .github/workflows/artifactpoisoning3.yml:43:14:51:45 | unzip input.zip\necho current directory contents\nls -al\n\necho Reading PR number\ntmp=$(> $GITHUB_OUTPUT\n | provenance | Config | | .github/workflows/artifactpoisoning3.yml:41:9:53:6 | Run Step: prepare [pr] | .github/workflows/artifactpoisoning3.yml:53:20:53:50 | steps.prepare.outputs.pr | provenance | | | .github/workflows/artifactpoisoning3.yml:43:14:51:45 | unzip input.zip\necho current directory contents\nls -al\n\necho Reading PR number\ntmp=$(> $GITHUB_OUTPUT\n | .github/workflows/artifactpoisoning3.yml:41:9:53:6 | Run Step: prepare [pr] | provenance | | -| .github/workflows/artifactpoisoning4.yml:9:9:17:6 | Uses Step | .github/workflows/artifactpoisoning4.yml:19:14:19:58 | echo "::set-output name=id::$(> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | | +| .github/workflows/test11.yml:22:9:30:6 | Uses Step | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | provenance | Config | | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | .github/workflows/test11.yml:19:16:19:50 | steps.set-ref.outputs.pr_num | provenance | | -| .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | .github/workflows/test11.yml:20:13:20:44 | steps.set-ref.outputs.ref | provenance | | | .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [pr_num] | provenance | | -| .github/workflows/test11.yml:32:14:44:44 | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | .github/workflows/test11.yml:30:9:46:2 | Run Step: set-ref [ref] | provenance | | -| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | .github/workflows/test.yml:49:20:49:56 | needs.job1.outputs['job_output'] | provenance | | -| .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | provenance | | -| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | provenance | | -| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | provenance | | -| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | provenance | | -| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | provenance | | -| .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | provenance | | -| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | provenance | | -| .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | provenance | | -| .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | provenance | | -| .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | provenance | | -| .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | provenance | | -| .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | provenance | | -| .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | provenance | | -| .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | provenance | | +| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | provenance | | +| .github/workflows/test14.yml:24:14:26:52 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | provenance | | +| .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | provenance | | +| .github/workflows/test14.yml:35:14:36:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | provenance | | +| .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | provenance | | +| .github/workflows/test14.yml:45:14:47:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | provenance | | +| .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | provenance | | +| .github/workflows/test15.yml:11:14:12:103 | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | provenance | | +| .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | provenance | | +| .github/workflows/test15.yml:18:14:20:53 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | provenance | | +| .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | .github/workflows/test15.yml:28:21:28:36 | env.TITLE | provenance | | +| .github/workflows/test15.yml:26:14:27:100 | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | provenance | | +| .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | .github/workflows/test15.yml:36:21:36:36 | env.TITLE | provenance | | +| .github/workflows/test15.yml:33:14:35:50 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | provenance | | +| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | provenance | | +| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | provenance | | +| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | provenance | | +| .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | provenance | | +| .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | provenance | | +| .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | provenance | | +| .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | provenance | | +| .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | provenance | | +| .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | provenance | | +| .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | provenance | | +| .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | provenance | | +| .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | provenance | | +| .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | provenance | | +| .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | provenance | | +| .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | semmle.label | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json)\nif [ -z "$pr_num" ] \|\| [ "$pr_num" == "null" ]; then\n pr_num=""\nfi\n\nref=$pr_num\nif [ -z "$ref" ] \|\| [ "$ref" == "null" ]; then\n ref=${{ github.ref }}\nfi\n\necho "pr_num=$pr_num" >> $GITHUB_OUTPUT\necho "ref=$ref" >> $GITHUB_OUTPUT\n | | .github/workflows/test11.yml:54:20:54:60 | needs.get-artifacts.outputs.pr_num | semmle.label | needs.get-artifacts.outputs.pr_num | -| .github/workflows/test11.yml:55:20:55:57 | needs.get-artifacts.outputs.ref | semmle.label | needs.get-artifacts.outputs.ref | | .github/workflows/test12.yml:10:21:10:67 | github.event.pull_request.title \|\| "foo" | semmle.label | github.event.pull_request.title \|\| "foo" | | .github/workflows/test13.yml:10:21:10:57 | github.event.changes.body.from | semmle.label | github.event.changes.body.from | | .github/workflows/test13.yml:11:21:11:58 | github.event.changes.title.from | semmle.label | github.event.changes.title.from | | .github/workflows/test13.yml:12:21:12:61 | github.event.changes.head.ref.from | semmle.label | github.event.changes.head.ref.from | | .github/workflows/test13.yml:13:21:13:55 | toJson(github.event.changes) | semmle.label | toJson(github.event.changes) | -| .github/workflows/test.yml:8:7:10:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] | -| .github/workflows/test.yml:8:20:8:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 | -| .github/workflows/test.yml:12:9:18:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] | -| .github/workflows/test.yml:15:20:15:64 | github.event['head_commit']['message'] | semmle.label | github.event['head_commit']['message'] | -| .github/workflows/test.yml:18:9:24:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] | -| .github/workflows/test.yml:20:18:20:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value | -| .github/workflows/test.yml:24:9:28:6 | Run Step: step2 [MSG2] | semmle.label | Run Step: step2 [MSG2] | -| .github/workflows/test.yml:26:19:26:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG | -| .github/workflows/test.yml:28:9:32:6 | Run Step: step3 [MSG3] | semmle.label | Run Step: step3 [MSG3] | -| .github/workflows/test.yml:30:20:30:48 | steps.step2.outputs.MSG2 | semmle.label | steps.step2.outputs.MSG2 | -| .github/workflows/test.yml:32:9:36:6 | Run Step: step4 [MSG4] | semmle.label | Run Step: step4 [MSG4] | -| .github/workflows/test.yml:34:20:34:48 | steps.step3.outputs.MSG3 | semmle.label | steps.step3.outputs.MSG3 | -| .github/workflows/test.yml:36:9:41:2 | Run Step: step5 [MSG5] | semmle.label | Run Step: step5 [MSG5] | -| .github/workflows/test.yml:38:20:38:48 | steps.step4.outputs.MSG4 | semmle.label | steps.step4.outputs.MSG4 | -| .github/workflows/test.yml:49:20:49:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] | +| .github/workflows/test14.yml:13:9:16:6 | Run Step: changed-files [files] | semmle.label | Run Step: changed-files [files] | +| .github/workflows/test14.yml:14:14:15:117 | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | semmle.label | echo "files=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test14.yml:16:21:16:60 | steps.changed-files.outputs.files | semmle.label | steps.changed-files.outputs.files | +| .github/workflows/test14.yml:23:9:27:6 | Run Step: changed-files [files] | semmle.label | Run Step: changed-files [files] | +| .github/workflows/test14.yml:24:14:26:52 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "files=${FILES}" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test14.yml:27:21:27:60 | steps.changed-files.outputs.files | semmle.label | steps.changed-files.outputs.files | +| .github/workflows/test14.yml:29:5:38:2 | Job: test3 [CHANGED-FILES] | semmle.label | Job: test3 [CHANGED-FILES] | +| .github/workflows/test14.yml:35:14:36:122 | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | semmle.label | echo "CHANGED-FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:37:21:37:44 | env.CHANGED-FILES | semmle.label | env.CHANGED-FILES | +| .github/workflows/test14.yml:39:5:48:45 | Job: test4 [CHANGED-FILES] | semmle.label | Job: test4 [CHANGED-FILES] | +| .github/workflows/test14.yml:45:14:47:57 | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | semmle.label | FILES=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} -- docs/)\necho "CHANGED-FILES=${FILES}" >> "$GITHUB_ENV"\n | +| .github/workflows/test14.yml:48:21:48:44 | env.CHANGED-FILES | semmle.label | env.CHANGED-FILES | +| .github/workflows/test15.yml:10:9:13:6 | Run Step: title [title] | semmle.label | Run Step: title [title] | +| .github/workflows/test15.yml:11:14:12:103 | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | semmle.label | echo "title=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test15.yml:13:21:13:52 | steps.title.outputs.title | semmle.label | steps.title.outputs.title | +| .github/workflows/test15.yml:17:9:21:6 | Run Step: title [title] | semmle.label | Run Step: title [title] | +| .github/workflows/test15.yml:18:14:20:53 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | semmle.label | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "title=$PR_TITLE" >> "$GITHUB_OUTPUT"\n | +| .github/workflows/test15.yml:21:21:21:52 | steps.title.outputs.title | semmle.label | steps.title.outputs.title | +| .github/workflows/test15.yml:23:5:29:2 | Job: test3 [TITLE] | semmle.label | Job: test3 [TITLE] | +| .github/workflows/test15.yml:26:14:27:100 | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | semmle.label | echo "TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:28:21:28:36 | env.TITLE | semmle.label | env.TITLE | +| .github/workflows/test15.yml:30:5:36:37 | Job: test4 [TITLE] | semmle.label | Job: test4 [TITLE] | +| .github/workflows/test15.yml:33:14:35:50 | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | semmle.label | PR_TITLE=$(jq --raw-output .pull_request.title ${GITHUB_EVENT_PATH})\necho "TITLE=$PR_TITLE" >> "$GITHUB_ENV"\n | +| .github/workflows/test15.yml:36:21:36:36 | env.TITLE | semmle.label | env.TITLE | +| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] | +| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 | +| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] | +| .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | semmle.label | github.event['pull_request']['body'] | +| .github/workflows/test.yml:23:9:27:6 | Run Step: step1 [MSG] | semmle.label | Run Step: step1 [MSG] | +| .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | semmle.label | steps.step0.outputs.value | +| .github/workflows/test.yml:27:9:31:6 | Run Step: step2 [MSG2] | semmle.label | Run Step: step2 [MSG2] | +| .github/workflows/test.yml:29:19:29:46 | steps.step1.outputs.MSG | semmle.label | steps.step1.outputs.MSG | +| .github/workflows/test.yml:31:9:35:6 | Run Step: step3 [MSG3] | semmle.label | Run Step: step3 [MSG3] | +| .github/workflows/test.yml:33:20:33:48 | steps.step2.outputs.MSG2 | semmle.label | steps.step2.outputs.MSG2 | +| .github/workflows/test.yml:35:9:39:6 | Run Step: step4 [MSG4] | semmle.label | Run Step: step4 [MSG4] | +| .github/workflows/test.yml:37:20:37:48 | steps.step3.outputs.MSG3 | semmle.label | steps.step3.outputs.MSG3 | +| .github/workflows/test.yml:39:9:44:2 | Run Step: step5 [MSG5] | semmle.label | Run Step: step5 [MSG5] | +| .github/workflows/test.yml:41:20:41:48 | steps.step4.outputs.MSG4 | semmle.label | steps.step4.outputs.MSG4 | +| .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | semmle.label | needs.job1.outputs['job_output'] | | .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/untrusted_checkout1.yml:11:9:14:6 | Run Step: artifact [pr_number] | semmle.label | Run Step: artifact [pr_number] | | .github/workflows/untrusted_checkout1.yml:12:14:13:63 | echo "::set-output name=pr_number::$(> $GITHUB_ENV\n | provenance | | -| .github/workflows/artifactpoisoning52.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning52.yml:19:14:22:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\ncat foo >> "$GITHUB_ENV"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | | -| .github/workflows/artifactpoisoning53.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning53.yml:18:14:23:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | | -| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | provenance | | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | provenance | | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | provenance | Config | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | provenance | Config | +| .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | provenance | Config | +| .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | provenance | Config | +| .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | provenance | Config | +| .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | provenance | Config | +| .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | provenance | Config | +| .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | provenance | Config | +| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | provenance | Config | +| .github/workflows/artifactpoisoning51.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning51.yml:19:14:20:57 | echo "pr_number=$(cat foo/bar)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/artifactpoisoning52.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning52.yml:19:14:22:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\ncat foo >> "$GITHUB_ENV"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | Config | +| .github/workflows/artifactpoisoning53.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning53.yml:18:14:23:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | Config | +| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | Config | nodes | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | semmle.label | Uses Step | @@ -51,7 +48,6 @@ nodes | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | semmle.label | sed -f config foo.md > bar.md\n | | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | semmle.label | python test.py | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | semmle.label | make snapshot | subpaths diff --git a/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected b/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected index e1532c06cdc..8d946507799 100644 --- a/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected +++ b/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected @@ -1,24 +1,21 @@ edges -| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | provenance | | -| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | provenance | | -| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | provenance | | -| .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | provenance | | -| .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | provenance | | -| .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | provenance | | -| .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | provenance | | -| .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | provenance | | -| .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | provenance | | -| .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | provenance | | -| .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | provenance | | -| .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | provenance | | -| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | provenance | | -| .github/workflows/artifactpoisoning51.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning51.yml:19:14:20:57 | echo "pr_number=$(cat foo/bar)" >> $GITHUB_ENV\n | provenance | | -| .github/workflows/artifactpoisoning52.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning52.yml:19:14:22:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\ncat foo >> "$GITHUB_ENV"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | | -| .github/workflows/artifactpoisoning53.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning53.yml:18:14:23:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | | -| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | | -| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | provenance | | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | provenance | | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | provenance | Config | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | provenance | Config | +| .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | provenance | Config | +| .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | provenance | Config | +| .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | provenance | Config | +| .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | provenance | Config | +| .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | provenance | Config | +| .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | provenance | Config | +| .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | provenance | Config | +| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | provenance | Config | +| .github/workflows/artifactpoisoning51.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning51.yml:19:14:20:57 | echo "pr_number=$(cat foo/bar)" >> $GITHUB_ENV\n | provenance | Config | +| .github/workflows/artifactpoisoning52.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning52.yml:19:14:22:40 | echo "PACKAGES_FILE_LIST<> "${GITHUB_ENV}"\ncat foo >> "$GITHUB_ENV"\necho "EOF" >> "${GITHUB_ENV}"\n | provenance | Config | +| .github/workflows/artifactpoisoning53.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning53.yml:18:14:23:29 | {\n echo 'JSON_RESPONSE<> "$GITHUB_ENV"\n | provenance | Config | +| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | Config | +| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | Config | nodes | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | semmle.label | Uses Step | @@ -51,7 +48,6 @@ nodes | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | semmle.label | sed -f config foo.md > bar.md\n | | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | semmle.label | python test.py | -| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | semmle.label | Uses Step | | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | semmle.label | make snapshot | subpaths