You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: actions/ql/src/Security/CWE-094/CodeInjectionLow.md
+33-22Lines changed: 33 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,45 +1,50 @@
1
1
## Overview
2
2
3
-
Using user-controlled input in GitHub Actions may lead to code injection in contexts like _run:_ or _script:_.
3
+
Using the output of a previous workflow step in GitHub Actions may lead to code injection in contexts like _run:_ or _script:_ if the step output can be controlled by a malicious actor. This alert does not always indicate a vulnerability, as step outputs are often derived from trusted sources and cannot be controlled by an attacker. However, if the step output originates from user-controlled data (such as issue comments, pull request titles, or commit messages), it may be exploitable.
4
4
5
-
Code injection in GitHub Actions may allow an attacker to exfiltrate any secrets used in the workflow and the temporary GitHub repository authorization token. The token may have write access to the repository, allowing an attacker to make changes to the repository.
5
+
If a step output is user-controlled, code injection in GitHub Actions may allow an attacker to exfiltrate any secrets used in the workflow and the temporary GitHub repository authorization token. The token may have write access to the repository, allowing an attacker to make changes to the repository.
6
6
7
7
## Recommendation
8
8
9
-
The best practice to avoid code injection vulnerabilities in GitHub workflows is to set the untrusted input value of the expression to an intermediate environment variable and then use the environment variable using the native syntax of the shell/script interpreter (that is, not _${{ env.VAR }}_).
9
+
First, determine whether the step output can actually be controlled by an attacker. Trace the data flow from the step that sets the output to understand where the value originates. If the output is derived from trusted sources (such as hardcoded values, repository settings, or authenticated API responses), the risk is minimal.
10
+
11
+
If the step output can be user-controlled, the best practice to avoid code injection vulnerabilities in GitHub workflows is to set the untrusted input value of the expression to an intermediate environment variable and then use the environment variable using the native syntax of the shell/script interpreter (that is, not _${{ env.VAR }}_).
10
12
11
13
It is also recommended to limit the permissions of any tokens used by a workflow such as the GITHUB_TOKEN.
12
14
13
15
## Example
14
16
15
17
### Incorrect Usage
16
18
17
-
The following example lets attackers inject an arbitrary shell command:
19
+
The following example lets attackers inject an arbitrary shell command if output `message` of the step `get-message` is derived from user-controlled data:
18
20
19
21
```yaml
20
-
on: issue_comment
21
-
22
22
jobs:
23
-
echo-body:
23
+
echo-message:
24
24
runs-on: ubuntu-latest
25
25
steps:
26
+
- id: get-message
27
+
run: |
28
+
# If this value comes from user input, it is vulnerable
29
+
echo "message=$USER_INPUT" >> $GITHUB_OUTPUT
26
30
- run: |
27
-
echo '${{ github.event.comment.body }}'
31
+
echo '${{ steps.get-message.outputs.message }}'
28
32
```
29
33
30
34
The following example uses an environment variable, but **still allows the injection** because of the use of expression syntax:
31
35
32
36
```yaml
33
-
on: issue_comment
34
-
35
37
jobs:
36
-
echo-body:
38
+
echo-message:
37
39
runs-on: ubuntu-latest
38
40
steps:
39
-
- env:
40
-
BODY: ${{ github.event.issue.body }}
41
-
run: |
42
-
echo '${{ env.BODY }}'
41
+
- id: get-message
42
+
run: |
43
+
echo "message=$USER_INPUT" >> $GITHUB_OUTPUT
44
+
- env:
45
+
MESSAGE: ${{ steps.get-message.outputs.message }}
46
+
run: |
47
+
echo '${{ env.MESSAGE }}'
43
48
```
44
49
45
50
### Correct Usage
@@ -48,28 +53,34 @@ The following example uses shell syntax to read the environment variable and wil
48
53
49
54
```yaml
50
55
jobs:
51
-
echo-body:
56
+
echo-message:
52
57
runs-on: ubuntu-latest
53
58
steps:
59
+
- id: get-message
60
+
run: |
61
+
echo "message=$USER_INPUT" >> $GITHUB_OUTPUT
54
62
- env:
55
-
BODY: ${{ github.event.issue.body }}
63
+
MESSAGE: ${{ steps.get-message.outputs.message }}
56
64
run: |
57
-
echo "$BODY"
65
+
echo "$MESSAGE"
58
66
```
59
67
60
68
The following example uses `process.env` to read environment variables within JavaScript code.
0 commit comments