Refactor bash script parsing to improve coverage of env var injection

This commit is contained in:
Alvaro Muñoz
2024-06-28 12:31:43 +02:00
parent 40a6f3bbee
commit a485528ebe
9 changed files with 172 additions and 64 deletions

View File

@@ -235,3 +235,14 @@ predicate inNonPrivilegedJob(AstNode node) {
not j.isPrivilegedExternallyTriggerable()
)
}
bindingset[snippet]
predicate outputsPartialFileContent(string snippet) {
// e.g.
// echo FOO=`yq '.foo' foo.yml` >> $GITHUB_ENV
// echo "FOO=$(<foo.txt)" >> $GITHUB_ENV
// yq '.foo' foo.yml >> $GITHUB_PATH
// cat foo.txt >> $GITHUB_PATH
snippet
.regexpMatch(["(\\$\\(|`)<.*", ".*(\\b|^|\\s+)" + ["cat\\s+", "jq\\s+", "yq\\s+", "tail\\s+", "head\\s+", "ls\\s+"] + ".*"])
}

View File

@@ -23,6 +23,60 @@ class AdditionalTaintStep extends Unit {
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
}
/**
* 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 envToRunFlow(string file, string var_name, Run run, string key) {
exists(string content, string value |
(
file = "GITHUB_ENV" and
writeToGitHubEnv(run, content) and
extractVariableAndValue(content, key, value)
or
file = "GITHUB_OUTPUT" and
writeToGitHubOutput(run, content) and
extractVariableAndValue(content, key, value)
or
file = "GITHUB_PATH" and
writeToGitHubPath(run, content) and
key = "path" and
value = content
) and
(
// e.g. echo "FOO=$BODY" >> $GITHUB_ENV
// e.g. echo "FOO=${BODY}" >> $GITHUB_ENV
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
or
// e.g. echo "FOO=$(echo $BODY)" >> $GITHUB_ENV
value.matches("$(echo %") and value.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
(
value.matches("%$" + ["", "{", "ENV{"] + var2_name + "%")
or
value.matches("$(echo %") and value.indexOf(var2_name) > 0
)
)
)
)
}
/**
* Holds if a Run step declares an environment variable, uses it in its script to set another env var.
* e.g.
@@ -32,20 +86,10 @@ class AdditionalTaintStep extends Unit {
* echo "foo=$(echo $BODY)" >> $GITHUB_ENV
*/
predicate envToRunStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Run run, string var_name, string content, string value |
exists(Run run, string var_name |
run.getInScopeEnvVarExpr(var_name) = pred.asExpr() and
succ.asExpr() = run.getScriptScalar()
|
(
writeToGitHubEnv(run, content) or
writeToGitHubOutput(run, content)
) and
extractVariableAndValue(content, _, value) and
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
or
writeToGitHubPath(run, content) and
value = content and
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
succ.asExpr() = run.getScriptScalar() and
envToRunFlow(["GITHUB_ENV", "GITHUB_PATH"], var_name, run, _)
)
}
@@ -63,16 +107,26 @@ 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 content, string key, string value |
writeToGitHubOutput(run, content) and
extractVariableAndValue(content, key, value) and
c = any(DataFlow::FieldContent ct | ct.getName() = key) and
pred.asExpr() = run.getInScopeEnvVarExpr(var_name) and
exists(Run run, string var_name, string key |
run.getInScopeEnvVarExpr(var_name) = pred.asExpr() and
succ.asExpr() = run and
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
envToRunFlow("GITHUB_OUTPUT", var_name, run, key) and
c = any(DataFlow::FieldContent ct | ct.getName() = key)
)
}
// predicate dISABLEDenvToOutputStoreStep(
// DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c
// ) {
// exists(Run run, string var_name, string content, string key, string value |
// writeToGitHubOutput(run, content) and
// extractVariableAndValue(content, key, value) and
// c = any(DataFlow::FieldContent ct | ct.getName() = key) and
// pred.asExpr() = run.getInScopeEnvVarExpr(var_name) and
// succ.asExpr() = run and
// value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
// )
// }
predicate envToEnvStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) {
exists(Run run, string var_name, string content, string key, string value |
writeToGitHubEnv(run, content) and

View File

@@ -1,22 +1,26 @@
private import actions
private import codeql.actions.TaintTracking
private import codeql.actions.dataflow.ExternalFlow
import codeql.actions.dataflow.FlowSources
private import codeql.actions.security.ArtifactPoisoningQuery
private import codeql.actions.dataflow.FlowSteps
import codeql.actions.DataFlow
import codeql.actions.dataflow.FlowSources
abstract class EnvPathInjectionSink extends DataFlow::Node { }
/**
* Holds if a Run step declares a PATH environment variable with contents from a local file.
* e.g.
* run: |
* cat foo.txt >> $GITHUB_PATH
*/
class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink {
EnvPathInjectionFromFileReadSink() {
exists(Run run, UntrustedArtifactDownloadStep step, string value |
this.asExpr() = run.getScriptScalar() and
step.getAFollowingStep() = run and
writeToGitHubPath(run, value) and
// (eg: echo DATABASE_SHA=`yq '.creationMetadata.sha' codeql-database.yml` >> $GITHUB_ENV)
value
.regexpMatch(["\\$\\(", "`"] +
["cat\\s+", "<", "jq\\s+", "yq\\s+", "tail\\s+", "head\\s+"] + ".*" + ["`", "\\)"])
outputsPartialFileContent(value)
)
}
}
@@ -31,15 +35,10 @@ class EnvPathInjectionFromFileReadSink extends EnvPathInjectionSink {
*/
class EnvPathInjectionFromEnvVarSink extends EnvPathInjectionSink {
EnvPathInjectionFromEnvVarSink() {
exists(Run run, Expression expr, string var_name, string value |
run.getInScopeEnvVarExpr(var_name) = expr and
run.getScriptScalar() = this.asExpr() and
writeToGitHubPath(run, value) and
(
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
or
value.matches("$(echo %") and value.indexOf(var_name) > 0
)
exists(Run run, string var_name |
envToRunFlow("GITHUB_PATH", var_name, run, _) and
exists(run.getInScopeEnvVarExpr(var_name)) and
run.getScriptScalar() = this.asExpr()
)
}
}

View File

@@ -1,12 +1,20 @@
private import actions
private import codeql.actions.TaintTracking
private import codeql.actions.dataflow.ExternalFlow
import codeql.actions.dataflow.FlowSources
private import codeql.actions.security.ArtifactPoisoningQuery
private import codeql.actions.dataflow.FlowSteps
import codeql.actions.DataFlow
import codeql.actions.dataflow.FlowSources
abstract class EnvVarInjectionSink extends DataFlow::Node { }
/**
* Holds if a Run step declares an environment variable with contents from a local file.
* e.g.
* run: |
* echo "sha=$(cat test-results/sha-number)" >> $GITHUB_ENV
* echo "sha=$(<test-results/sha-number)" >> $GITHUB_ENV
*/
class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink {
EnvVarInjectionFromFileReadSink() {
exists(Run run, UntrustedArtifactDownloadStep step, string content, string value |
@@ -14,10 +22,7 @@ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink {
step.getAFollowingStep() = run and
writeToGitHubEnv(run, content) and
extractVariableAndValue(content, _, value) and
// (eg: echo DATABASE_SHA=`yq '.creationMetadata.sha' codeql-database.yml` >> $GITHUB_ENV)
value
.regexpMatch(["\\$\\(", "`"] +
["cat\\s+", "<", "jq\\s+", "yq\\s+", "tail\\s+", "head\\s+"] + ".*" + ["`", "\\)"])
outputsPartialFileContent(value)
)
}
}
@@ -32,16 +37,10 @@ class EnvVarInjectionFromFileReadSink extends EnvVarInjectionSink {
*/
class EnvVarInjectionFromEnvVarSink extends EnvVarInjectionSink {
EnvVarInjectionFromEnvVarSink() {
exists(Run run, Expression expr, string var_name, string content, string value |
run.getInScopeEnvVarExpr(var_name) = expr and
run.getScriptScalar() = this.asExpr() and
writeToGitHubEnv(run, content) and
extractVariableAndValue(content, _, value) and
(
value.matches("%$" + ["", "{", "ENV{"] + var_name + "%")
or
value.matches("$(echo %") and value.indexOf(var_name) > 0
)
exists(Run run, string var_name |
envToRunFlow("GITHUB_ENV", var_name, run, _) and
exists(run.getInScopeEnvVarExpr(var_name)) and
run.getScriptScalar() = this.asExpr()
)
}
}

View File

@@ -18,7 +18,7 @@ class PoisonableCommandStep extends PoisonableStep, Run {
PoisonableCommandStep() {
exists(string regexp |
poisonableCommandsDataModel(regexp) and
exists(this.getScript().splitAt("\n").trim().regexpFind("([^a-z]|^)" + regexp, _, _))
exists(this.getScript().splitAt("\n").trim().regexpFind("(^|\\b|\\s+)" + regexp, _, _))
)
}
}
@@ -29,7 +29,7 @@ class LocalScriptExecutionRunStep extends PoisonableStep, Run {
LocalScriptExecutionRunStep() {
exists(string line, string regexp, int group | line = this.getScript().splitAt("\n").trim() |
poisonableLocalScriptsDataModel(regexp, group) and
cmd = line.regexpCapture(regexp, group)
cmd = line.regexpCapture("(^|\\b|\\s+)" + regexp, group)
)
}
@@ -40,16 +40,12 @@ class LocalActionUsesStep extends PoisonableStep, UsesStep {
LocalActionUsesStep() { this.getCallee().matches("./%") }
}
class EnvVarInjectionRunStep extends PoisonableStep, Run {
EnvVarInjectionRunStep() {
exists(string content, string value |
// Heuristic:
// Run step with env var definition based on file content.
// eg: `echo "sha=$(cat test-results/sha-number)" >> $GITHUB_ENV`
// eg: `echo "sha=$(<test-results/sha-number)" >> $GITHUB_ENV`
class EnvVarInjectionFromFileReadRunStep extends PoisonableStep, Run {
EnvVarInjectionFromFileReadRunStep() {
exists(string content, string value|
writeToGitHubEnv(this, content) and
extractVariableAndValue(content, _, value) and
value.matches("%" + ["ls ", "cat ", "jq ", "$(<"] + "%")
outputsPartialFileContent(value)
)
}
}

View File

@@ -54,10 +54,10 @@ extensions:
extensible: poisonableLocalScriptsDataModel
data:
# TODO: It could also be in the form of `dir/cmd`
- ["(^|;\\s*|\\s+)(\\.\\/)(.*)(\\s+|;|$)", 3]
- ["(^|;\\s*|\\s+)(source|sh|bash|zsh|fish)\\s+(.*)(\\s+|;|$)", 3]
- ["(^|;\\s*|\\s+)(node)\\s+(.*)(\\.js|\\.ts)(\\s+|;|$)", 3]
- ["(^|;\\s*|\\s+)(python)\\s+(.*)\\.py(\\s+|;|$)", 3]
- ["(^|;\\s*|\\s+)(ruby)\\s+(.*)\\.rb(\\s+|;|$)", 3]
- ["(^|;\\s*|\\s+)(go)\\s+(.*)\\.go(\\s+|;|$)", 3]
- ["(\\.\\/)(.*)(\\s+|;|$)", 3]
- ["(source|sh|bash|zsh|fish)\\s+(.*)(\\s+|;|$)", 3]
- ["(node)\\s+(.*)(\\.js|\\.ts)(\\s+|;|$)", 3]
- ["(python)\\s+(.*)\\.py(\\s+|;|$)", 3]
- ["(ruby)\\s+(.*)\\.rb(\\s+|;|$)", 3]
- ["(go)\\s+(.*)\\.go(\\s+|;|$)", 3]

View File

@@ -0,0 +1,28 @@
name: Test
on:
pull_request_target:
jobs:
test:
runs-on: ubuntu-latest
steps:
- env:
TITLE: ${{ github.event.pull_request.title }}
run: |
FOO=${TITLE##*/}
echo PR_TITLE=${FOO} >> $GITHUB_ENV
- env:
TITLE: ${{ github.event.pull_request.title }}
run: |
FOO=$TITLE+
echo PR_TITLE=$FOO >> $GITHUB_ENV
- env:
TITLE: ${{ github.event.pull_request.title }}
run: |
venv="$(echo $TITLE)')"
echo "VIRTUAL_ENV=${venv}" >> $GITHUB_ENV

View File

@@ -11,6 +11,9 @@ edges
| .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<id>[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 | |
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 |
@@ -36,6 +39,12 @@ nodes
| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test5.yml:10:9:30:6 | Uses Step | semmle.label | 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 | semmle.label | 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 |
| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | semmle.label | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n |
| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | semmle.label | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n |
| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .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 |
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 |
@@ -50,3 +59,6 @@ subpaths
| .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | .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 | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test4.yml:55:14:55:70 | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV | echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV |
| .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P<id>[0-9]+)') >> $GITHUB_ENV | .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<id>[0-9]+)') >> $GITHUB_ENV | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test4.yml:58:14:58:94 | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P<id>[0-9]+)') >> $GITHUB_ENV | echo ISSUE_KEY=$(echo "${TITLE}" \| grep -oP 'ISPN-(?P<id>[0-9]+)') >> $GITHUB_ENV |
| .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 | .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 | Potential environment variable injection in $@, which may be controlled by an external user. | .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 | 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 |
| .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | .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 | Potential environment variable injection in $@, which may be controlled by an external user. | .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n |
| .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 |

View File

@@ -11,6 +11,9 @@ edges
| .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<id>[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 | |
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 |
@@ -36,5 +39,11 @@ nodes
| .github/workflows/test4.yml:60:19:60:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test5.yml:10:9:30:6 | Uses Step | semmle.label | 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 | semmle.label | 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 |
| .github/workflows/test6.yml:11:19:11:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test6.yml:12:14:14:46 | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n | semmle.label | FOO=${TITLE##*/}\necho PR_TITLE=${FOO} >> $GITHUB_ENV\n |
| .github/workflows/test6.yml:16:19:16:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .github/workflows/test6.yml:17:14:19:44 | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n | semmle.label | FOO=$TITLE+\necho PR_TITLE=$FOO >> $GITHUB_ENV\n |
| .github/workflows/test6.yml:21:19:21:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
| .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 |
subpaths
#select