Thousands of public GitHub repositories are vulnerable to malicious code injection via self-hosted GitHub Actions runners, which could lead to high-impact supply chain attacks, security researchers warn.
This new class of CI/CD attacks can be launched if a repository has self-hosted runners attached. These are “build agents hosted by end users running the Actions runner agent on their own infrastructure,” Praetorian security researcher Adnan Khan explains.
A self-hosted runner attached to a repository can be used by any workflow running in that repository’s context, and this also applies to workflows from fork pull requests, which could run malicious code, thus representing a major security risk.
“By changing a workflow file within their fork, and then creating a pull request anyone with a GitHub account can run arbitrary code on a self-hosted runner,” Khan notes.
Furthermore, the researcher warns, self-hosted runners that are set up following the default steps are persistent, meaning that a process could run in the background even after the job completes, thus opening the door to deploying a persistence mechanism.
An attacker could check for the presence of a specific GitHub action and of a message in the run logs, and if the runner’s name is repeated, to determine whether a runner is persistent or not.
According to the researcher, an attacker who discovers a repository of interest, can then check whether it has a self-hosted runner attached and use a fork pull request to become a contributor to that repository, which would then allow them to run workflows on the runner without requiring approval.
For that, the attacker could find a typo or a small code change, create a pull request for it, then wait until the pull request is merged, which would make their account a contributor to the target repository.
If the default fork pull request approval requirement is in place for the repository, only the attacker’s first request would require approval, meaning that the attacker would then be able to execute code on the runner and set up persistence without arousing suspicion.
Using this attack flow, Khan was able to gain persistent access to GitHub’s own actions/runner-images repository, which contains workflows for building Windows and MacOS runner images, allowing the researcher to poison those images.
The researcher says he had access to the repository for five days, starting July 18, 2023. He reported the issue to GitHub on July 22 and the first mitigations were deployed on July 25. GitHub handed out a $20,000 bug bounty reward for the finding.
“A skilled attacker could drop a payload that checked if the image was processing a workflow for a high-value target organization and only then run a second stage to perform a poisoned pipeline execution attack within GitHub’s build environment,” Khan notes.
Thousands of vulnerable repositories
After reporting the vulnerability to GitHub, Khan started working with his colleague John Stawinski to identify other repositories that could fall victim to the attack, and discovered thousands of them on GitHub.
The researchers limited their investigation to repositories belonging to organizations that would pay out high rewards through their bug bounty programs, and have “submitted over 20 bug bounty reports, raking in hundreds of thousands of dollars in bounties,” Stawinski says.
However, they also investigated various other means of exploiting GitHub Actions and expanded their research to other continuous integration and continuous delivery (CI/CD) platforms, including Buildkite, Jenkins, and CircleCI.
“Our targets included the world’s most advanced tech companies, often in the AI/ML or Web3 space. These companies have invested hundreds of thousands of dollars into security and sport some of the best-funded bug bounty programs. Yet, they were in the dark on these new attacks,” the researcher notes.
The researchers discovered they could compromise PyTorch and Microsoft Deepspeed releases, compromise a CloudFlare application, backdoor several blockchains, achieve remote code execution on a domain-joined Microsoft machine, and provide explicit steps to compromise TensorFlow releases.
“When we operated against PyTorch, we could have added our own malicious code to their releases on nearly all of their release platforms. […] In the hands of a nation-state, this single attack could be devastating. In fact, many of these attacks could have caused their own version of SolarWinds or the recent Ledger crypto hack,” Stawinski notes.
To mitigate this class of vulnerability, organizations are advised to change the default repository settings so that all outside contributions require approval. “It is a no-brainer for any public repository that uses self-hosted runners to ensure that they are using the restrictive setting,” Khan notes.
*The article initially stated that tens of thousands of repositories were vulnerable but was updated after the researcher told SecurityWeek they were more confident to estimate the impact to thousands of repositories.