Coordinated Disclosure Timeline
- 2024-09-13: Report sent to security@superset.apache.org
- 2024-11-20: Report sent to security@apache.org
- 2024-12-09: Fix commit
- 2025-01-29: https://github.com/apache/superset/pull/31340 merged
Summary
Apache Superset is vulnerable to a Poisoned Pipeline Execution (PPE) attack which may lead to a full compromise of the apache/superset
repository.
Project
Apache Superset
Tested Version
Latest commit at the time of reporting
Details
Poisoned Pipeline Execution (PPE) in ephemeral-env.yml
(GHSL-2024-208
)
The ephemeral-env.yml
workflow is triggered when a Pull Request gets commented.
This workflow first checks if certain secrets are available to the runner:
config:
runs-on: "ubuntu-22.04"
if: github.event.issue.pull_request
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
According to past executions, these secrets are available.
It then process the body of the comment. If the comment does not match the /^\/testenv (up|down)/
regular expression, it will return noop
. Because of this, the “Limit to committers” step does not get executed and therefore the job wont fail, enabling the execution of the following job: “ephemeral-docker-build”.
- name: Limit to committers
if: >
steps.eval-body.outputs.result != 'noop' &&
github.event.comment.author_association != 'MEMBER' &&
github.event.comment.author_association != 'OWNER'
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
const errMsg = '@${{ github.event.comment.user.login }} Ephemeral environment creation is currently limited to committers.'
github.rest.issues.createComment({
issue_number: ${{ github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: errMsg
})
core.setFailed(errMsg)
The ephemeral-docker-build
job will collect some data from the triggering Pull Request:
- name: Get Info from comment
uses: actions/github-script@v7
id: get-pr-info
with:
script: |
const request = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ github.event.issue.number }},
}
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
const pr = await github.rest.pulls.get(request);
return pr.data;
And set the Pull Request HEAD SHA to a step output variable:
- name: Debug
id: get-sha
run: |
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
The HEAD of the Pull Request gets checked-out:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses: actions/checkout@v4
with:
ref: ${{ steps.get-sha.outputs.sha }}
persist-credentials: false
Finally, the ./scripts/build_docker.py
checked-out script and, therefore, attacker controlled gets executed:
- name: Build ephemeral env image
run: |
./scripts/build_docker.py \
"ci" \
"pull_request" \
--build_context_ref ${{ github.event.issue.number }}
An attacker would be able to open a Pull Request with a malicious ./scripts/build_docker.py
and add a comment to the Pull Request to trigger the workflow and gain code execution.
Impact
This issue may lead to secret leak (AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
) and full write access to the repository.
Credit
This issue was 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-208
in any communication regarding this issue.