Skip to content

Commit

Permalink
feat: mitigating script injection attacks by passing issue body as en…
Browse files Browse the repository at this point in the history
…v var (#42)

BREAKING CHANGE: Add `issue-body` argument which is required from v3 onwards

To mitigate script injection attacks, github-issue-parser v3 will require workflow authors to pass the issue body as an argument. By doing so you will follow GitHub's [Good practices for mitigating script injection attacks
](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#good-practices-for-mitigating-script-injection-attacks)

```yml
- uses: stefanbuck/github-issue-parser@v3
  id: issue-parser
  with:
    issue-body: ${{ github.event.issue.body }} # required
    template-path: .github/ISSUE_TEMPLATE/bug-report.yml # optional but recommended
```
  • Loading branch information
stefanbuck committed Oct 19, 2022
1 parent 1d341cb commit 0b27d4a
Show file tree
Hide file tree
Showing 16 changed files with 3,731 additions and 167 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
git config user.email github-actions@github.com
git add .gitignore dist/
git commit -m "build"
git push --force https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v2
git push --force https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: npx semantic-release
Expand Down
100 changes: 41 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,104 +7,86 @@ Use this action to convert issues into a unified JSON structure. Read the [Codel
## Setup

```yml
- uses: stefanbuck/github-issue-parser@v2
- uses: stefanbuck/github-issue-parser@v3
id: issue-parser
with:
template-path: .github/ISSUE_TEMPLATE/bug-report.yml
issue-body: ${{ github.event.issue.body }} # required
template-path: .github/ISSUE_TEMPLATE/bug-report.yml # optional but recommended

- run: echo '${{ steps.issue-parser.outputs.jsonString }}' > bug-details.json
- run: cat ${HOME}/issue-parser-result.json

- run: echo '${{ steps.issue-parser.outputs.issueparser_your_contact_details }}'
- run: echo $FAVORITE_DISH
env:
FAVORITE_DISH: ${{ steps.issue-parser.outputs.issueparser_favorite_dish }}
```

`template-path` is optional and meant to be used with Issue Forms.

## Example

Given an issue form

```yml
name: Bug
description: Something is broken

title: "Order Pizza"

body:
- type: input
id: contact
attributes:
label: Your contact details
validations:
required: true

- type: input
id: what_happened
attributes:
label: What happened?
validations:
required: true

- type: input
id: version
attributes:
label: Version
validations:
required: true

- type: input
id: browsers
id: favorite_dish
attributes:
label: What browsers are you seeing the problem on?
label: What's your favorite dish?
validations:
required: true

- type: checkboxes
id: what_else
id: favorite_color
attributes:
label: What else?
label: What's your preferred color?
options:
- label: Never give up
- label: Hot Dog is a Sandwich
- label: Red
- label: Green
- label: Blue
```

And an issue body

```md
### Your contact details
### What's your favorite dish?

me@me.com
Pizza

### What happened?
### What's your preferred color?

A bug happened!
- [x] Red
- [ ] Green
- [x] Blue
```

### Version
The actions output will be

1.0.0
```json
{
"favorite_dish": "Pizza",
"favorite_color": ["Red", "Blue"]
}
```

## Action outputs

### What browsers are you seeing the problem on?
- `jsonString` - The entire output
- `issueparser_<field_id>` - Access individual values

Chrome, Safari

### What else?
Please take a look at GitHub's [Good practices for mitigating script injection attacks](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#good-practices-for-mitigating-script-injection-attacks) when using inline scripts. The examples blow are safe because they use intermediate environment variable as suggested by GitHub.

- [x] Never give up
- [ ] Hot Dog is a Sandwich
```yaml
- run: echo $JSON_STRING > output.json
env:
JSON_STRING: ${{ steps.issue-parser.outputs.jsonString }}
```

The actions output will be

```json
{
"contact": "me@me.com",
"what_happened": "A bug happened!",
"version": "1.0.0",
"browsers": "Chrome, Safari",
"what_else": ["Never give up"]
}
```yaml
- run: echo $FAV_DISH
env:
FAV_DISH: ${{ steps.issue-parser.outputs.issueparser_favorite_dish }}
```


Want to learn more about this concept? Check out the [Codeless Contributions with GitHub Issue Forms](https://stefanbuck.com/blog/codeless-contributions-with-github-issue-forms) post on my blog.


Expand Down
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ branding:
inputs:
template-path:
description: 'Path to the issue form template file'
issue-body:
required: true
description: 'Issue body to parse'
outputs:
jsonString:
description: 'JSON string'
runs:
using: 'node12'
using: 'node16'
main: 'dist/index.js'
5 changes: 0 additions & 5 deletions fixtures/blank/issue.js

This file was deleted.

9 changes: 9 additions & 0 deletions fixtures/full-example/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"contact": "me@me.com",
"what_happened": "A bug happened!",
"version": "1.0.0",
"browsers": "Chrome, Safari",
"anything_else": ["Never give up"],
"second_anything_else": ["Hot Dog is a Sandwich", "Another item"],
"checkbox_without_an_id": []
}
52 changes: 52 additions & 0 deletions fixtures/full-example/form.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
body:
- type: input
id: contact
attributes:
label: Your contact details
validations:
required: true

- type: input
id: what_happened
attributes:
label: What happened?
validations:
required: true

- type: input
id: version
attributes:
label: Version
validations:
required: true

- type: input
id: browsers
attributes:
label: What browsers are you seeing the problem on?
validations:
required: true

- type: checkboxes
id: anything_else
attributes:
label: What else?
options:
- label: Never give up
- label: Hot Dog is a Sandwich

- type: checkboxes
id: second_anything_else
attributes:
label: And with that?
options:
- label: Never give up
- label: Hot Dog is a Sandwich
- label: Another item

- type: checkboxes
attributes:
label: Checkbox without an id?
options:
- label: IDs are great
- label: IDs are bad
31 changes: 31 additions & 0 deletions fixtures/full-example/issue-body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
### Your contact details

me@me.com

### What happened?

A bug happened!

### Version

1.0.0

### What browsers are you seeing the problem on?

Chrome, Safari

### What else?

- [x] Never give up
- [ ] Hot Dog is a Sandwich

### And with that?

- [] Never give up
- [X] Hot Dog is a Sandwich
- [x] Another item

### Checkbox without an id?

- [ ] IDs are great
- [ ] IDs are bad
6 changes: 6 additions & 0 deletions fixtures/full-example/issue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const { resolve } = require("path");
const { readFileSync } = require("fs");

const issueBodyPath = resolve(__dirname, "issue-body.md");

module.exports = readFileSync(issueBodyPath, "utf-8");
6 changes: 1 addition & 5 deletions fixtures/multiple-paragraphs/issue.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,4 @@ const { readFileSync } = require("fs");

const issueBodyPath = resolve(__dirname, "issue-body.md");

module.exports = {
issue: {
body: readFileSync(issueBodyPath, "utf-8"),
},
};
module.exports = readFileSync(issueBodyPath, "utf-8")
9 changes: 2 additions & 7 deletions fixtures/readme-example/expected.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{
"contact": "me@me.com",
"what_happened": "A bug happened!",
"version": "1.0.0",
"browsers": "Chrome, Safari",
"anything_else": ["Never give up"],
"second_anything_else": ["Hot Dog is a Sandwich", "Another item"],
"checkbox_without_an_id": []
"favorite_dish": "Pizza",
"favorite_color": ["Red", "Blue"]
}
55 changes: 7 additions & 48 deletions fixtures/readme-example/form.yml
Original file line number Diff line number Diff line change
@@ -1,57 +1,16 @@
name: Bug
description: Something is broken

title: "Order Pizza"

body:
- type: input
id: contact
attributes:
label: Your contact details
validations:
required: true

- type: input
id: what_happened
id: favorite_dish
attributes:
label: What happened?
label: What's your favorite dish?
validations:
required: true

- type: input
id: version
attributes:
label: Version
validations:
required: true

- type: input
id: browsers
attributes:
label: What browsers are you seeing the problem on?
validations:
required: true

- type: checkboxes
id: anything_else
attributes:
label: What else?
options:
- label: Never give up
- label: Hot Dog is a Sandwich

- type: checkboxes
id: second_anything_else
attributes:
label: And with that?
options:
- label: Never give up
- label: Hot Dog is a Sandwich
- label: Another item

- type: checkboxes
id: favorite_color
attributes:
label: Checkbox without an id?
label: What's your preferred color?
options:
- label: IDs are great
- label: IDs are bad
- label: Red
- label: Green
- label: Blue
Loading

0 comments on commit 0b27d4a

Please sign in to comment.