From bd9cd3eb8680757845031da5e5837277a03a616b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Wed, 17 Apr 2024 11:15:59 +0200 Subject: [PATCH] new untrusted checkout step --- ql/lib/ext/sergeysova_jq-action.model.yml | 7 +++++++ ql/src/Security/CWE-829/UntrustedCheckout.ql | 21 ++++++++++++++++++- .../.github/workflows/untrusted_checkout2.yml | 19 +++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 ql/lib/ext/sergeysova_jq-action.model.yml create mode 100644 ql/test/query-tests/Security/CWE-829/.github/workflows/untrusted_checkout2.yml diff --git a/ql/lib/ext/sergeysova_jq-action.model.yml b/ql/lib/ext/sergeysova_jq-action.model.yml new file mode 100644 index 00000000000..8ab1d090b1c --- /dev/null +++ b/ql/lib/ext/sergeysova_jq-action.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: githubsecuritylab/actions-all + extensible: sinkModel + data: + - ["sergeysova/jq-action", "*", "input.cmd", "code-injection", "manual"] + diff --git a/ql/src/Security/CWE-829/UntrustedCheckout.ql b/ql/src/Security/CWE-829/UntrustedCheckout.ql index 40f6d2fec9e..c9cbb0ab13c 100644 --- a/ql/src/Security/CWE-829/UntrustedCheckout.ql +++ b/ql/src/Security/CWE-829/UntrustedCheckout.ql @@ -66,7 +66,8 @@ predicate containsHeadRef(string s) { "\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.head\\.sha\\b", "\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.id\\b", "\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.number\\b", - "\\bhead\\.sha\\b", "\\bhead\\.ref\\b" + // heuristics + "\\bhead\\.sha\\b", "\\bhead\\.ref\\b", "\\bpr_number\\b", "\\bpr_head_sha\\b" ], _, _) ) } @@ -121,6 +122,24 @@ class GitCheckout extends PRHeadCheckoutStep instanceof Run { } } +/** Checkout of a Pull Request HEAD ref using gh within a Run step */ +class GhCheckout extends PRHeadCheckoutStep instanceof Run { + GhCheckout() { + exists(string line | + this.getScript().splitAt("\n") = line and + line.regexpMatch(".*gh\\s+pr\\s+checkout.*") and + ( + containsHeadRef(line) + or + exists(string varname | + containsHeadRef(this.getInScopeEnvVarExpr(varname).getExpression()) and + exists(line.regexpFind(varname, _, _)) + ) + ) + ) + } +} + from Workflow w, PRHeadCheckoutStep checkout where w.isPrivileged() and diff --git a/ql/test/query-tests/Security/CWE-829/.github/workflows/untrusted_checkout2.yml b/ql/test/query-tests/Security/CWE-829/.github/workflows/untrusted_checkout2.yml new file mode 100644 index 00000000000..d9e5d6be670 --- /dev/null +++ b/ql/test/query-tests/Security/CWE-829/.github/workflows/untrusted_checkout2.yml @@ -0,0 +1,19 @@ +on: issue_comment + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Get PR number + id: pr_number + if: ${{ github.event_name == 'issue_comment'}} + run: | + PR_URL="${{ github.event.issue.pull_request.url }}" + PR_NUMBER=${PR_URL##*/} + echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT + - name: Checkout Pull Request + if: github.event_name == 'issue_comment' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr checkout ${{ needs.should_run_it.outputs.pr_number }}