Skip to content

Commit 3bd5f5f

Browse files
committed
describe safe function calls are ignored on untrusted inputs check
1 parent 9e16139 commit 3bd5f5f

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

docs/checks.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,9 @@ jobs:
10151015
- name: Get comments
10161016
# ERROR: Accessing untrusted inputs via `.*` object filter; bodies of comment, review, and review_comment
10171017
run: echo '${{ toJSON(github.event.*.body) }}'
1018+
- name: Do something with checking skip
1019+
# OK: This placeholder uses an untrusted input, but the input cannot be injected to the script
1020+
run: if [ "${{ contains(github.event.pull_request.author.title, '[SKIP]') }}" = "true" ]; then echo "skip"; fi
10181021
```
10191022
10201023
Output:
@@ -1034,7 +1037,7 @@ test.yaml:22:31: object filter extracts potentially untrusted properties "github
10341037
| ^~~~~~~~~~~~~~~~~~~~
10351038
```
10361039
1037-
[Playground](https://rhysd.github.io/actionlint/#eNqEkUFLAzEQhe/9FXMQ2gqJRzGnXkRQaAV7L9l06EazmTUzaZGy/12yW5aqLJ5CMm++93iJtkEDW2SZUTTQ5hB2CT9zeZi9U8VmBiDIUk6AlCOrIsxVjpJVsGXWj1iw5UEFoGAAvyYfpafChQriJeBF1gMNoKsJ5jfnMxy81LnSeMQo+jqM7teg6+ajQ2ZkA9aJp8h3LDbg6vgwkk9eajPeABK2pIQ+MBooVowuobDebl4e19B1V9KepdqkGmS2BxwW/s8GJ8vgAjHuJ1IODMUu+VZWx/vJtIPCgKPIFFAHOiz+NlSj3e8cNY0XbbPUlHTpvdS0/PUTTyhQlBiFp9oXen7brBc/LG51RfuvZUF+BwAA///RHa9N)
1040+
[Playground](https://rhysd.github.io/actionlint/#eNqEkUFr20AQhe/+FQ9RsFMq9Vi6oZBDS2kDSSC5hRDW64l369WOujPrUIL/e1nJmLjF5CRG8+Z7T0/J9mRwR6IzTgZDifEx0+9SX8x+8VLMDFASrU8glyRtFZZlSVraaOtuXInSIJMKaDGBb3JIOlKxp0KDRtrLRqABOc+Yv3t5wTqoL8uOtpS0ex2mG8+w280PDkVIDKzTwEk+itpIF9vPB/JzUG8OE5Bp4FZ5Q8mgWgm5TCrd3fXltyvsdq+kI6sdctuTiF3TdPB2NjxbgYsstDqRcmK04nIY9GL76WTaSWHgOAlH6iKvF/835MmuHh33fdDOFvWcu9p7rensnz/xnRRVSUnlVPvKP2+vrxZHFu+7Ja/+nB01PxG/MoR7Uh/SeswP58lt6iSbMBybhCfco6kmjpPakGRxus/9p4y1fsD8/vbyx83DvGZo8AWN5kINHs6hntIUv6mOzTmewt8AAAD//6j/5EY=)
10381041
10391042
Since `${{ }}` placeholders are evaluated and replaced directly by GitHub Actions runtime, you need to use them carefully in
10401043
inline scripts at `run:`. For example, if we have step as follows,
@@ -1093,6 +1096,13 @@ Instead, you should store the JSON string in an environment variable:
10931096
BODIES: '${{ toJSON(github.event.*.body) }}'
10941097
```
10951098

1099+
The following functions return a boolean value so it is not possible to inject anything as the result of the returned value.
1100+
actionlint does not report an error even if untrusted inputs are passed to these function calls.
1101+
1102+
- `contains()`
1103+
- `startswith()`
1104+
- `endswith()`
1105+
10961106
At last, the popular action [actions/github-script][github-script] has the same issue in its `script` input. actionlint also
10971107
checks the input.
10981108

expr_insecure_test.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,25 @@ func TestExprInsecureDetectUntrustedValue(t *testing.T) {
211211
"github.event.",
212212
},
213213
},
214+
testCase{
215+
"contains(github.event.issue.body, 'foo') || github.event.issue.title",
216+
[]string{
217+
"github.event.issue.title",
218+
},
219+
},
220+
testCase{
221+
"github.event.issue.title && contains(github.event.issue.body, 'foo')",
222+
[]string{
223+
"github.event.issue.title",
224+
},
225+
},
226+
testCase{
227+
"format('{0}{1}{2}', github.event.issue.title, contains(github.event.issue.body, 'foo'), github.event.issue.title)",
228+
[]string{
229+
"github.event.issue.title",
230+
"github.event.issue.title",
231+
},
232+
},
214233
)
215234

216235
for _, tc := range tests {
@@ -297,6 +316,7 @@ func TestExprInsecureNoUntrustedValue(t *testing.T) {
297316
"matrix.github.event.issue.title",
298317
"matrix.event.issue.title",
299318
"github",
319+
"github.event",
300320
"github.event.issue",
301321
"github.event.commits.foo.message",
302322
"github.event.commits[0]",
@@ -315,14 +335,12 @@ func TestExprInsecureNoUntrustedValue(t *testing.T) {
315335
"matrix.foo[github.event.pages].page_name",
316336
"github.event.issue.body.foo.bar",
317337
"github.event.issue.body[0]",
318-
319-
"contains(github.event.issue.title, 'bug')",
320338
"contains(github.event.issue.body, github.event.issue.title)",
321339
"startsWith(github.event.comment.body, 'LGTM')",
322340
"endsWith(github.event.pull_request.title, github.event.issue.title)",
323-
"contains(github.event.*.body, 'sensitive')",
324-
"startsWith(github.event.*.body[0], 'Important')",
325-
"endsWith(github.event.commits[0].message, github.event.pull_request.title)",
341+
"contains(contains(github.event.issue.body, github.event.issue.title), github.event.issue.title)", // safe -> safe
342+
"contains(fromJSON(github.event.issue.body), github.event.issue.title)", // safe -> unsafe
343+
"fromJSON(contains(github.event.issue.body, github.event.issue.title))", // unsafe -> safe
326344
}
327345

328346
for _, input := range inputs {

testdata/examples/untrusted_input.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ jobs:
2020
- name: Get comments
2121
# ERROR: Accessing untrusted inputs via `.*` object filter; bodies of comment, review, and review_comment
2222
run: echo '${{ toJSON(github.event.*.body) }}'
23+
- name: Do something with checking skip
24+
# OK: This placeholder uses an untrusted input, but the input cannot be injected to the script
25+
run: if [ "${{ contains(github.event.pull_request.author.title, '[SKIP]') }}" = "true" ]; then echo "skip"; fi

0 commit comments

Comments
 (0)