Skip to content

Commit 8f350d9

Browse files
author
Alvaro Muñoz
authored
Merge pull request #104 from github/new_gh_sources
New gh CLI sources
2 parents 54338f4 + 02c5f74 commit 8f350d9

File tree

9 files changed

+412
-9
lines changed

9 files changed

+412
-9
lines changed

ql/lib/codeql/actions/config/Config.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ predicate vulnerableActionsDataModel(
125125
* - cmd_regex: Regular expression for matching untrusted git commands
126126
* - flag: Flag for the command
127127
*/
128-
predicate untrustedGitCommandsDataModel(string cmd_regex, string flag) {
129-
Extensions::untrustedGitCommandsDataModel(cmd_regex, flag)
128+
predicate untrustedGitCommandDataModel(string cmd_regex, string flag) {
129+
Extensions::untrustedGitCommandDataModel(cmd_regex, flag)
130+
}
131+
132+
/**
133+
* MaD models for untrusted gh commands
134+
* Fields:
135+
* - cmd_regex: Regular expression for matching untrusted gh commands
136+
* - flag: Flag for the command
137+
*/
138+
predicate untrustedGhCommandDataModel(string cmd_regex, string flag) {
139+
Extensions::untrustedGhCommandDataModel(cmd_regex, flag)
130140
}

ql/lib/codeql/actions/config/ConfigExtensions.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,9 @@ extensible predicate vulnerableActionsDataModel(
6161
/**
6262
* Holds for git commands that may introduce untrusted data when called on an attacker controlled branch.
6363
*/
64-
extensible predicate untrustedGitCommandsDataModel(string cmd_regex, string flag);
64+
extensible predicate untrustedGitCommandDataModel(string cmd_regex, string flag);
65+
66+
/**
67+
* Holds for gh commands that may introduce untrusted data
68+
*/
69+
extensible predicate untrustedGhCommandDataModel(string cmd_regex, string flag);

ql/lib/codeql/actions/dataflow/FlowSources.qll

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class GitCommandSource extends RemoteFlowSource, CommandSource {
8080

8181
GitCommandSource() {
8282
exists(Step checkout, string cmd_regex |
83-
// This shoould be:
83+
// This should be:
8484
// source instanceof PRHeadCheckoutStep
8585
// but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error
8686
// so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround
@@ -105,8 +105,8 @@ class GitCommandSource extends RemoteFlowSource, CommandSource {
105105
checkout.getAFollowingStep() = run and
106106
run.getScript().getAStmt() = cmd and
107107
cmd.indexOf("git") = 0 and
108-
untrustedGitCommandsDataModel(cmd_regex, flag) and
109-
cmd.regexpMatch(".*" + cmd_regex + ".*")
108+
untrustedGitCommandDataModel(cmd_regex, flag) and
109+
cmd.regexpMatch(cmd_regex + ".*")
110110
)
111111
}
112112

@@ -117,6 +117,28 @@ class GitCommandSource extends RemoteFlowSource, CommandSource {
117117
override Run getEnclosingRun() { result = run }
118118
}
119119

120+
class GhCLICommandSource extends RemoteFlowSource, CommandSource {
121+
Run run;
122+
string cmd;
123+
string flag;
124+
125+
GhCLICommandSource() {
126+
exists(string cmd_regex |
127+
this.asExpr() = run.getScript() and
128+
run.getScript().getAStmt() = cmd and
129+
cmd.indexOf("gh ") = 0 and
130+
untrustedGhCommandDataModel(cmd_regex, flag) and
131+
cmd.regexpMatch(cmd_regex + ".*")
132+
)
133+
}
134+
135+
override string getSourceType() { result = flag }
136+
137+
override Run getEnclosingRun() { result = run }
138+
139+
override string getCommand() { result = cmd }
140+
}
141+
120142
class GitHubEventPathSource extends RemoteFlowSource, CommandSource {
121143
string cmd;
122144
string flag;
@@ -206,7 +228,7 @@ class ArtifactSource extends RemoteFlowSource, FileSource {
206228
*/
207229
private class CheckoutSource extends RemoteFlowSource, FileSource {
208230
CheckoutSource() {
209-
// This shoould be:
231+
// This should be:
210232
// source instanceof PRHeadCheckoutStep
211233
// but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error
212234
// so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround

ql/lib/codeql/actions/security/OutputClobberingQuery.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class OutputClobberingFromFileReadSink extends OutputClobberingSink {
2020
(
2121
step instanceof UntrustedArtifactDownloadStep
2222
or
23-
// This shoould be:
23+
// This should be:
2424
// artifact instanceof PRHeadCheckoutStep
2525
// but PRHeadCheckoutStep uses Taint Tracking anc causes a non-Monolitic Recursion error
2626
// so we list all the subclasses of PRHeadCheckoutStep here and use actions/checkout as a workaround
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
extensions:
2+
- addsTo:
3+
pack: github/actions-all
4+
extensible: untrustedGhCommandDataModel
5+
data:
6+
#
7+
# PULL REQUESTS
8+
#
9+
# HEAD_REF=$(gh pr view "${{ github.event.issue.number }}" --json headRefName -q '.headRefName')
10+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.headRefName.*", "branch,oneline"]
11+
# TITLE=$(gh pr view $PR_NUMBER --json title --jq .title)
12+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.title.*", "title,oneline"]
13+
# BODY=$(gh pr view $PR_NUMBER --json body --jq .body)
14+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.body.*", "text,multiline"]
15+
# COMMENTS="$(gh pr view --repo ${{ github.repository }} "$PR_NUMBER" --json "body,comments" -q '.body, .comments[].body')"
16+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.comments.*", "text,multiline"]
17+
# CHANGED_FILES="$(gh pr view --repo ${{ github.repository }} ${{ needs.check-comment.outputs.pull_number }} --json files --jq '.files.[].path')"
18+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.files.*", "filename,multiline"]
19+
# AUTHOR=$(gh pr view ${ORI_PR} -R ${REPO} --json author -q '.author.login')
20+
- ["gh\\s+pr\\b.*\\bview\\b.*\\.author.*", "username,oneline"]
21+
#
22+
# ISSUES
23+
#
24+
# TITLE=$(gh issue view "$ISSUE_NUMBER" --json title --jq '.title')
25+
- ["gh\\s+issue\\b.*\\bview\\b.*\\.title.*", "title,oneline"]
26+
# BODY=$(gh issue view -R ${GITHUB_REPOSITORY} ${ORIGINAL_ISSUE_NUMBER} --json title,body,assignees --jq .body)
27+
- ["gh\\s+issue\\b.*\\bview\\b.*\\.body.*", "text,multiline"]
28+
# COMMENTS=$(gh issue view "$ISSUE_NUMBER" --json comments --jq '.comments[].body')
29+
- ["gh\\s+issue\\b.*\\bview\\b.*\\.comments.*", "text,multiline"]
30+
#
31+
# API
32+
#
33+
# PR="$(gh api /repos/test/test/pulls/${PR_NUMBER})"
34+
#
35+
# HEAD_REF=$(gh api -H 'Accept: application/vnd.github+json' /repos/test/test/commits/${{ env.sui_sha }}/pulls --jq '.[].head.ref' | head -n 1)
36+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*\\b.*\\.head.ref.*", "branch,oneline"]
37+
# TITLE=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".title")
38+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*\\b.*\\.title.*", "title,oneline"]
39+
# BODY=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".body")
40+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*\\b.*\\.body.*", "text,multiline"]
41+
# COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')
42+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*/comments\\b.*\\.body.*", "text,multiline"]
43+
# CHANGED_FILES=$(gh api /repos/test/test/pulls/${{PR_NUMBER}}/files --jq '.[].filename')
44+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*/files\\b.*\\.filename.*", "filename,oneline"]
45+
# AUTHOR=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".user.login")
46+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/pulls.*\\b.*\\.user\\.login.*", "username,oneline"]
47+
#
48+
# ISSUES
49+
#
50+
# TITLE=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".title")
51+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/issues.*\\b.*\\.title.*", "title,oneline"]
52+
# BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")
53+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/issues.*\\b.*\\.body.*", "text,multiline"]
54+
# COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')
55+
- ["gh\\s+api\\b.*\\b(/)?repos/.*/issues.*/comments\\b.*\\.body.*", "text,multiline"]
56+

ql/lib/ext/config/untrusted_git_commands.yml renamed to ql/lib/ext/config/untrusted_git_command.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extensions:
22
- addsTo:
33
pack: github/actions-all
4-
extensible: untrustedGitCommandsDataModel
4+
extensible: untrustedGitCommandDataModel
55
data:
66
# FILES=$(git diff-tree --no-commit-id --name-only HEAD -r)
77
- ["git\\b.*\\bdiff-tree\\b", "filename,multiline"]
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: Pull Request Open
2+
3+
on:
4+
pull_request_target:
5+
6+
jobs:
7+
pulls1:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- id: head_ref
11+
run: |
12+
HEAD_REF=$(gh pr view "${{ github.event.issue.number }}" --json headRefName -q '.headRefName')
13+
echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
14+
- run: echo "${{ steps.head_ref.outputs.head_ref}}"
15+
- id: title
16+
run: |
17+
TITLE=$(gh pr view $PR_NUMBER --json title --jq .title)
18+
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
19+
- run: echo "${{ steps.title.outputs.title}}"
20+
- id: body
21+
run: |
22+
BODY=$(gh pr view $PR_NUMBER --json body --jq .body)
23+
echo "body=$BODY" >> "$GITHUB_OUTPUT"
24+
- run: echo "${{ steps.body.outputs.body}}"
25+
- id: comments
26+
run: |
27+
COMMENTS="$(gh pr view --repo ${{ github.repository }} "$PR_NUMBER" --json "body,comments" -q '.body, .comments[].body')"
28+
echo "comments=$COMMENTS" >> "$GITHUB_OUTPUT"
29+
- run: echo "${{ steps.comments.outputs.comments}}"
30+
- id: files
31+
run: |
32+
CHANGED_FILES="$(gh pr view --repo ${{ github.repository }} ${{ needs.check-comment.outputs.pull_number }} --json files --jq '.files.[].path')"
33+
echo "files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
34+
- run: echo "${{ steps.files.outputs.files}}"
35+
- id: author
36+
run: |
37+
AUTHOR=$(gh pr view ${ORI_PR} -R ${REPO} --json author -q '.author.login')
38+
echo "author=$AUTHOR" >> "$GITHUB_OUTPUT"
39+
- run: echo "${{ steps.author.outputs.author}}"
40+
pulls2:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- id: head_ref
44+
run: |
45+
HEAD_REF=$(gh api -H 'Accept: application/vnd.github+json' /repos/test/test/commits/${{ env.sui_sha }}/pulls --jq '.[].head.ref' | head -n 1)
46+
echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
47+
- run: echo "${{ steps.head_ref.outputs.head_ref}}"
48+
- id: title
49+
run: |
50+
TITLE=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".title")
51+
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
52+
- run: echo "${{ steps.title.outputs.title}}"
53+
- id: body
54+
run: |
55+
BODY=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".body")
56+
echo "body=$BODY" >> "$GITHUB_OUTPUT"
57+
- run: echo "${{ steps.body.outputs.body}}"
58+
- id: comments
59+
run: |
60+
COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')
61+
echo "comments=$COMMENTS" >> "$GITHUB_OUTPUT"
62+
- run: echo "${{ steps.comments.outputs.comments}}"
63+
- id: files
64+
run: |
65+
CHANGED_FILES=$(gh api /repos/test/test/pulls/${{PR_NUMBER}}/files --jq '.[].filename')
66+
echo "files=$CHANGED_FILES" >> "$GITHUB_OUTPUT"
67+
- run: echo "${{ steps.files.outputs.files}}"
68+
- id: author
69+
run: |
70+
AUTHOR=$(gh api /repos/test/test/pulls/${{PR_NUMBER}} --jq ".user.login")
71+
echo "author=$AUTHOR" >> "$GITHUB_OUTPUT"
72+
- run: echo "${{ steps.author.outputs.author}}"
73+
issues1:
74+
runs-on: ubuntu-latest
75+
steps:
76+
- id: title
77+
run: |
78+
TITLE=$(gh issue view "$ISSUE_NUMBER" --json title --jq '.title')
79+
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
80+
- run: echo "${{ steps.title.outputs.title}}"
81+
- id: body
82+
run: |
83+
BODY=$(gh issue view -R ${GITHUB_REPOSITORY} ${ORIGINAL_ISSUE_NUMBER} --json title,body --jq '.body')
84+
echo "body=$BODY" >> "$GITHUB_OUTPUT"
85+
- run: echo "${{ steps.body.outputs.body}}"
86+
- id: comments
87+
run: |
88+
COMMENTS=$(gh issue view "$ISSUE_NUMBER" --json comments --jq '.comments[].body')
89+
echo "comments=$COMMENTS" >> "$GITHUB_OUTPUT"
90+
- run: echo "${{ steps.comments.outputs.comments}}"
91+
issues2:
92+
runs-on: ubuntu-latest
93+
steps:
94+
- id: title
95+
run: |
96+
TITLE=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".title")
97+
echo "title=$TITLE" >> "$GITHUB_OUTPUT"
98+
- run: echo "${{ steps.title.outputs.title}}"
99+
- id: body
100+
run: |
101+
BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")
102+
echo "body=$BODY" >> "$GITHUB_OUTPUT"
103+
- run: echo "${{ steps.body.outputs.body}}"
104+
- id: comments
105+
run: |
106+
COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')
107+
echo "comments=$COMMENTS" >> "$GITHUB_OUTPUT"
108+
- run: echo "${{ steps.comments.outputs.comments}}"
109+
110+
111+
112+

0 commit comments

Comments
 (0)