From 8cf1a6afa7755cedad993fec7d9957023abda72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 2 Aug 2024 15:48:57 +0200 Subject: [PATCH] feat(bash): Add support for `cat hazelcast/.github/java-config.env >> $GITHUB_ENV` --- ql/lib/codeql/actions/Helper.qll | 26 ++++++++ .../security/EnvPathInjectionQuery.qll | 43 ++++++++----- .../actions/security/EnvVarInjectionQuery.qll | 48 ++++++++++----- .../security/OutputClobberingQuery.qll | 60 ++++++++++++------- .../CWE-077/.github/workflows/test10.yml | 28 +++++++++ .../CWE-077/EnvVarInjectionCritical.expected | 4 ++ .../CWE-077/EnvVarInjectionMedium.expected | 3 + 7 files changed, 158 insertions(+), 54 deletions(-) create mode 100644 ql/test/query-tests/Security/CWE-077/.github/workflows/test10.yml diff --git a/ql/lib/codeql/actions/Helper.qll b/ql/lib/codeql/actions/Helper.qll index f177c645dbd..2953817de6b 100644 --- a/ql/lib/codeql/actions/Helper.qll +++ b/ql/lib/codeql/actions/Helper.qll @@ -212,6 +212,32 @@ predicate writeToGitHubPath(Run run, string content) { extractFileWrite(run.getScript(), "GITHUB_PATH", 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) +} + predicate inPrivilegedCompositeAction(AstNode node) { exists(CompositeAction a | a = node.getEnclosingCompositeAction() and diff --git a/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll b/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll index fc45b8c041d..40c0c7da9eb 100644 --- a/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/EnvPathInjectionQuery.qll @@ -2,6 +2,7 @@ private import actions private import codeql.actions.TaintTracking private import codeql.actions.dataflow.ExternalFlow private import codeql.actions.security.ArtifactPoisoningQuery +private import codeql.actions.security.UntrustedCheckoutQuery private import codeql.actions.dataflow.FlowSteps import codeql.actions.DataFlow import codeql.actions.dataflow.FlowSources @@ -16,27 +17,39 @@ abstract class EnvPathInjectionSink extends DataFlow::Node { } */ class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink { EnvPathInjectionFromFileReadSink() { - exists(Run run, UntrustedArtifactDownloadStep step, string value | + exists(Run run, Step step | + ( + step instanceof UntrustedArtifactDownloadStep or + step instanceof PRHeadCheckoutStep + ) and this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and - writeToGitHubPath(run, value) and ( - outputsPartialFileContent(value) - or // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_PATH - exists(string line, string var_name, string var_value | - run.getScript().splitAt("\n") = line - | - var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and - var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and - outputsPartialFileContent(var_value) and + // cat test-results/.env >> $GITHUB_PATH + fileToGitHubPath(run, _) + or + exists(string value | + writeToGitHubPath(run, value) and ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + outputsPartialFileContent(value) or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 + // e.g. + // FOO=$(cat test-results/sha-number) + // echo "FOO=$FOO" >> $GITHUB_PATH + exists(string line, string var_name, string var_value | + run.getScript().splitAt("\n") = line + | + var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and + var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and + outputsPartialFileContent(var_value) and + ( + value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + or + value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and + value.indexOf(var_name) > 0 + ) + ) ) ) ) diff --git a/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll b/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll index f7a9283f800..4f54f38f274 100644 --- a/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll +++ b/ql/lib/codeql/actions/security/EnvVarInjectionQuery.qll @@ -2,6 +2,7 @@ private import actions private import codeql.actions.TaintTracking private import codeql.actions.dataflow.ExternalFlow private import codeql.actions.security.ArtifactPoisoningQuery +private import codeql.actions.security.UntrustedCheckoutQuery private import codeql.actions.dataflow.FlowSteps import codeql.actions.DataFlow import codeql.actions.dataflow.FlowSources @@ -12,33 +13,48 @@ abstract class EnvVarInjectionSink extends DataFlow::Node { } * Holds if a Run step declares an environment variable with contents from a local file. * e.g. * run: | + * cat test-results/.env >> $GITHUB_ENV * echo "sha=$(cat test-results/sha-number)" >> $GITHUB_ENV * echo "sha=$(> $GITHUB_ENV */ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink { EnvVarInjectionFromFileReadSink() { - exists(Run run, UntrustedArtifactDownloadStep step, string content, string value | + exists(Run run, Step step | + ( + step instanceof UntrustedArtifactDownloadStep or + step instanceof PRHeadCheckoutStep + ) and this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and - writeToGitHubEnv(run, content) and - extractVariableAndValue(content, _, value) and ( - outputsPartialFileContent(value) - or // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_ENV - exists(string line, string var_name, string var_value | - run.getScript().splitAt("\n") = line - | - var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and - var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and - outputsPartialFileContent(var_value) and + // cat test-results/.env >> $GITHUB_ENV + fileToGitHubEnv(run, _) + or + exists(string content, string value | + writeToGitHubEnv(run, content) and + extractVariableAndValue(content, _, value) and ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + // e.g. + // echo "FOO=$(cat test-results/sha-number)" >> $GITHUB_ENV + outputsPartialFileContent(value) or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 + // e.g. + // FOO=$(cat test-results/sha-number) + // echo "FOO=$FOO" >> $GITHUB_ENV + exists(string line, string var_name, string var_value | + run.getScript().splitAt("\n") = line + | + var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and + var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and + outputsPartialFileContent(var_value) and + ( + value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + or + value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and + value.indexOf(var_name) > 0 + ) + ) ) ) ) diff --git a/ql/lib/codeql/actions/security/OutputClobberingQuery.qll b/ql/lib/codeql/actions/security/OutputClobberingQuery.qll index 4fe3268c00a..af8f7af089d 100644 --- a/ql/lib/codeql/actions/security/OutputClobberingQuery.qll +++ b/ql/lib/codeql/actions/security/OutputClobberingQuery.qll @@ -2,6 +2,7 @@ private import actions private import codeql.actions.TaintTracking private import codeql.actions.dataflow.ExternalFlow private import codeql.actions.security.ArtifactPoisoningQuery +private import codeql.actions.security.UntrustedCheckoutQuery private import codeql.actions.dataflow.FlowSteps import codeql.actions.DataFlow import codeql.actions.dataflow.FlowSources @@ -12,40 +13,53 @@ abstract class OutputClobberingSink extends DataFlow::Node { } * Holds if a Run step declares an environment variable with contents from a local file. * e.g. * run: | + * cat test-results/.vars >> $GITHUB_OUTPUT * echo "sha=$(cat test-results/sha-number)" >> $GITHUB_OUTPUT * echo "sha=$(> $GITHUB_OUTPUT */ class OutputClobberingFromFileReadSink extends OutputClobberingSink { OutputClobberingFromFileReadSink() { - exists(Run run, UntrustedArtifactDownloadStep step, string content, string key, string value | + exists(Run run, Step step | + ( + step instanceof UntrustedArtifactDownloadStep or + step instanceof PRHeadCheckoutStep + ) and this.asExpr() = run.getScriptScalar() and step.getAFollowingStep() = run and - writeToGitHubOutput(run, content) and - extractVariableAndValue(content, key, value) and - // there is a different output variable in the same script - // TODO: key2/value2 should be declared before key/value - exists(string content2, string key2 | - writeToGitHubOutput(run, content2) and - extractVariableAndValue(content2, key2, _) and - not key2 = key - ) and ( - outputsPartialFileContent(value) - or // e.g. - // FOO=$(cat test-results/sha-number) - // echo "FOO=$FOO" >> $GITHUB_OUTPUT - exists(string line, string var_name, string var_value | - run.getScript().splitAt("\n") = line - | - var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and - var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and - outputsPartialFileContent(var_value) and + // cat test-results/.vars >> $GITHUB_OUTPUT + fileToGitHubOutput(run, _) + or + exists(string content, string key, string value | + writeToGitHubOutput(run, content) and + extractVariableAndValue(content, key, value) and + // there is a different output variable in the same script + // TODO: key2/value2 should be declared before key/value + exists(string content2, string key2 | + writeToGitHubOutput(run, content2) and + extractVariableAndValue(content2, key2, _) and + not key2 = key + ) and ( - value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + outputsPartialFileContent(value) or - value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and - value.indexOf(var_name) > 0 + // e.g. + // FOO=$(cat test-results/sha-number) + // echo "FOO=$FOO" >> $GITHUB_OUTPUT + exists(string line, string var_name, string var_value | + run.getScript().splitAt("\n") = line + | + var_name = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 1) and + var_value = line.regexpCapture("([a-zA-Z0-9\\-_]+)=(.*)", 2) and + outputsPartialFileContent(var_value) and + ( + value.matches("%$" + ["", "{", "ENV{"] + var_name + "%") + or + value.regexpMatch("\\$\\((echo|printf|write-output)\\s+.*") and + value.indexOf(var_name) > 0 + ) + ) ) ) ) diff --git a/ql/test/query-tests/Security/CWE-077/.github/workflows/test10.yml b/ql/test/query-tests/Security/CWE-077/.github/workflows/test10.yml new file mode 100644 index 00000000000..f43a12cb42a --- /dev/null +++ b/ql/test/query-tests/Security/CWE-077/.github/workflows/test10.yml @@ -0,0 +1,28 @@ +name: Build and Dockerize + +on: + pull_request_target: + +jobs: + build: + name: Test + runs-on: ubuntu-latest + steps: + - name: Decide Which 'ref' To Checkout + id: decide-ref + run: | + if [[ "${{github.event_name}}" == "pull_request_target" ]]; then + echo "ref=refs/pull/${{ github.event.pull_request.number }}/merge" >> $GITHUB_OUTPUT + else + echo "ref=${{github.ref}}" >> $GITHUB_OUTPUT + fi + + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{steps.decide-ref.outputs.ref}} + path: "foo" + + - name: Read Java Config + run: cat foo/.github/java-config.env >> $GITHUB_ENV + diff --git a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected index 7d92032f00b..359275aef43 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionCritical.expected @@ -19,6 +19,7 @@ edges | .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 | | 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,6 +59,8 @@ nodes | .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/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 | +| .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | semmle.label | cat foo/.github/java-config.env >> $GITHUB_ENV | 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 | @@ -80,3 +83,4 @@ subpaths | .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/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 | diff --git a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected index 2cd36953802..eaa9fed4c61 100644 --- a/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected +++ b/ql/test/query-tests/Security/CWE-077/EnvVarInjectionMedium.expected @@ -19,6 +19,7 @@ edges | .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 | | 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,5 +59,7 @@ nodes | .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/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 | +| .github/workflows/test10.yml:27:14:27:59 | cat foo/.github/java-config.env >> $GITHUB_ENV | semmle.label | cat foo/.github/java-config.env >> $GITHUB_ENV | subpaths #select