Skip to content

Commit c676bdd

Browse files
committed
Actions: Report both workflow_call and workflow_dispatch code injection
Treat workflow_call and workflow_dispatch inputs independently for code-injection severity classification so mixed-trigger workflows can produce both low and medium alerts. Add a regression test for workflows that define both triggers and update the corresponding expected results.
1 parent c9ea8d1 commit c676bdd

File tree

5 files changed

+62
-1
lines changed

5 files changed

+62
-1
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ private predicate isWorkflowCallInput(DataFlow::Node source) {
109109
)
110110
}
111111

112+
/**
113+
* Holds if the source is an input expression that can be supplied via workflow_dispatch.
114+
*/
115+
private predicate isWorkflowDispatchInput(DataFlow::Node source) {
116+
source instanceof WorkflowDispatchInputSource
117+
}
118+
112119
/**
113120
* Holds if there is a code injection flow from `source` to `sink` with medium severity.
114121
*/
@@ -117,7 +124,7 @@ predicate mediumSeverityCodeInjection(
117124
) {
118125
CodeInjectionFlow::flowPath(source, sink) and
119126
not criticalSeverityCodeInjection(source, sink, _) and
120-
not isWorkflowCallInput(source.getNode()) and
127+
not (isWorkflowCallInput(source.getNode()) and not isWorkflowDispatchInput(source.getNode())) and
121128
not isGithubScriptUsingToJson(sink.getNode().asExpr())
122129
}
123130

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Code Injection via workflow_call and workflow_dispatch
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
title:
7+
description: "Title for the issue"
8+
required: true
9+
type: string
10+
body:
11+
description: "Body with no explicit type (defaults to string)"
12+
required: false
13+
workflow_call:
14+
inputs:
15+
title:
16+
description: "Title for the issue"
17+
required: true
18+
type: string
19+
body:
20+
description: "Body with explicit string type"
21+
required: false
22+
type: string
23+
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
build:
29+
runs-on: ubuntu-latest
30+
31+
steps:
32+
- name: vulnerable title input
33+
run: |
34+
echo "${{ inputs.title }}"
35+
36+
- name: vulnerable body input
37+
run: |
38+
echo "${{ inputs.body }}"
39+
40+
- name: safe input via env
41+
run: |
42+
echo "$title"
43+
env:
44+
title: ${{ inputs.title }}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ nodes
685685
| .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | semmle.label | inputs.title |
686686
| .github/workflows/workflow_call.yml:35:18:35:36 | inputs.count | semmle.label | inputs.count |
687687
| .github/workflows/workflow_call.yml:40:18:40:35 | inputs.flag | semmle.label | inputs.flag |
688+
| .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | semmle.label | inputs.title |
689+
| .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | semmle.label | inputs.body |
688690
| .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | semmle.label | inputs.title |
689691
| .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | semmle.label | inputs.body |
690692
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | semmle.label | github.event.workflow_run.display_title |

actions/ql/test/query-tests/Security/CWE-094/CodeInjectionLow.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ nodes
685685
| .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | semmle.label | inputs.title |
686686
| .github/workflows/workflow_call.yml:35:18:35:36 | inputs.count | semmle.label | inputs.count |
687687
| .github/workflows/workflow_call.yml:40:18:40:35 | inputs.flag | semmle.label | inputs.flag |
688+
| .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | semmle.label | inputs.title |
689+
| .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | semmle.label | inputs.body |
688690
| .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | semmle.label | inputs.title |
689691
| .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | semmle.label | inputs.body |
690692
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | semmle.label | github.event.workflow_run.display_title |
@@ -706,3 +708,5 @@ subpaths
706708
#select
707709
| .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | Potential code injection in $@, which may be controlled by a calling workflow. | .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | ${{ inputs.taint }} |
708710
| .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | Potential code injection in $@, which may be controlled by a calling workflow. | .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | ${{ inputs.title }} |
711+
| .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | Potential code injection in $@, which may be controlled by a calling workflow. | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | ${{ inputs.title }} |
712+
| .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | Potential code injection in $@, which may be controlled by a calling workflow. | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | ${{ inputs.body }} |

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ nodes
685685
| .github/workflows/workflow_call.yml:30:18:30:36 | inputs.title | semmle.label | inputs.title |
686686
| .github/workflows/workflow_call.yml:35:18:35:36 | inputs.count | semmle.label | inputs.count |
687687
| .github/workflows/workflow_call.yml:40:18:40:35 | inputs.flag | semmle.label | inputs.flag |
688+
| .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | semmle.label | inputs.title |
689+
| .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | semmle.label | inputs.body |
688690
| .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | semmle.label | inputs.title |
689691
| .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | semmle.label | inputs.body |
690692
| .github/workflows/workflow_run.yml:9:19:9:64 | github.event.workflow_run.display_title | semmle.label | github.event.workflow_run.display_title |
@@ -759,6 +761,8 @@ subpaths
759761
| .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
760762
| .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
761763
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
764+
| .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_call_and_dispatch.yml:34:18:34:36 | inputs.title | ${{ inputs.title }} |
765+
| .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_call_and_dispatch.yml:38:18:38:35 | inputs.body | ${{ inputs.body }} |
762766
| .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_dispatch.yml:36:18:36:36 | inputs.title | ${{ inputs.title }} |
763767
| .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_dispatch.yml:41:18:41:35 | inputs.body | ${{ inputs.body }} |
764768
| .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |

0 commit comments

Comments
 (0)