From e2e1dddb36f9818aa4db1edacdc26bda25432bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Tue, 15 Oct 2024 09:48:01 +0200 Subject: [PATCH] Move arg injection sinks to ShellScript class --- ql/lib/codeql/actions/Ast.qll | 8 ++ ql/lib/codeql/actions/Bash.qll | 52 ++++++++++-- ql/lib/codeql/actions/PowerShell.qll | 12 +++ ql/lib/codeql/actions/ast/internal/Ast.qll | 8 ++ .../security/ArgumentInjectionQuery.qll | 58 +++---------- ql/test/library-tests/commands.expected | 84 +++++++++---------- .../.github/workflows/arg_injection.yml | 12 +++ .../ArgumentInjectionCritical.expected | 1 - 8 files changed, 139 insertions(+), 96 deletions(-) diff --git a/ql/lib/codeql/actions/Ast.qll b/ql/lib/codeql/actions/Ast.qll index 620f74e25bb..e41354ce31b 100644 --- a/ql/lib/codeql/actions/Ast.qll +++ b/ql/lib/codeql/actions/Ast.qll @@ -354,6 +354,14 @@ class ShellScript extends ScalarValueImpl instanceof ShellScriptImpl { predicate getACmdReachingGitHubPathWrite(string cmd) { super.getACmdReachingGitHubPathWrite(cmd) } + predicate getAnEnvReachingArgumentInjectionSink(string var, string command, string argument) { + super.getAnEnvReachingArgumentInjectionSink(var, command, argument) + } + + predicate getACmdReachingArgumentInjectionSink(string cmd, string command, string argument) { + super.getACmdReachingArgumentInjectionSink(cmd, command, argument) + } + predicate fileToGitHubEnv(string path) { super.fileToGitHubEnv(path) } predicate fileToGitHubOutput(string path) { super.fileToGitHubOutput(path) } diff --git a/ql/lib/codeql/actions/Bash.qll b/ql/lib/codeql/actions/Bash.qll index 541ab437db2..12866a141a6 100644 --- a/ql/lib/codeql/actions/Bash.qll +++ b/ql/lib/codeql/actions/Bash.qll @@ -133,7 +133,8 @@ class BashShellScript extends ShellScript { this.doStmtRestoreQuotedStrings(i, round, _, new) | new order by round - ) + ) and + not result.indexOf("qstr:") > -1 } private predicate doStmtRestoreCmdSubstitutions(int line, int round, string old, string new) { @@ -155,7 +156,8 @@ class BashShellScript extends ShellScript { this.doStmtRestoreCmdSubstitutions(i, round, _, new) | new order by round - ) + ) and + not result.indexOf("cmdsubs:") > -1 } override string getAStmt() { result = this.getStmt(_) } @@ -186,7 +188,8 @@ class BashShellScript extends ShellScript { this.doCmdRestoreQuotedStrings(i, round, _, new) | new order by round - ) + ) and + not result.indexOf("qstr:") > -1 } private predicate doCmdRestoreCmdSubstitutions(int line, int round, string old, string new) { @@ -208,13 +211,16 @@ class BashShellScript extends ShellScript { this.doCmdRestoreCmdSubstitutions(i, round, _, new) | new order by round - ) + ) and + not result.indexOf("cmdsubs:") > -1 } string getACmd() { result = this.getCmd(_) } override string getCommand(int i) { - result = this.getCmd(i) and + // remove redirection + result = + this.getCmd(i).regexpReplaceAll("(>|>>|2>|2>>|<|<<<)\\s*[\\{\\}\\$\"'_\\-0-9a-zA-Z]+$", "") and // exclude variable declarations not result.regexpMatch("^[a-zA-Z0-9\\-_]+=") and // exclude the following keywords @@ -286,6 +292,18 @@ class BashShellScript extends ShellScript { Bash::cmdReachingGitHubFileWrite(this, cmd, "GITHUB_PATH", _) } + override predicate getAnEnvReachingArgumentInjectionSink( + string var, string command, string argument + ) { + Bash::envReachingArgumentInjectionSink(this, var, command, argument) + } + + override predicate getACmdReachingArgumentInjectionSink( + string cmd, string command, string argument + ) { + Bash::cmdReachingArgumentInjectionSink(this, cmd, command, argument) + } + override predicate fileToGitHubEnv(string path) { Bash::fileToFileWrite(this, "GITHUB_ENV", path) } @@ -633,6 +651,30 @@ module Bash { ) } + predicate envReachingArgumentInjectionSink( + BashShellScript script, string source, string command, string argument + ) { + exists(string cmd, string regex, int command_group, int argument_group | + cmd = script.getACommand() and + argumentInjectionSinksDataModel(regex, command_group, argument_group) and + argument = cmd.regexpCapture(regex, argument_group) and + command = cmd.regexpCapture(regex, command_group) and + envReachingRunExpr(script, source, argument) + ) + } + + predicate cmdReachingArgumentInjectionSink( + BashShellScript script, string source, string command, string argument + ) { + exists(string cmd, string regex, int command_group, int argument_group | + cmd = script.getACommand() and + argumentInjectionSinksDataModel(regex, command_group, argument_group) and + argument = cmd.regexpCapture(regex, argument_group) and + command = cmd.regexpCapture(regex, command_group) and + cmdReachingRunExpr(script, source, argument) + ) + } + /** * Holds if a command output is used, directly or indirectly, in a Run's step expression. * Where the expression is a string captured from the Run's script. diff --git a/ql/lib/codeql/actions/PowerShell.qll b/ql/lib/codeql/actions/PowerShell.qll index 1727930c2a3..3ae706970fa 100644 --- a/ql/lib/codeql/actions/PowerShell.qll +++ b/ql/lib/codeql/actions/PowerShell.qll @@ -42,6 +42,18 @@ class PowerShellScript extends ShellScript { override predicate getACmdReachingGitHubPathWrite(string cmd) { none() } + override predicate getAnEnvReachingArgumentInjectionSink( + string var, string command, string argument + ) { + none() + } + + override predicate getACmdReachingArgumentInjectionSink( + string cmd, string command, string argument + ) { + none() + } + override predicate fileToGitHubEnv(string path) { none() } override predicate fileToGitHubOutput(string path) { none() } diff --git a/ql/lib/codeql/actions/ast/internal/Ast.qll b/ql/lib/codeql/actions/ast/internal/Ast.qll index 43772a978c5..7c433a39e62 100644 --- a/ql/lib/codeql/actions/ast/internal/Ast.qll +++ b/ql/lib/codeql/actions/ast/internal/Ast.qll @@ -227,6 +227,14 @@ class ShellScriptImpl extends ScalarValueImpl { abstract predicate getACmdReachingGitHubPathWrite(string cmd); + abstract predicate getAnEnvReachingArgumentInjectionSink( + string var, string command, string argument + ); + + abstract predicate getACmdReachingArgumentInjectionSink( + string cmd, string command, string argument + ); + abstract predicate fileToGitHubEnv(string path); abstract predicate fileToGitHubOutput(string path); diff --git a/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll b/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll index a0309437292..f7e4a983445 100644 --- a/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/ArgumentInjectionQuery.qll @@ -9,23 +9,6 @@ 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.getScript().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.getScript(), 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. @@ -36,23 +19,16 @@ predicate envToArgInjSink(string var, Run run, string command) { */ class ArgumentInjectionFromEnvVarSink extends ArgumentInjectionSink { string command; + string argument; ArgumentInjectionFromEnvVarSink() { exists(Run run, string var | - envToArgInjSink(var, run, command) and run.getScript() = this.asExpr() and - exists(run.getInScopeEnvVarExpr(var)) - ) - or - exists( - Run run, string cmd, string argument, string regexp, int argument_group, int command_group - | - run.getScript().getACommand() = cmd and - run.getScript() = this.asExpr() and - argumentInjectionSinksDataModel(regexp, command_group, argument_group) and - argument = cmd.regexpCapture(regexp, argument_group) and - command = cmd.regexpCapture(regexp, command_group) and - argument.regexpMatch(".*\\$(\\{)?(GITHUB_HEAD_REF).*") + ( + exists(run.getInScopeEnvVarExpr(var)) or + var = "GITHUB_HEAD_REF" + ) and + run.getScript().getAnEnvReachingArgumentInjectionSink(var, command, argument) ) } @@ -68,18 +44,13 @@ class ArgumentInjectionFromEnvVarSink extends ArgumentInjectionSink { */ class ArgumentInjectionFromCommandSink extends ArgumentInjectionSink { string command; + string argument; ArgumentInjectionFromCommandSink() { - exists( - CommandSource source, Run run, string cmd, string argument, string regexp, int argument_group, - int command_group - | + exists(CommandSource source, Run run | run = source.getEnclosingRun() and this.asExpr() = run.getScript() and - cmd = run.getScript().getACommand() and - argumentInjectionSinksDataModel(regexp, command_group, argument_group) and - argument = cmd.regexpCapture(regexp, argument_group) and - command = cmd.regexpCapture(regexp, command_group) + run.getScript().getACmdReachingArgumentInjectionSink(source.getCommand(), command, argument) ) } @@ -103,14 +74,9 @@ private module ArgumentInjectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource or - exists( - Run run, string argument, string cmd, string regexp, int command_group, int argument_group - | + exists(Run run | run.getScript() = source.asExpr() and - run.getScript().getACommand() = cmd and - argumentInjectionSinksDataModel(regexp, command_group, argument_group) and - argument = cmd.regexpCapture(regexp, argument_group) and - argument.regexpMatch(".*\\$(\\{)?(GITHUB_HEAD_REF).*") + run.getScript().getAnEnvReachingArgumentInjectionSink("GITHUB_HEAD_REF", _, _) ) } @@ -120,7 +86,7 @@ private module ArgumentInjectionConfig implements DataFlow::ConfigSig { exists(Run run, string var | run.getInScopeEnvVarExpr(var) = pred.asExpr() and succ.asExpr() = run.getScript() and - envToArgInjSink(var, run, _) + run.getScript().getAnEnvReachingArgumentInjectionSink(var, _, _) ) } } diff --git a/ql/test/library-tests/commands.expected b/ql/test/library-tests/commands.expected index e78f152e60b..d5536ca1c74 100644 --- a/ql/test/library-tests/commands.expected +++ b/ql/test/library-tests/commands.expected @@ -22,15 +22,11 @@ | .github/workflows/expression_nodes.yml:10:9:13:6 | Run Step | LINE 2 echo '${{github.event.issue.body}}' | | .github/workflows/expression_nodes.yml:13:9:16:6 | Run Step | LINE 1 echo '${{ github.event.comment.body }}' echo '${{github.event.issue.body}}' | | .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 1 echo '${{ github.event.comment.body }}' | -| .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 1 echo qstr:0:0:12:34:githubeventcommentbody | -| .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 1 echo qstr:2:0:12:34:githubeventcommentbody | | .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 2 echo '${{github.event.issue.body}}' | | .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 3 echo '${{ github.event.comment.body }}' | -| .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 3 echo qstr:0:0:12:34:githubeventcommentbody | -| .github/workflows/expression_nodes.yml:16:9:20:6 | Run Step | LINE 3 echo qstr:2:0:12:34:githubeventcommentbody | | .github/workflows/expression_nodes.yml:20:9:21:47 | Run Step | LINE 1 echo '${{ github.event.comment.body }}' echo '${{github.event.issue.body}}' | | .github/workflows/multiline2.yml:11:9:15:6 | Run Step | echo "CHANGELOGEOF" | -| .github/workflows/multiline2.yml:11:9:15:6 | Run Step | echo "changelog< issue.txt << EOL | +| .github/workflows/multiline2.yml:40:9:46:6 | Run Step | cat > issue.txt < | | .github/workflows/multiline2.yml:46:9:52:6 | Run Step | ${ISSUE_BODY} | | .github/workflows/multiline2.yml:46:9:52:6 | Run Step | EOL | | .github/workflows/multiline2.yml:46:9:52:6 | Run Step | FOO | -| .github/workflows/multiline2.yml:46:9:52:6 | Run Step | cat << EOL | +| .github/workflows/multiline2.yml:46:9:52:6 | Run Step | cat < | | .github/workflows/multiline2.yml:46:9:52:6 | Run Step | tee -a $GITHUB_ENV | | .github/workflows/multiline2.yml:52:9:58:6 | Run Step | EOF | | .github/workflows/multiline2.yml:52:9:58:6 | Run Step | Hello | | .github/workflows/multiline2.yml:52:9:58:6 | Run Step | World | -| .github/workflows/multiline2.yml:52:9:58:6 | Run Step | cat < file.txt | | .github/workflows/multiline2.yml:58:9:63:6 | Run Step | EOF | -| .github/workflows/multiline2.yml:58:9:63:6 | Run Step | cat <<-EOF | +| .github/workflows/multiline2.yml:58:9:63:6 | Run Step | cat < | | .github/workflows/multiline2.yml:58:9:63:6 | Run Step | echo "FOO=$TITLE" | | .github/workflows/multiline2.yml:58:9:63:6 | Run Step | tee -a "$GITHUB_ENV" | | .github/workflows/multiline2.yml:63:9:66:6 | Run Step | cat issue.txt | @@ -84,77 +80,77 @@ | .github/workflows/multiline2.yml:63:9:66:6 | Run Step | tr -d ' ' | | .github/workflows/multiline2.yml:66:9:71:6 | Run Step | echo "$TITLE" | | .github/workflows/multiline2.yml:66:9:71:6 | Run Step | echo "EOF" | -| .github/workflows/multiline2.yml:66:9:71:6 | Run Step | echo "PR_TITLE<> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:11:9:15:6 | Run Step | echo "changelog<> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:11:9:15:6 | Run Step | echo -e "$FILTERED_CHANGELOG" >> $GITHUB_OUTPUT | +| .github/workflows/multiline.yml:11:9:15:6 | Run Step | echo "CHANGELOGEOF" | +| .github/workflows/multiline.yml:11:9:15:6 | Run Step | echo "changelog<> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:15:9:20:6 | Run Step | echo "$EOF" >> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:15:9:20:6 | Run Step | echo "status<<$EOF" >> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:20:9:24:6 | Run Step | echo "$EOF" >> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:20:9:24:6 | Run Step | echo "response<<$EOF" >> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:20:9:24:6 | Run Step | echo $output >> $GITHUB_OUTPUT | -| .github/workflows/multiline.yml:24:9:30:6 | Run Step | echo 'JSON_RESPONSE<> "$GITHUB_ENV" | +| .github/workflows/multiline.yml:24:9:30:6 | Run Step | } | | .github/workflows/multiline.yml:30:9:34:6 | Run Step | ${{ toJson(github.event) }} | | .github/workflows/multiline.yml:30:9:34:6 | Run Step | EOF | | .github/workflows/multiline.yml:30:9:34:6 | Run Step | cat <<-"EOF" > event.json | | .github/workflows/multiline.yml:34:9:40:6 | Run Step | ${ISSUE_BODY} | | .github/workflows/multiline.yml:34:9:40:6 | Run Step | EOL | | .github/workflows/multiline.yml:34:9:40:6 | Run Step | FOO | -| .github/workflows/multiline.yml:34:9:40:6 | Run Step | cat >> $GITHUB_ENV << EOL | +| .github/workflows/multiline.yml:34:9:40:6 | Run Step | cat >> $GITHUB_ENV < | | .github/workflows/multiline.yml:40:9:46:6 | Run Step | ${ISSUE_BODY} | | .github/workflows/multiline.yml:40:9:46:6 | Run Step | EOL | | .github/workflows/multiline.yml:40:9:46:6 | Run Step | FOO | -| .github/workflows/multiline.yml:40:9:46:6 | Run Step | cat > issue.txt << EOL | +| .github/workflows/multiline.yml:40:9:46:6 | Run Step | cat > issue.txt < | | .github/workflows/multiline.yml:46:9:52:6 | Run Step | ${ISSUE_BODY} | | .github/workflows/multiline.yml:46:9:52:6 | Run Step | EOL | | .github/workflows/multiline.yml:46:9:52:6 | Run Step | FOO | -| .github/workflows/multiline.yml:46:9:52:6 | Run Step | cat << EOL >> $GITHUB_ENV | +| .github/workflows/multiline.yml:46:9:52:6 | Run Step | cat << EOL | | .github/workflows/multiline.yml:52:9:58:6 | Run Step | EOF | | .github/workflows/multiline.yml:52:9:58:6 | Run Step | Hello | | .github/workflows/multiline.yml:52:9:58:6 | Run Step | World | -| .github/workflows/multiline.yml:52:9:58:6 | Run Step | cat < file.txt | | .github/workflows/multiline.yml:58:9:63:6 | Run Step | EOF | -| .github/workflows/multiline.yml:58:9:63:6 | Run Step | cat <<-EOF >> "$GITHUB_ENV" | +| .github/workflows/multiline.yml:58:9:63:6 | Run Step | cat <<-EOF | | .github/workflows/multiline.yml:58:9:63:6 | Run Step | echo "FOO=$TITLE" | | .github/workflows/multiline.yml:63:9:66:6 | Run Step | cat issue.txt | -| .github/workflows/multiline.yml:63:9:66:6 | Run Step | echo REPO_NAME=$(cat issue.txt \| sed 's/\\\\r/\\\\n/g' \| grep -ioE '\\\\s*[a-z0-9_-]+/[a-z0-9_-]+\\\\s*$' \| tr -d ' ') >> $GITHUB_ENV | +| .github/workflows/multiline.yml:63:9:66:6 | Run Step | echo REPO_NAME=$(cat issue.txt \| sed 's/\\\\r/\\\\n/g' \| grep -ioE '\\\\s*[a-z0-9_-]+/[a-z0-9_-]+\\\\s*$' \| tr -d ' ') | | .github/workflows/multiline.yml:63:9:66:6 | Run Step | grep -ioE '\\\\s*[a-z0-9_-]+/[a-z0-9_-]+\\\\s*$' | | .github/workflows/multiline.yml:63:9:66:6 | Run Step | sed 's/\\\\r/\\\\n/g' | | .github/workflows/multiline.yml:63:9:66:6 | Run Step | tr -d ' ' | -| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "$TITLE" >> $GITHUB_ENV | -| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "EOF" >> $GITHUB_ENV | -| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "PR_TITLE<> $GITHUB_ENV | +| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "$TITLE" | +| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "EOF" | +| .github/workflows/multiline.yml:66:9:71:6 | Run Step | echo "PR_TITLE<> "$GITHUB_ENV" | +| .github/workflows/multiline.yml:71:9:78:6 | Run Step | } | | .github/workflows/multiline.yml:78:9:85:6 | Run Step | echo '$ISSUE' | | .github/workflows/multiline.yml:78:9:85:6 | Run Step | echo 'EOF' | -| .github/workflows/multiline.yml:78:9:85:6 | Run Step | echo 'JSON_RESPONSE<> "$GITHUB_ENV" | -| .github/workflows/multiline.yml:85:9:89:29 | Run Step | echo 'JSON_RESPONSE<> "$GITHUB_ENV" | +| .github/workflows/multiline.yml:78:9:85:6 | Run Step | echo 'JSON_RESPONSE< | +| .github/workflows/multiline.yml:78:9:85:6 | Run Step | } | +| .github/workflows/multiline.yml:85:9:89:29 | Run Step | echo 'JSON_RESPONSE< | +| .github/workflows/multiline.yml:85:9:89:29 | Run Step | } | | .github/workflows/poisonable_steps.yml:7:9:8:6 | Run Step | venv/bin/activate | | .github/workflows/poisonable_steps.yml:13:9:14:6 | Run Step | . venv/bin/activate | | .github/workflows/poisonable_steps.yml:14:9:15:6 | Run Step | . venv/bin/activate | @@ -171,7 +167,7 @@ | .github/workflows/poisonable_steps.yml:20:9:21:6 | Run Step | echo foo | | .github/workflows/poisonable_steps.yml:20:9:21:6 | Run Step | sh venv/bin/activate.sh | | .github/workflows/poisonable_steps.yml:21:9:22:6 | Run Step | echo foo | -| .github/workflows/poisonable_steps.yml:21:9:22:6 | Run Step | sh venv/bin/activate.sh > output | +| .github/workflows/poisonable_steps.yml:21:9:22:6 | Run Step | sh venv/bin/activate.sh | | .github/workflows/poisonable_steps.yml:22:9:23:6 | Run Step | python venv/bin/activate.py | | .github/workflows/poisonable_steps.yml:23:9:24:6 | Run Step | echo foo | | .github/workflows/poisonable_steps.yml:23:9:24:6 | Run Step | python venv/bin/activate.py | 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 59ea1564bdd..42ba8bf2749 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 @@ -34,3 +34,15 @@ jobs: - run: | BODY=$(git log --format=%s) sed "s/FOO/$BODY/g" > /tmp/foo + + - name: Checkout ref + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + - name: Detect new changesets + id: added-files + run: | + delimiter="$(openssl rand -hex 8)" + echo "changesets<<${delimiter}" >> "${GITHUB_OUTPUT}" + echo "$(git diff --name-only --diff-filter=A ${{ steps.comment-branch.outputs.base_sha }} ${{ steps.parse-sha.outputs.sha }} .changeset/*.md)" >> "${GITHUB_OUTPUT}" + echo "${delimiter}" >> "${GITHUB_OUTPUT}" diff --git a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected index 326cb935f7c..1e4051fef43 100644 --- a/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-088/ArgumentInjectionCritical.expected @@ -26,5 +26,4 @@ subpaths | .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 |