Skip to content

Commit 0211902

Browse files
author
Alvaro Muñoz
committed
models: add models for zentered/issue-forms-parser
1 parent d85ca10 commit 0211902

7 files changed

Lines changed: 119 additions & 0 deletions

File tree

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,20 @@ class Xt0rtedSlashCommandSource extends RemoteFlowSource {
361361
override Event getEvent() { result = this.asExpr().getATriggerEvent() }
362362
}
363363

364+
class ZenteredIssueFormBodyParserSource extends RemoteFlowSource {
365+
ZenteredIssueFormBodyParserSource() {
366+
exists(UsesStep u |
367+
u.getCallee() = "zentered/issue-forms-body-parser" and
368+
not exists(u.getArgument("body")) and
369+
this.asExpr() = u
370+
)
371+
}
372+
373+
override string getSourceType() { result = "text" }
374+
375+
override Event getEvent() { result = this.asExpr().getATriggerEvent() }
376+
}
377+
364378
class OctokitRequestActionSource extends RemoteFlowSource {
365379
OctokitRequestActionSource() {
366380
exists(UsesStep u, string route |

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,25 @@ predicate xt0rtedSlashCommandActionTaintStep(DataFlow::Node pred, DataFlow::Node
9191
)
9292
}
9393

94+
/**
95+
* A read of user-controlled field of the zentered/issue-forms-body-parser action.
96+
*/
97+
predicate zenteredIssueFormBodyParserSource(DataFlow::Node pred, DataFlow::Node succ) {
98+
exists(StepsExpression o |
99+
pred instanceof ZenteredIssueFormBodyParserSource and
100+
o.getTarget() = pred.asExpr() and
101+
o.getStepId() = pred.asExpr().(UsesStep).getId() and
102+
(
103+
not o instanceof JsonReferenceExpression and
104+
o.getFieldName() = "data"
105+
or
106+
o instanceof JsonReferenceExpression and
107+
o.(JsonReferenceExpression).getInnerExpression().matches("%.data")
108+
) and
109+
succ.asExpr() = o
110+
)
111+
}
112+
94113
/**
95114
* A read of user-controlled field of the octokit/request-action action.
96115
*/
@@ -130,6 +149,8 @@ class TaintSteps extends AdditionalTaintStep {
130149
tjActionsChangedFilesTaintStep(node1, node2) or
131150
tjActionsVerifyChangedFilesTaintStep(node1, node2) or
132151
xt0rtedSlashCommandActionTaintStep(node1, node2) or
152+
xt0rtedSlashCommandActionTaintStep(node1, node2) or
153+
zenteredIssueFormBodyParserSource(node1, node2) or
133154
octokitRequestActionTaintStep(node1, node2)
134155
}
135156
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extensions:
2+
- addsTo:
3+
pack: github/actions-all
4+
extensible: actionsSummaryModel
5+
data:
6+
- ["zentered/issue-forms-body-parser", "*", "input.body", "output.data", "taint", "manual"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Issue Forms Body Parser
2+
3+
on: issues
4+
5+
jobs:
6+
process:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- name: Issue Forms Body Parser
10+
id: parse
11+
uses: zentered/issue-forms-body-parser@v2.0.0
12+
- run: echo ${{ steps.parse.outputs.data }}
13+
- run: echo ${{ toJSON(steps.parse.outputs.data) }}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Issue Forms Body Parser
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
issue_number:
7+
type: string
8+
description: issue number
9+
required: true
10+
env:
11+
GH_TOKEN: ${{ github.token }}
12+
13+
jobs:
14+
process:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Fetch the issue
18+
id: read_issue_body
19+
run:
20+
echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT
21+
22+
- name: Issue Forms Body Parser
23+
id: parse
24+
uses: zentered/issue-forms-body-parser@v2.0.0
25+
with:
26+
body: ${{ steps.read_issue_body.outputs.body }}
27+
28+
- run: echo ${{ steps.parse.outputs.data }}
29+
- run: echo ${{ toJSON(steps.parse.outputs.data) }}

ql/test/query-tests/Security/CWE-094/CodeInjectionCritical.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ edges
199199
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | provenance | |
200200
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | provenance | |
201201
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | provenance | |
202+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | provenance | |
203+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | provenance | |
204+
| .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | provenance | |
205+
| .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | provenance | |
206+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | provenance | |
207+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | provenance | |
208+
| .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | provenance | |
202209
| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | provenance | |
203210
| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | provenance | |
204211
| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | provenance | |
@@ -586,6 +593,15 @@ nodes
586593
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
587594
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | semmle.label | Uses Step: parse |
588595
| .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | semmle.label | steps.parse.outputs.payload |
596+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | semmle.label | Uses Step: parse |
597+
| .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | semmle.label | steps.parse.outputs.data |
598+
| .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | semmle.label | toJSON(steps.parse.outputs.data) |
599+
| .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | semmle.label | Run Step: read_issue_body [body] |
600+
| .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | semmle.label | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT |
601+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | semmle.label | Uses Step: parse [data] |
602+
| .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | semmle.label | steps.read_issue_body.outputs.body |
603+
| .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | semmle.label | steps.parse.outputs.data |
604+
| .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | semmle.label | toJSON(steps.parse.outputs.data) |
589605
| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
590606
| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 |
591607
| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] |
@@ -764,6 +780,10 @@ subpaths
764780
| .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | .github/workflows/test19.yml:100:14:102:48 | BODY=$(gh api /repos/test/test/issues/${{PR_NUMBER}} --jq ".body")\necho "body=$BODY" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:103:21:103:49 | steps.body.outputs.body | ${{ steps.body.outputs.body}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
765781
| .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | ${{ steps.comments.outputs.comments}} | .github/workflows/test19.yml:4:3:4:21 | pull_request_target | pull_request_target |
766782
| .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | ${{ steps.parse.outputs.payload }} | .github/workflows/test24.yml:2:3:2:8 | issues | issues |
783+
| .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | ${{ steps.parse.outputs.data }} | .github/workflows/test25.yml:3:5:3:10 | issues | issues |
784+
| .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | ${{ toJSON(steps.parse.outputs.data) }} | .github/workflows/test25.yml:3:5:3:10 | issues | issues |
785+
| .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | ${{ steps.parse.outputs.data }} | .github/workflows/test26.yml:4:3:4:19 | workflow_dispatch | workflow_dispatch |
786+
| .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | ${{ toJSON(steps.parse.outputs.data) }} | .github/workflows/test26.yml:4:3:4:19 | workflow_dispatch | workflow_dispatch |
767787
| .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | .github/workflows/test.yml:20:20:20:62 | github.event['pull_request']['body'] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | ${{needs.job1.outputs['job_output']}} | .github/workflows/test.yml:2:3:2:21 | pull_request_target | pull_request_target |
768788
| .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | .github/workflows/untrusted_checkout1.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/untrusted_checkout1.yml:15:20:15:58 | steps.artifact.outputs.pr_number | ${{ steps.artifact.outputs.pr_number }} | .github/workflows/untrusted_checkout1.yml:2:3:2:21 | pull_request_target | pull_request_target |
769789
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | Potential code injection in $@, which may be controlled by an external user ($@). | .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | ${{ github.event.workflow_run.display_title }} | .github/workflows/workflow_run.yml:2:3:2:14 | workflow_run | workflow_run |

ql/test/query-tests/Security/CWE-094/CodeInjectionMedium.expected

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ edges
199199
| .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | .github/workflows/test19.yml:108:21:108:57 | steps.comments.outputs.comments | provenance | |
200200
| .github/workflows/test19.yml:105:14:107:56 | COMMENTS=$(gh api /repos/test/test/pulls/${PR_NUMBER}/comments --jq '.[].body')\necho "comments=$COMMENTS" >> "$GITHUB_OUTPUT"\n | .github/workflows/test19.yml:104:9:108:6 | Run Step: comments [comments] | provenance | |
201201
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | provenance | |
202+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | provenance | |
203+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | provenance | |
204+
| .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | provenance | |
205+
| .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | provenance | |
206+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | provenance | |
207+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | provenance | |
208+
| .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | provenance | |
202209
| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | .github/workflows/test.yml:52:20:52:56 | needs.job1.outputs['job_output'] | provenance | |
203210
| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | provenance | |
204211
| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | .github/workflows/test.yml:25:18:25:48 | steps.step0.outputs.value | provenance | |
@@ -586,6 +593,15 @@ nodes
586593
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
587594
| .github/workflows/test24.yml:8:9:17:6 | Uses Step: parse | semmle.label | Uses Step: parse |
588595
| .github/workflows/test24.yml:19:17:19:50 | steps.parse.outputs.payload | semmle.label | steps.parse.outputs.payload |
596+
| .github/workflows/test25.yml:9:9:12:6 | Uses Step: parse | semmle.label | Uses Step: parse |
597+
| .github/workflows/test25.yml:12:20:12:50 | steps.parse.outputs.data | semmle.label | steps.parse.outputs.data |
598+
| .github/workflows/test25.yml:13:20:13:58 | toJSON(steps.parse.outputs.data) | semmle.label | toJSON(steps.parse.outputs.data) |
599+
| .github/workflows/test26.yml:17:9:22:6 | Run Step: read_issue_body [body] | semmle.label | Run Step: read_issue_body [body] |
600+
| .github/workflows/test26.yml:20:11:20:140 | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT | semmle.label | echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{ github.repository }} --json body --jq '.body')" >> $GITHUB_OUTPUT |
601+
| .github/workflows/test26.yml:22:9:28:6 | Uses Step: parse [data] | semmle.label | Uses Step: parse [data] |
602+
| .github/workflows/test26.yml:26:18:26:58 | steps.read_issue_body.outputs.body | semmle.label | steps.read_issue_body.outputs.body |
603+
| .github/workflows/test26.yml:28:20:28:50 | steps.parse.outputs.data | semmle.label | steps.parse.outputs.data |
604+
| .github/workflows/test26.yml:29:20:29:58 | toJSON(steps.parse.outputs.data) | semmle.label | toJSON(steps.parse.outputs.data) |
589605
| .github/workflows/test.yml:11:7:13:4 | Job outputs node [job_output] | semmle.label | Job outputs node [job_output] |
590606
| .github/workflows/test.yml:11:20:11:50 | steps.step5.outputs.MSG5 | semmle.label | steps.step5.outputs.MSG5 |
591607
| .github/workflows/test.yml:17:9:23:6 | Uses Step: step0 [value] | semmle.label | Uses Step: step0 [value] |

0 commit comments

Comments
 (0)