Coordinated Disclosure Timeline
- 2024-10-29: Reported to Eclipse Security Team via Issue tracker.
- 2024-11-02: Fix merged.
Summary
Multiple Eclipse repositories are vulnerable to Poisoned Pipeline Execution (PPE) via Code Injection allowing a malicious actor to exfiltrate the Eclipse’s Personal Access Token with organization write permission.
Project
Eclipse JDT, Eclipse Platform, Eclipse Platform UI, Eclipse PDE, Eclipse Equinox P2 and Eclipse-JDTLS
Tested Version
Latest commit at the time of reporting.
Details
The following repositories have worflows manifesting the same Vulnerability. The following report focuses on the Eclipse JDT ones but they apply to:
Issue 1: Code Injection via PR branch name in publishVersionCheckResults.yml
(GHSL-2024-320
)
The version-increments.yml
workflow present in the eclipse-jdt/eclipse.jdt.core
, eclipse-jdt/eclipse.jdt.ui
, and eclipse-jdt/eclipse.jdt.debug
repositories get executed when the Pull-Request Checks
workflow completes:
name: Publish Version Check Results
on:
workflow_run:
workflows: ["Pull-Request Checks"]
types: [completed]
It then calls the publishVersionCheckResults.yml
reusable workflow from the eclipse-platform/eclipse.platform.releng.aggregator
repository and passes the JDT_BOT_PAT
secret to it:
jobs:
publish-version-check-results:
uses: eclipse-platform/eclipse.platform.releng.aggregator/.github/workflows/publishVersionCheckResults.yml@master
with:
botGithubId: eclipse-jdt-bot
secrets:
githubBotPAT: ${{ secrets.JDT_BOT_PAT }}
The publishVersionCheckResults.yml
workflow will check if an artifact called versions-git-patch
is available from the triggering workflow:
- name: Search version increment git patch
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: search-patch
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
run_id: context.payload.workflow_run.id,
...context.repo
})
let artifact = allArtifacts.data.artifacts.find(artifact => artifact.name == 'versions-git-patch')
return artifact?.id
If it exists, it will checkout the code of the triggering Pull request, download the artifact and create a patch to apply to the Pull Request origin repository:
- name: Apply and push version increment
id: git-commit
if: steps.search-patch.outputs.result
run: |
set -x
# Set initial placeholder name/mail and read it from the patch later
git config --global user.email 'foo@bar'
git config --global user.name 'Foo Bar'
git am version_increments.patch
# Read the author's name+mail from the just applied patch and recommit it with both set as committer
botMail=$(git log -1 --pretty=format:'%ae')
botName=$(git log -1 --pretty=format:'%an')
git config --global user.email "${botMail}"
git config --global user.name "${botName}"
git commit --amend --no-edit
fileList=$(git diff-tree --no-commit-id --name-only HEAD -r)
echo "file-list<<EOF" >> $GITHUB_OUTPUT
echo "$fileList" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
git push \
"https://oauth2:${BOT_PA_TOKEN}@github.com/${{ github.event.workflow_run.head_repository.full_name }}.git" \
'HEAD:refs/heads/${{ github.event.workflow_run.head_branch }}'
In the last line, the attacker-controlled Pull Request branch name gets interpolated in the bash code. Since branch names can contain backticks and dollar symbols, it is possible for an attacker to create a Pull Request from a branch called foo`CMD$IFSARG1$IFSARG2`bar
which will run the CMD ARG1 ARG2
command, allowing the attacker to run arbitrary commands on the GitHub runner and exfiltrate the JDT_BOT_PAT
by dumping the runner’s memory.
Impact
This issue may lead to the exfiltration of the JDT_BOT_PAT
Personal Access Token. Since this PAT is used in three different repositories, it seems like its a token defined at the organization level and that could have write access at the org level.
Issue 2: Code Injection via PR changed file names in publishVersionCheckResults.yml
(GHSL-2024-321
)
The publishVersionCheckResults.yml
workflow checks outs untrusted code from the triggering Pull Request:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
if: steps.search-patch.outputs.result
with:
ref: "${{ github.event.workflow_run.head_sha }}"
persist-credentials: false #Opt out from persisting the default Github-token authentication in order to enable use of the bot's PAT when pushing below
Since an attacker can upload the version_increments.patch
file, they will be able to control the file list returned by the git diff-tree
command:
set -x
# Set initial placeholder name/mail and read it from the patch later
git config --global user.email 'foo@bar'
git config --global user.name 'Foo Bar'
git am version_increments.patch
# Read the author's name+mail from the just applied patch and recommit it with both set as committer
botMail=$(git log -1 --pretty=format:'%ae')
botName=$(git log -1 --pretty=format:'%an')
git config --global user.email "${botMail}"
git config --global user.name "${botName}"
git commit --amend --no-edit
fileList=$(git diff-tree --no-commit-id --name-only HEAD -r)
echo "file-list<<EOF" >> $GITHUB_OUTPUT
echo "$fileList" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
This list of attacker-controlled names is assigned to the steps.git-commit.outputs.file-list
output variable and later interpolated into a JS script allowing an attacker to gain arbitrary code execution:
- name: Add or update information comment
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
if: always()
with:
github-token: ${{ secrets.githubBotPAT }}
script: |
const fs = require('fs')
const fileList = `${{ steps.git-commit.outputs.file-list }}`
if (fileList) { // if list is empty, no versions were changed
Impact
This issue may lead to the exfiltration of the JDT_BOT_PAT
Personal Access Token. Since this PAT is used in three different repositories, it seems like its a token defined at the organization level and that could have write access at the org level.
Credit
These issues were discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-320
or GHSL-2024-321
in any communication regarding these issues.