Skip to content

Commit 1cdcb32

Browse files
author
Alvaro Muñoz
authored
Merge pull request #48 from GitHubSecurityLab/new_untrusted_checkout_step
new untrusted checkout step
2 parents d18c575 + afaab8b commit 1cdcb32

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
- addsTo:
3+
pack: githubsecuritylab/actions-all
4+
extensible: sinkModel
5+
data:
6+
- ["sergeysova/jq-action", "*", "input.cmd", "code-injection", "manual"]
7+

ql/src/Security/CWE-829/UntrustedCheckout.ql

+20-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ predicate containsHeadRef(string s) {
6666
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.head\\.sha\\b",
6767
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.id\\b",
6868
"\\bgithub\\.event\\.check_run\\.pull_requests\\[\\d+\\]\\.number\\b",
69-
"\\bhead\\.sha\\b", "\\bhead\\.ref\\b"
69+
// heuristics
70+
"\\bhead\\.sha\\b", "\\bhead\\.ref\\b", "\\bpr_number\\b", "\\bpr_head_sha\\b"
7071
], _, _)
7172
)
7273
}
@@ -121,6 +122,24 @@ class GitCheckout extends PRHeadCheckoutStep instanceof Run {
121122
}
122123
}
123124

125+
/** Checkout of a Pull Request HEAD ref using gh within a Run step */
126+
class GhCheckout extends PRHeadCheckoutStep instanceof Run {
127+
GhCheckout() {
128+
exists(string line |
129+
this.getScript().splitAt("\n") = line and
130+
line.regexpMatch(".*gh\\s+pr\\s+checkout.*") and
131+
(
132+
containsHeadRef(line)
133+
or
134+
exists(string varname |
135+
containsHeadRef(this.getInScopeEnvVarExpr(varname).getExpression()) and
136+
exists(line.regexpFind(varname, _, _))
137+
)
138+
)
139+
)
140+
}
141+
}
142+
124143
from Workflow w, PRHeadCheckoutStep checkout
125144
where
126145
w.isPrivileged() and
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
on: issue_comment
2+
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Get PR number
8+
id: pr_number
9+
if: ${{ github.event_name == 'issue_comment'}}
10+
run: |
11+
PR_URL="${{ github.event.issue.pull_request.url }}"
12+
PR_NUMBER=${PR_URL##*/}
13+
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT
14+
- name: Checkout Pull Request
15+
if: github.event_name == 'issue_comment'
16+
env:
17+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
run: |
19+
gh pr checkout ${{ needs.should_run_it.outputs.pr_number }}

ql/test/query-tests/Security/CWE-829/UntrustedCheckout.expected

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
| .github/workflows/issue_comment_octokit.yml:79:9:83:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
1919
| .github/workflows/issue_comment_octokit.yml:95:9:100:2 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
2020
| .github/workflows/issue_comment_octokit.yml:109:9:114:66 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
21+
| .github/workflows/untrusted_checkout2.yml:14:9:19:72 | Run Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
2122
| .github/workflows/untrusted_checkout.yml:10:9:13:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
2223
| .github/workflows/untrusted_checkout.yml:13:9:15:31 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
2324
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |

0 commit comments

Comments
 (0)